diff --git a/Net/Demos/CrossHttpConsole/uDM.pas b/Net/Demos/CrossHttpConsole/uDM.pas index d3d08bd..5a9298c 100644 --- a/Net/Demos/CrossHttpConsole/uDM.pas +++ b/Net/Demos/CrossHttpConsole/uDM.pas @@ -5,12 +5,14 @@ interface uses {$IFDEF __CROSS_SSL__} Net.CrossSslSocket, - {$IFDEF POSIX} Net.CrossSslDemoCert, {$ENDIF} - {$ENDIF} System.SysUtils, System.Classes, System.Generics.Collections, - Net.CrossSocket.Base, Net.CrossSocket, Net.CrossHttpServer, Net.CrossHttpMiddleware; + Net.CrossSocket.Base, + Net.CrossSocket, + Net.CrossHttpServer, + Net.CrossHttpMiddleware, + Net.CrossHttpUtils; type IProgress = interface @@ -200,17 +202,14 @@ procedure TDM.DataModuleCreate(Sender: TObject); begin FHttpServer := TCrossHttpServer.Create(0); {$IFDEF __CROSS_SSL__} - {$IFDEF POSIX} FHttpServer.SetCertificate(SSL_SERVER_CERT); FHttpServer.SetPrivateKey(SSL_SERVER_PKEY); - {$ELSE} - FHttpServer.SetCertificateFile('server.crt'); - FHttpServer.SetPrivateKeyFile('server.key'); - {$ENDIF} {$ENDIF} - FHttpServer.Addr := IPv4_ALL; // IPv4 +// FHttpServer.Addr := IPv4_ALL; // IPv4 +// FHttpServer.Addr := IPv6_ALL; // IPv6 + FHttpServer.Addr := IPv4v6_ALL; // IPv4v6 FHttpServer.Port := AppCfg.ListenPort; - FHttpServer.Compressible := False; + FHttpServer.Compressible := True; FHttpServer.OnConnected := _OnConnected; FHttpServer.OnDisconnected := _OnDisconnected; @@ -277,15 +276,15 @@ procedure TDM._CreateRouter; ; FHttpServer - .Get('/null', + .Get('/hello', procedure(ARequest: ICrossHttpRequest; AResponse: ICrossHttpResponse) begin - AResponse.Send(''); + AResponse.Send('Hello World'); end) - .Get('/hello', + .Get('/null', procedure(ARequest: ICrossHttpRequest; AResponse: ICrossHttpResponse) begin - AResponse.Send('Hello World'); + AResponse.Send(''); end) .Get('/yeah', procedure(ARequest: ICrossHttpRequest; AResponse: ICrossHttpResponse) @@ -348,6 +347,55 @@ procedure TDM._CreateRouter; LWatch.Stop; end); end) + .Dir('/static', 'D:\') + .Dir('/g', 'G:\') + .Get('/file', + procedure(ARequest: ICrossHttpRequest; AResponse: ICrossHttpResponse) + var + LStream: TStream; + begin + LStream := TFile.OpenRead('d:\2.txt'); + AResponse.ContentType := TMediaType.TEXT_HTML; + AResponse.SendNoCompress(LStream, + StrToInt64Def(ARequest.Query['pos'], 0), + StrToInt64Def(ARequest.Query['count'], 0), + procedure(AConnection: ICrossConnection; ASuccess: Boolean) + begin + FreeAndNil(LStream); + end); + end) + .Get('/stream', + procedure(ARequest: ICrossHttpRequest; AResponse: ICrossHttpResponse) + var + LStream: TMemoryStream; + begin + LStream := TMemoryStream.Create; + LStream.LoadFromFile('d:\2.txt'); + AResponse.ContentType := TMediaType.TEXT_HTML; + AResponse.SendZCompress(LStream, + StrToInt64Def(ARequest.Query['pos'], 0), + StrToInt64Def(ARequest.Query['count'], 0), + TCompressType.ctGZip, + procedure(AConnection: ICrossConnection; ASuccess: Boolean) + begin + FreeAndNil(LStream); + end); + end) + .Get('/bytes', + procedure(ARequest: ICrossHttpRequest; AResponse: ICrossHttpResponse) + var + LBytes: TBytes; + begin + LBytes := TFile.ReadAllBytes('d:\2.txt'); + AResponse.ContentType := TMediaType.TEXT_HTML; + AResponse.SendNoCompress(LBytes, + StrToInt64Def(ARequest.Query['pos'], 0), + StrToInt64Def(ARequest.Query['count'], 0), + procedure(AConnection: ICrossConnection; ASuccess: Boolean) + begin + LBytes := nil; + end); + end) ; for I := 0 to AppCfg.DirMaps.Count - 1 do diff --git a/Net/Demos/TestCrossSocket/TestCrossSocket.dproj b/Net/Demos/TestCrossSocket/TestCrossSocket.dproj index 310b429..dde5c7d 100644 --- a/Net/Demos/TestCrossSocket/TestCrossSocket.dproj +++ b/Net/Demos/TestCrossSocket/TestCrossSocket.dproj @@ -1,11 +1,11 @@  {483A6D14-7DE6-4EEC-9995-E68E10B0F2C9} - 18.2 + 18.5 FMX TestCrossSocket.dpr True - Debug + Release Win32 1247 Application @@ -175,7 +175,7 @@ $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_100x100.png $(MSBuildProjectName) $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png - CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone & iPad;CFBundleResourceSpecification=ResourceRules.plist;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;FMLocalNotificationPermission=false;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSCameraUsageDescription=The reason for accessing the camera + CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone & iPad;CFBundleResourceSpecification=ResourceRules.plist;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;FMLocalNotificationPermission=false;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSCameraUsageDescription=The reason for accessing the camera;CFBundleShortVersionString=1.0.0;NSPhotoLibraryAddUsageDescription=The reason for adding to the photo library;NSFaceIDUsageDescription=The reason for accessing the face id;NSLocationAlwaysAndWhenInUseUsageDescription=The reason for accessing the location information of the user;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSSiriUsageDescription=The reason for accessing Siri $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_180x180.png @@ -186,6 +186,8 @@ $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_58x58.png true $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_29x29.png + $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_1125x2436.png + $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_2436x1125.png $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_640x960.png @@ -217,7 +219,7 @@ $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_100x100.png $(MSBuildProjectName) $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png - CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone & iPad;CFBundleResourceSpecification=ResourceRules.plist;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;FMLocalNotificationPermission=false;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSCameraUsageDescription=The reason for accessing the camera + CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone & iPad;CFBundleResourceSpecification=ResourceRules.plist;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;FMLocalNotificationPermission=false;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSCameraUsageDescription=The reason for accessing the camera;CFBundleShortVersionString=1.0.0;NSPhotoLibraryAddUsageDescription=The reason for adding to the photo library;NSFaceIDUsageDescription=The reason for accessing the face id;NSLocationAlwaysAndWhenInUseUsageDescription=The reason for accessing the location information of the user;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSSiriUsageDescription=The reason for accessing Siri $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_180x180.png @@ -228,6 +230,8 @@ $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_58x58.png true $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_29x29.png + $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_1125x2436.png + $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_2436x1125.png $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_320x480.png @@ -257,7 +261,7 @@ iPhoneAndiPad $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_100x100.png $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png - CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone & iPad;CFBundleResourceSpecification=ResourceRules.plist;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;FMLocalNotificationPermission=false;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSCameraUsageDescription=The reason for accessing the camera + CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone & iPad;CFBundleResourceSpecification=ResourceRules.plist;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;FMLocalNotificationPermission=false;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSCameraUsageDescription=The reason for accessing the camera;CFBundleShortVersionString=1.0.0;NSPhotoLibraryAddUsageDescription=The reason for adding to the photo library;NSFaceIDUsageDescription=The reason for accessing the face id;NSLocationAlwaysAndWhenInUseUsageDescription=The reason for accessing the location information of the user;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSSiriUsageDescription=The reason for accessing Siri $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1024.png $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_180x180.png @@ -268,6 +272,8 @@ $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_58x58.png $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png true + $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_1125x2436.png + $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_2436x1125.png $(fmxlinux)\Lib\$(ProductVersion)\$(Config);$(DCC_UnitSearchPath) @@ -275,12 +281,11 @@ FireDACTDataDriver;FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;tethering;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DbxCommonDriver;dbxcds;fmxFireDAC;DBXOracleDriver;CustomIPTransport;dsnap;IndyIPServer;fmxase;IndyCore;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;ibmonitor;xmlrtl;DataSnapNativeClient;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;FMXTee;soaprtl;emsclient;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;DataSnapServerMidas;DBXFirebirdDriver;inet;fmxobj;FireDACMySQLDriver;soapmidas;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage) true - CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts + CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;CFBundleShortVersionString=1.0.0;NSLocationAlwaysAndWhenInUseUsageDescription=The reason for accessing the location information of the user $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png - true true Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) FireDACTDataDriver;FireDACSqliteDriver;FireDACDSDriver;frxTee22;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;frxe22;DbxCommonDriver;vclimg;DCEF_XE8;dbxcds;DatasnapConnectorsFreePascal;appanalytics;vcldb;vcldsnap;tmswizdXE8;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;CodeSiteExpressPkg;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FmxPkgXE8;FireDACASADriver;ZrcCrossXE8;frx22;bindcompfmx;ZrcCommonXE8;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;tmsxlsdXE8;DBXOdbcDriver;ibmonitor;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;svnui;VclExXE8;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;ZrcIcsXE8;vclie;frxDB22;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;tmsexdXE8;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;tmsdXE8;fmxobj;FireDACMySQLDriver;soapmidas;vclx;svn;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage) @@ -288,11 +293,11 @@ CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(ModuleName);FileDescription=$(ModuleName);ProductName=$(ModuleName) $(BDS)\bin\default_app.manifest true + PerMonitor $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png - true true Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) FireDACTDataDriver;FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;appanalytics;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;ibmonitor;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;tmsexdXE8;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;tmsdXE8;fmxobj;FireDACMySQLDriver;soapmidas;vclx;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage) @@ -300,6 +305,7 @@ CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(ModuleName);FileDescription=$(ModuleName);ProductName=$(ModuleName) $(BDS)\bin\default_app.manifest true + PerMonitor DEBUG;$(DCC_Define) @@ -325,7 +331,6 @@ 1033 CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName) true - true Debug @@ -341,10 +346,10 @@ 1033 - true true true Debug + PerMonitor Debug @@ -395,6 +400,11 @@ true + + + true + + TestCrossSocket.exe @@ -407,179 +417,271 @@ true - + splash_image.png true - + + + TestCrossSocket.icns + true + + + + + TestCrossSocket.exe + true + + + - splash_image.png true - + + + true + + + + + classes.dex + true + + + libTestCrossSocket.so true - + - splash_image.png true - + + + TestCrossSocket + true + + + + + ic_launcher.png + true + + + + + libTestCrossSocket.so + true + + + TestCrossSocket.icns true - - - TestCrossSocket.exe + + true - + + + true + + + + + Info.plist + true + + + + + true + + + + + true + + + + + libTestCrossSocket.so + true + + + + + splash_image.png + true + + + ic_launcher.png true - - + + true - - + + true - + + + TestCrossSocket + true + + + classes.dex true - + - libTestCrossSocket.so + ic_launcher.png true - + - classes.dex true - + + ic_launcher.png true - + + splash_image.png true - + + splash_image.png true - - - TestCrossSocket + + + splash_image.png true - + - ic_launcher.png + libTestCrossSocket.so true - + + + splash_image.png + true + + + libTestCrossSocket.so true - - - TestCrossSocket.icns + + + ic_launcher.png true - - - Info.plist + + + ic_launcher.png true - + true - + - splash_image.png + classes.dex true - + true - - + + true - - - Info.plist + + + ic_launcher.png true - + + + ic_launcher.png + true + + + - TestCrossSocket + Info.plist true - + - ic_launcher.png + splash_image.png true - - + + true - + + TestCrossSocket true - - - Contents\MacOS\ - TestCrossSocket.rsm + + + libTestCrossSocket.so true - - + + + splash_image.png true @@ -589,9 +691,8 @@ true - - - TestCrossSocket + + true @@ -601,6 +702,11 @@ true + + + true + + 1 @@ -610,7 +716,6 @@ 1 - Contents\MacOS 0 @@ -620,6 +725,12 @@ 1 + + + res\xml + 1 + + library\lib\armeabi-v7a @@ -657,6 +768,12 @@ 1 + + + res\values-v21 + 1 + + res\drawable @@ -735,6 +852,11 @@ 1 .framework + + Contents\MacOS + 1 + .framework + 0 @@ -757,6 +879,11 @@ 1 .dylib + + Contents\MacOS + 1 + .dylib + 0 .dll;.bpl @@ -780,6 +907,11 @@ 1 .dylib + + Contents\MacOS + 1 + .dylib + 0 .bpl @@ -802,6 +934,10 @@ Contents\Resources\StartUp\ 0 + + Contents\Resources\StartUp\ + 0 + 0 @@ -938,23 +1074,41 @@ 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + ..\ 1 + + ..\ + 1 + Contents 1 + + Contents + 1 + Contents\Resources 1 + + Contents\Resources + 1 + @@ -977,6 +1131,10 @@ Contents\MacOS 1 + + Contents\MacOS + 1 + 0 @@ -1016,6 +1174,7 @@ + diff --git a/Net/Demos/TestCrossSocket/uMain.pas b/Net/Demos/TestCrossSocket/uMain.pas index bee6507..695b1b7 100644 --- a/Net/Demos/TestCrossSocket/uMain.pas +++ b/Net/Demos/TestCrossSocket/uMain.pas @@ -11,11 +11,10 @@ interface FMX.Controls.Presentation, FMX.Edit, FMX.EditBox, FMX.SpinBox, System.Diagnostics, FMX.Objects, {$IFDEF __SSL__} + Net.CrossSslSocket.Base, Net.CrossSslSocket, - {$IFDEF POSIX} Net.CrossSslDemoCert, {$ENDIF} - {$ENDIF} Net.SocketAPI, Net.CrossSocket.Base, Net.CrossSocket; type @@ -309,14 +308,8 @@ procedure TfmMain.FormCreate(Sender: TObject); FRunWatch := TStopwatch.StartNew; {$IFDEF __SSL__} - FSocket.InitSslCtx(SSLv23); - {$IFDEF POSIX} FSocket.SetCertificate(SSL_SERVER_CERT); FSocket.SetPrivateKey(SSL_SERVER_PKEY); - {$ELSE} - FSocket.SetCertificateFile('server.crt'); - FSocket.SetPrivateKeyFile('server.key'); - {$ENDIF} {$ENDIF} FTestProc := diff --git a/Net/MbedObj/Android/libmbedtls.a b/Net/MbedObj/Android/libmbedtls.a new file mode 100644 index 0000000..4114fb1 Binary files /dev/null and b/Net/MbedObj/Android/libmbedtls.a differ diff --git a/Net/MbedObj/Linux64/libmbedcrypto.so b/Net/MbedObj/Linux64/libmbedcrypto.so new file mode 100644 index 0000000..f3ab69d Binary files /dev/null and b/Net/MbedObj/Linux64/libmbedcrypto.so differ diff --git a/Net/MbedObj/Linux64/libmbedtls.so b/Net/MbedObj/Linux64/libmbedtls.so new file mode 100644 index 0000000..6c943b3 Binary files /dev/null and b/Net/MbedObj/Linux64/libmbedtls.so differ diff --git a/Net/MbedObj/Linux64/libmbedx509.so b/Net/MbedObj/Linux64/libmbedx509.so new file mode 100644 index 0000000..449f5b8 Binary files /dev/null and b/Net/MbedObj/Linux64/libmbedx509.so differ diff --git a/Net/MbedObj/MbedTls.zip b/Net/MbedObj/MbedTls.zip new file mode 100644 index 0000000..dad5c2a Binary files /dev/null and b/Net/MbedObj/MbedTls.zip differ diff --git a/Net/MbedObj/Win32/aes.obj b/Net/MbedObj/Win32/aes.obj new file mode 100644 index 0000000..f56ecf2 Binary files /dev/null and b/Net/MbedObj/Win32/aes.obj differ diff --git a/Net/MbedObj/Win32/aesni.obj b/Net/MbedObj/Win32/aesni.obj new file mode 100644 index 0000000..9ac006c Binary files /dev/null and b/Net/MbedObj/Win32/aesni.obj differ diff --git a/Net/MbedObj/Win32/arc4.obj b/Net/MbedObj/Win32/arc4.obj new file mode 100644 index 0000000..9f6bbcf Binary files /dev/null and b/Net/MbedObj/Win32/arc4.obj differ diff --git a/Net/MbedObj/Win32/aria.obj b/Net/MbedObj/Win32/aria.obj new file mode 100644 index 0000000..54bc9ce Binary files /dev/null and b/Net/MbedObj/Win32/aria.obj differ diff --git a/Net/MbedObj/Win32/asn1parse.obj b/Net/MbedObj/Win32/asn1parse.obj new file mode 100644 index 0000000..f2b2395 Binary files /dev/null and b/Net/MbedObj/Win32/asn1parse.obj differ diff --git a/Net/MbedObj/Win32/asn1write.obj b/Net/MbedObj/Win32/asn1write.obj new file mode 100644 index 0000000..016201f Binary files /dev/null and b/Net/MbedObj/Win32/asn1write.obj differ diff --git a/Net/MbedObj/Win32/base64.obj b/Net/MbedObj/Win32/base64.obj new file mode 100644 index 0000000..da2446d Binary files /dev/null and b/Net/MbedObj/Win32/base64.obj differ diff --git a/Net/MbedObj/Win32/bignum.obj b/Net/MbedObj/Win32/bignum.obj new file mode 100644 index 0000000..650b503 Binary files /dev/null and b/Net/MbedObj/Win32/bignum.obj differ diff --git a/Net/MbedObj/Win32/blowfish.obj b/Net/MbedObj/Win32/blowfish.obj new file mode 100644 index 0000000..b940de9 Binary files /dev/null and b/Net/MbedObj/Win32/blowfish.obj differ diff --git a/Net/MbedObj/Win32/camellia.obj b/Net/MbedObj/Win32/camellia.obj new file mode 100644 index 0000000..d9c224e Binary files /dev/null and b/Net/MbedObj/Win32/camellia.obj differ diff --git a/Net/MbedObj/Win32/ccm.obj b/Net/MbedObj/Win32/ccm.obj new file mode 100644 index 0000000..06eb13c Binary files /dev/null and b/Net/MbedObj/Win32/ccm.obj differ diff --git a/Net/MbedObj/Win32/chacha20.obj b/Net/MbedObj/Win32/chacha20.obj new file mode 100644 index 0000000..7febb82 Binary files /dev/null and b/Net/MbedObj/Win32/chacha20.obj differ diff --git a/Net/MbedObj/Win32/chachapoly.obj b/Net/MbedObj/Win32/chachapoly.obj new file mode 100644 index 0000000..6424348 Binary files /dev/null and b/Net/MbedObj/Win32/chachapoly.obj differ diff --git a/Net/MbedObj/Win32/cipher.obj b/Net/MbedObj/Win32/cipher.obj new file mode 100644 index 0000000..4d3bb54 Binary files /dev/null and b/Net/MbedObj/Win32/cipher.obj differ diff --git a/Net/MbedObj/Win32/cipher_wrap.obj b/Net/MbedObj/Win32/cipher_wrap.obj new file mode 100644 index 0000000..feaf637 Binary files /dev/null and b/Net/MbedObj/Win32/cipher_wrap.obj differ diff --git a/Net/MbedObj/Win32/cmac.obj b/Net/MbedObj/Win32/cmac.obj new file mode 100644 index 0000000..2984aaf Binary files /dev/null and b/Net/MbedObj/Win32/cmac.obj differ diff --git a/Net/MbedObj/Win32/ctr_drbg.obj b/Net/MbedObj/Win32/ctr_drbg.obj new file mode 100644 index 0000000..05e97bc Binary files /dev/null and b/Net/MbedObj/Win32/ctr_drbg.obj differ diff --git a/Net/MbedObj/Win32/debug.obj b/Net/MbedObj/Win32/debug.obj new file mode 100644 index 0000000..c766bef Binary files /dev/null and b/Net/MbedObj/Win32/debug.obj differ diff --git a/Net/MbedObj/Win32/des.obj b/Net/MbedObj/Win32/des.obj new file mode 100644 index 0000000..22f5ac3 Binary files /dev/null and b/Net/MbedObj/Win32/des.obj differ diff --git a/Net/MbedObj/Win32/dhm.obj b/Net/MbedObj/Win32/dhm.obj new file mode 100644 index 0000000..2fb25ec Binary files /dev/null and b/Net/MbedObj/Win32/dhm.obj differ diff --git a/Net/MbedObj/Win32/ecdh.obj b/Net/MbedObj/Win32/ecdh.obj new file mode 100644 index 0000000..f70079b Binary files /dev/null and b/Net/MbedObj/Win32/ecdh.obj differ diff --git a/Net/MbedObj/Win32/ecdsa.obj b/Net/MbedObj/Win32/ecdsa.obj new file mode 100644 index 0000000..b111edb Binary files /dev/null and b/Net/MbedObj/Win32/ecdsa.obj differ diff --git a/Net/MbedObj/Win32/ecjpake.obj b/Net/MbedObj/Win32/ecjpake.obj new file mode 100644 index 0000000..b3b280b Binary files /dev/null and b/Net/MbedObj/Win32/ecjpake.obj differ diff --git a/Net/MbedObj/Win32/ecp.obj b/Net/MbedObj/Win32/ecp.obj new file mode 100644 index 0000000..19d36e5 Binary files /dev/null and b/Net/MbedObj/Win32/ecp.obj differ diff --git a/Net/MbedObj/Win32/ecp_curves.obj b/Net/MbedObj/Win32/ecp_curves.obj new file mode 100644 index 0000000..f50449a Binary files /dev/null and b/Net/MbedObj/Win32/ecp_curves.obj differ diff --git a/Net/MbedObj/Win32/entropy.obj b/Net/MbedObj/Win32/entropy.obj new file mode 100644 index 0000000..22dd4ae Binary files /dev/null and b/Net/MbedObj/Win32/entropy.obj differ diff --git a/Net/MbedObj/Win32/entropy_poll.obj b/Net/MbedObj/Win32/entropy_poll.obj new file mode 100644 index 0000000..ec5c7dd Binary files /dev/null and b/Net/MbedObj/Win32/entropy_poll.obj differ diff --git a/Net/MbedObj/Win32/error.obj b/Net/MbedObj/Win32/error.obj new file mode 100644 index 0000000..6f1beb7 Binary files /dev/null and b/Net/MbedObj/Win32/error.obj differ diff --git a/Net/MbedObj/Win32/gcm.obj b/Net/MbedObj/Win32/gcm.obj new file mode 100644 index 0000000..864497c Binary files /dev/null and b/Net/MbedObj/Win32/gcm.obj differ diff --git a/Net/MbedObj/Win32/havege.obj b/Net/MbedObj/Win32/havege.obj new file mode 100644 index 0000000..a17c78e Binary files /dev/null and b/Net/MbedObj/Win32/havege.obj differ diff --git a/Net/MbedObj/Win32/hkdf.obj b/Net/MbedObj/Win32/hkdf.obj new file mode 100644 index 0000000..bc666a5 Binary files /dev/null and b/Net/MbedObj/Win32/hkdf.obj differ diff --git a/Net/MbedObj/Win32/hmac_drbg.obj b/Net/MbedObj/Win32/hmac_drbg.obj new file mode 100644 index 0000000..3700e4d Binary files /dev/null and b/Net/MbedObj/Win32/hmac_drbg.obj differ diff --git a/Net/MbedObj/Win32/md.obj b/Net/MbedObj/Win32/md.obj new file mode 100644 index 0000000..cd6db11 Binary files /dev/null and b/Net/MbedObj/Win32/md.obj differ diff --git a/Net/MbedObj/Win32/md2.obj b/Net/MbedObj/Win32/md2.obj new file mode 100644 index 0000000..e290c82 Binary files /dev/null and b/Net/MbedObj/Win32/md2.obj differ diff --git a/Net/MbedObj/Win32/md4.obj b/Net/MbedObj/Win32/md4.obj new file mode 100644 index 0000000..22dd7d9 Binary files /dev/null and b/Net/MbedObj/Win32/md4.obj differ diff --git a/Net/MbedObj/Win32/md5.obj b/Net/MbedObj/Win32/md5.obj new file mode 100644 index 0000000..28a75b0 Binary files /dev/null and b/Net/MbedObj/Win32/md5.obj differ diff --git a/Net/MbedObj/Win32/md_wrap.obj b/Net/MbedObj/Win32/md_wrap.obj new file mode 100644 index 0000000..e32bb8c Binary files /dev/null and b/Net/MbedObj/Win32/md_wrap.obj differ diff --git a/Net/MbedObj/Win32/memory_buffer_alloc.obj b/Net/MbedObj/Win32/memory_buffer_alloc.obj new file mode 100644 index 0000000..7771342 Binary files /dev/null and b/Net/MbedObj/Win32/memory_buffer_alloc.obj differ diff --git a/Net/MbedObj/Win32/nist_kw.obj b/Net/MbedObj/Win32/nist_kw.obj new file mode 100644 index 0000000..b184794 Binary files /dev/null and b/Net/MbedObj/Win32/nist_kw.obj differ diff --git a/Net/MbedObj/Win32/oid.obj b/Net/MbedObj/Win32/oid.obj new file mode 100644 index 0000000..761f1c3 Binary files /dev/null and b/Net/MbedObj/Win32/oid.obj differ diff --git a/Net/MbedObj/Win32/padlock.obj b/Net/MbedObj/Win32/padlock.obj new file mode 100644 index 0000000..a54aaaa Binary files /dev/null and b/Net/MbedObj/Win32/padlock.obj differ diff --git a/Net/MbedObj/Win32/pem.obj b/Net/MbedObj/Win32/pem.obj new file mode 100644 index 0000000..54edea0 Binary files /dev/null and b/Net/MbedObj/Win32/pem.obj differ diff --git a/Net/MbedObj/Win32/pk.obj b/Net/MbedObj/Win32/pk.obj new file mode 100644 index 0000000..4a4fd5e Binary files /dev/null and b/Net/MbedObj/Win32/pk.obj differ diff --git a/Net/MbedObj/Win32/pk_wrap.obj b/Net/MbedObj/Win32/pk_wrap.obj new file mode 100644 index 0000000..c519c65 Binary files /dev/null and b/Net/MbedObj/Win32/pk_wrap.obj differ diff --git a/Net/MbedObj/Win32/pkcs11.obj b/Net/MbedObj/Win32/pkcs11.obj new file mode 100644 index 0000000..957625a Binary files /dev/null and b/Net/MbedObj/Win32/pkcs11.obj differ diff --git a/Net/MbedObj/Win32/pkcs12.obj b/Net/MbedObj/Win32/pkcs12.obj new file mode 100644 index 0000000..4f8ecc9 Binary files /dev/null and b/Net/MbedObj/Win32/pkcs12.obj differ diff --git a/Net/MbedObj/Win32/pkcs5.obj b/Net/MbedObj/Win32/pkcs5.obj new file mode 100644 index 0000000..4edd3b7 Binary files /dev/null and b/Net/MbedObj/Win32/pkcs5.obj differ diff --git a/Net/MbedObj/Win32/pkparse.obj b/Net/MbedObj/Win32/pkparse.obj new file mode 100644 index 0000000..b9e3d20 Binary files /dev/null and b/Net/MbedObj/Win32/pkparse.obj differ diff --git a/Net/MbedObj/Win32/pkwrite.obj b/Net/MbedObj/Win32/pkwrite.obj new file mode 100644 index 0000000..6137387 Binary files /dev/null and b/Net/MbedObj/Win32/pkwrite.obj differ diff --git a/Net/MbedObj/Win32/platform.obj b/Net/MbedObj/Win32/platform.obj new file mode 100644 index 0000000..eec9ddb Binary files /dev/null and b/Net/MbedObj/Win32/platform.obj differ diff --git a/Net/MbedObj/Win32/platform_util.obj b/Net/MbedObj/Win32/platform_util.obj new file mode 100644 index 0000000..355df3d Binary files /dev/null and b/Net/MbedObj/Win32/platform_util.obj differ diff --git a/Net/MbedObj/Win32/poly1305.obj b/Net/MbedObj/Win32/poly1305.obj new file mode 100644 index 0000000..84b5cf9 Binary files /dev/null and b/Net/MbedObj/Win32/poly1305.obj differ diff --git a/Net/MbedObj/Win32/ripemd160.obj b/Net/MbedObj/Win32/ripemd160.obj new file mode 100644 index 0000000..ce392f4 Binary files /dev/null and b/Net/MbedObj/Win32/ripemd160.obj differ diff --git a/Net/MbedObj/Win32/rsa.obj b/Net/MbedObj/Win32/rsa.obj new file mode 100644 index 0000000..678443b Binary files /dev/null and b/Net/MbedObj/Win32/rsa.obj differ diff --git a/Net/MbedObj/Win32/rsa_internal.obj b/Net/MbedObj/Win32/rsa_internal.obj new file mode 100644 index 0000000..1c37ac1 Binary files /dev/null and b/Net/MbedObj/Win32/rsa_internal.obj differ diff --git a/Net/MbedObj/Win32/sha1.obj b/Net/MbedObj/Win32/sha1.obj new file mode 100644 index 0000000..e2fcd07 Binary files /dev/null and b/Net/MbedObj/Win32/sha1.obj differ diff --git a/Net/MbedObj/Win32/sha256.obj b/Net/MbedObj/Win32/sha256.obj new file mode 100644 index 0000000..6b17f0c Binary files /dev/null and b/Net/MbedObj/Win32/sha256.obj differ diff --git a/Net/MbedObj/Win32/sha512.obj b/Net/MbedObj/Win32/sha512.obj new file mode 100644 index 0000000..cba4ba6 Binary files /dev/null and b/Net/MbedObj/Win32/sha512.obj differ diff --git a/Net/MbedObj/Win32/ssl_cache.obj b/Net/MbedObj/Win32/ssl_cache.obj new file mode 100644 index 0000000..809aa68 Binary files /dev/null and b/Net/MbedObj/Win32/ssl_cache.obj differ diff --git a/Net/MbedObj/Win32/ssl_ciphersuites.obj b/Net/MbedObj/Win32/ssl_ciphersuites.obj new file mode 100644 index 0000000..d4a3ad1 Binary files /dev/null and b/Net/MbedObj/Win32/ssl_ciphersuites.obj differ diff --git a/Net/MbedObj/Win32/ssl_cli.obj b/Net/MbedObj/Win32/ssl_cli.obj new file mode 100644 index 0000000..95cd81a Binary files /dev/null and b/Net/MbedObj/Win32/ssl_cli.obj differ diff --git a/Net/MbedObj/Win32/ssl_cookie.obj b/Net/MbedObj/Win32/ssl_cookie.obj new file mode 100644 index 0000000..b8b3660 Binary files /dev/null and b/Net/MbedObj/Win32/ssl_cookie.obj differ diff --git a/Net/MbedObj/Win32/ssl_srv.obj b/Net/MbedObj/Win32/ssl_srv.obj new file mode 100644 index 0000000..ee4ae0b Binary files /dev/null and b/Net/MbedObj/Win32/ssl_srv.obj differ diff --git a/Net/MbedObj/Win32/ssl_ticket.obj b/Net/MbedObj/Win32/ssl_ticket.obj new file mode 100644 index 0000000..84ff19c Binary files /dev/null and b/Net/MbedObj/Win32/ssl_ticket.obj differ diff --git a/Net/MbedObj/Win32/ssl_tls.obj b/Net/MbedObj/Win32/ssl_tls.obj new file mode 100644 index 0000000..ff3ef23 Binary files /dev/null and b/Net/MbedObj/Win32/ssl_tls.obj differ diff --git a/Net/MbedObj/Win32/threading.obj b/Net/MbedObj/Win32/threading.obj new file mode 100644 index 0000000..0facc12 Binary files /dev/null and b/Net/MbedObj/Win32/threading.obj differ diff --git a/Net/MbedObj/Win32/timing.obj b/Net/MbedObj/Win32/timing.obj new file mode 100644 index 0000000..499f6ae Binary files /dev/null and b/Net/MbedObj/Win32/timing.obj differ diff --git a/Net/MbedObj/Win32/version.obj b/Net/MbedObj/Win32/version.obj new file mode 100644 index 0000000..c9fc23c Binary files /dev/null and b/Net/MbedObj/Win32/version.obj differ diff --git a/Net/MbedObj/Win32/version_features.obj b/Net/MbedObj/Win32/version_features.obj new file mode 100644 index 0000000..24d02c4 Binary files /dev/null and b/Net/MbedObj/Win32/version_features.obj differ diff --git a/Net/MbedObj/Win32/x509.obj b/Net/MbedObj/Win32/x509.obj new file mode 100644 index 0000000..ec8bde7 Binary files /dev/null and b/Net/MbedObj/Win32/x509.obj differ diff --git a/Net/MbedObj/Win32/x509_create.obj b/Net/MbedObj/Win32/x509_create.obj new file mode 100644 index 0000000..358c5c9 Binary files /dev/null and b/Net/MbedObj/Win32/x509_create.obj differ diff --git a/Net/MbedObj/Win32/x509_crl.obj b/Net/MbedObj/Win32/x509_crl.obj new file mode 100644 index 0000000..fce8a7f Binary files /dev/null and b/Net/MbedObj/Win32/x509_crl.obj differ diff --git a/Net/MbedObj/Win32/x509_crt.obj b/Net/MbedObj/Win32/x509_crt.obj new file mode 100644 index 0000000..211cbed Binary files /dev/null and b/Net/MbedObj/Win32/x509_crt.obj differ diff --git a/Net/MbedObj/Win32/x509_csr.obj b/Net/MbedObj/Win32/x509_csr.obj new file mode 100644 index 0000000..b57c02f Binary files /dev/null and b/Net/MbedObj/Win32/x509_csr.obj differ diff --git a/Net/MbedObj/Win32/x509write_crt.obj b/Net/MbedObj/Win32/x509write_crt.obj new file mode 100644 index 0000000..61878b5 Binary files /dev/null and b/Net/MbedObj/Win32/x509write_crt.obj differ diff --git a/Net/MbedObj/Win32/x509write_csr.obj b/Net/MbedObj/Win32/x509write_csr.obj new file mode 100644 index 0000000..8a62d95 Binary files /dev/null and b/Net/MbedObj/Win32/x509write_csr.obj differ diff --git a/Net/MbedObj/Win32/xtea.obj b/Net/MbedObj/Win32/xtea.obj new file mode 100644 index 0000000..5c9afc0 Binary files /dev/null and b/Net/MbedObj/Win32/xtea.obj differ diff --git a/Net/MbedObj/Win64/aes.o b/Net/MbedObj/Win64/aes.o new file mode 100644 index 0000000..a40c232 Binary files /dev/null and b/Net/MbedObj/Win64/aes.o differ diff --git a/Net/MbedObj/Win64/aesni.o b/Net/MbedObj/Win64/aesni.o new file mode 100644 index 0000000..9fa4659 Binary files /dev/null and b/Net/MbedObj/Win64/aesni.o differ diff --git a/Net/MbedObj/Win64/arc4.o b/Net/MbedObj/Win64/arc4.o new file mode 100644 index 0000000..180b75a Binary files /dev/null and b/Net/MbedObj/Win64/arc4.o differ diff --git a/Net/MbedObj/Win64/aria.o b/Net/MbedObj/Win64/aria.o new file mode 100644 index 0000000..8fa2a9d Binary files /dev/null and b/Net/MbedObj/Win64/aria.o differ diff --git a/Net/MbedObj/Win64/asn1parse.o b/Net/MbedObj/Win64/asn1parse.o new file mode 100644 index 0000000..0f63999 Binary files /dev/null and b/Net/MbedObj/Win64/asn1parse.o differ diff --git a/Net/MbedObj/Win64/asn1write.o b/Net/MbedObj/Win64/asn1write.o new file mode 100644 index 0000000..3df1e7e Binary files /dev/null and b/Net/MbedObj/Win64/asn1write.o differ diff --git a/Net/MbedObj/Win64/base64.o b/Net/MbedObj/Win64/base64.o new file mode 100644 index 0000000..52abd47 Binary files /dev/null and b/Net/MbedObj/Win64/base64.o differ diff --git a/Net/MbedObj/Win64/bignum.o b/Net/MbedObj/Win64/bignum.o new file mode 100644 index 0000000..7c133fb Binary files /dev/null and b/Net/MbedObj/Win64/bignum.o differ diff --git a/Net/MbedObj/Win64/blowfish.o b/Net/MbedObj/Win64/blowfish.o new file mode 100644 index 0000000..096c5b7 Binary files /dev/null and b/Net/MbedObj/Win64/blowfish.o differ diff --git a/Net/MbedObj/Win64/camellia.o b/Net/MbedObj/Win64/camellia.o new file mode 100644 index 0000000..48ae9da Binary files /dev/null and b/Net/MbedObj/Win64/camellia.o differ diff --git a/Net/MbedObj/Win64/ccm.o b/Net/MbedObj/Win64/ccm.o new file mode 100644 index 0000000..70ec9b4 Binary files /dev/null and b/Net/MbedObj/Win64/ccm.o differ diff --git a/Net/MbedObj/Win64/chacha20.o b/Net/MbedObj/Win64/chacha20.o new file mode 100644 index 0000000..40a6631 Binary files /dev/null and b/Net/MbedObj/Win64/chacha20.o differ diff --git a/Net/MbedObj/Win64/chachapoly.o b/Net/MbedObj/Win64/chachapoly.o new file mode 100644 index 0000000..2434f5b Binary files /dev/null and b/Net/MbedObj/Win64/chachapoly.o differ diff --git a/Net/MbedObj/Win64/cipher.o b/Net/MbedObj/Win64/cipher.o new file mode 100644 index 0000000..df64d16 Binary files /dev/null and b/Net/MbedObj/Win64/cipher.o differ diff --git a/Net/MbedObj/Win64/cipher_wrap.o b/Net/MbedObj/Win64/cipher_wrap.o new file mode 100644 index 0000000..5aecacf Binary files /dev/null and b/Net/MbedObj/Win64/cipher_wrap.o differ diff --git a/Net/MbedObj/Win64/cmac.o b/Net/MbedObj/Win64/cmac.o new file mode 100644 index 0000000..5c1e183 Binary files /dev/null and b/Net/MbedObj/Win64/cmac.o differ diff --git a/Net/MbedObj/Win64/ctr_drbg.o b/Net/MbedObj/Win64/ctr_drbg.o new file mode 100644 index 0000000..563ad69 Binary files /dev/null and b/Net/MbedObj/Win64/ctr_drbg.o differ diff --git a/Net/MbedObj/Win64/debug.o b/Net/MbedObj/Win64/debug.o new file mode 100644 index 0000000..90a6bcc Binary files /dev/null and b/Net/MbedObj/Win64/debug.o differ diff --git a/Net/MbedObj/Win64/des.o b/Net/MbedObj/Win64/des.o new file mode 100644 index 0000000..bc2c451 Binary files /dev/null and b/Net/MbedObj/Win64/des.o differ diff --git a/Net/MbedObj/Win64/dhm.o b/Net/MbedObj/Win64/dhm.o new file mode 100644 index 0000000..5274cee Binary files /dev/null and b/Net/MbedObj/Win64/dhm.o differ diff --git a/Net/MbedObj/Win64/ecdh.o b/Net/MbedObj/Win64/ecdh.o new file mode 100644 index 0000000..0ab5989 Binary files /dev/null and b/Net/MbedObj/Win64/ecdh.o differ diff --git a/Net/MbedObj/Win64/ecdsa.o b/Net/MbedObj/Win64/ecdsa.o new file mode 100644 index 0000000..0308485 Binary files /dev/null and b/Net/MbedObj/Win64/ecdsa.o differ diff --git a/Net/MbedObj/Win64/ecjpake.o b/Net/MbedObj/Win64/ecjpake.o new file mode 100644 index 0000000..17bbdcf Binary files /dev/null and b/Net/MbedObj/Win64/ecjpake.o differ diff --git a/Net/MbedObj/Win64/ecp.o b/Net/MbedObj/Win64/ecp.o new file mode 100644 index 0000000..794f60b Binary files /dev/null and b/Net/MbedObj/Win64/ecp.o differ diff --git a/Net/MbedObj/Win64/ecp_curves.o b/Net/MbedObj/Win64/ecp_curves.o new file mode 100644 index 0000000..77bdbce Binary files /dev/null and b/Net/MbedObj/Win64/ecp_curves.o differ diff --git a/Net/MbedObj/Win64/entropy.o b/Net/MbedObj/Win64/entropy.o new file mode 100644 index 0000000..5fcf51a Binary files /dev/null and b/Net/MbedObj/Win64/entropy.o differ diff --git a/Net/MbedObj/Win64/entropy_poll.o b/Net/MbedObj/Win64/entropy_poll.o new file mode 100644 index 0000000..8b1218b Binary files /dev/null and b/Net/MbedObj/Win64/entropy_poll.o differ diff --git a/Net/MbedObj/Win64/error.o b/Net/MbedObj/Win64/error.o new file mode 100644 index 0000000..5cb9c74 Binary files /dev/null and b/Net/MbedObj/Win64/error.o differ diff --git a/Net/MbedObj/Win64/gcm.o b/Net/MbedObj/Win64/gcm.o new file mode 100644 index 0000000..d03241e Binary files /dev/null and b/Net/MbedObj/Win64/gcm.o differ diff --git a/Net/MbedObj/Win64/havege.o b/Net/MbedObj/Win64/havege.o new file mode 100644 index 0000000..a0b4fab Binary files /dev/null and b/Net/MbedObj/Win64/havege.o differ diff --git a/Net/MbedObj/Win64/hkdf.o b/Net/MbedObj/Win64/hkdf.o new file mode 100644 index 0000000..82bdc16 Binary files /dev/null and b/Net/MbedObj/Win64/hkdf.o differ diff --git a/Net/MbedObj/Win64/hmac_drbg.o b/Net/MbedObj/Win64/hmac_drbg.o new file mode 100644 index 0000000..3caf07e Binary files /dev/null and b/Net/MbedObj/Win64/hmac_drbg.o differ diff --git a/Net/MbedObj/Win64/md.o b/Net/MbedObj/Win64/md.o new file mode 100644 index 0000000..9b9c3d6 Binary files /dev/null and b/Net/MbedObj/Win64/md.o differ diff --git a/Net/MbedObj/Win64/md2.o b/Net/MbedObj/Win64/md2.o new file mode 100644 index 0000000..3e41613 Binary files /dev/null and b/Net/MbedObj/Win64/md2.o differ diff --git a/Net/MbedObj/Win64/md4.o b/Net/MbedObj/Win64/md4.o new file mode 100644 index 0000000..181e7b0 Binary files /dev/null and b/Net/MbedObj/Win64/md4.o differ diff --git a/Net/MbedObj/Win64/md5.o b/Net/MbedObj/Win64/md5.o new file mode 100644 index 0000000..3d986be Binary files /dev/null and b/Net/MbedObj/Win64/md5.o differ diff --git a/Net/MbedObj/Win64/md_wrap.o b/Net/MbedObj/Win64/md_wrap.o new file mode 100644 index 0000000..7245845 Binary files /dev/null and b/Net/MbedObj/Win64/md_wrap.o differ diff --git a/Net/MbedObj/Win64/memory_buffer_alloc.o b/Net/MbedObj/Win64/memory_buffer_alloc.o new file mode 100644 index 0000000..35b62c2 Binary files /dev/null and b/Net/MbedObj/Win64/memory_buffer_alloc.o differ diff --git a/Net/MbedObj/Win64/nist_kw.o b/Net/MbedObj/Win64/nist_kw.o new file mode 100644 index 0000000..d57a3d9 Binary files /dev/null and b/Net/MbedObj/Win64/nist_kw.o differ diff --git a/Net/MbedObj/Win64/oid.o b/Net/MbedObj/Win64/oid.o new file mode 100644 index 0000000..6454563 Binary files /dev/null and b/Net/MbedObj/Win64/oid.o differ diff --git a/Net/MbedObj/Win64/padlock.o b/Net/MbedObj/Win64/padlock.o new file mode 100644 index 0000000..06ee67a Binary files /dev/null and b/Net/MbedObj/Win64/padlock.o differ diff --git a/Net/MbedObj/Win64/pem.o b/Net/MbedObj/Win64/pem.o new file mode 100644 index 0000000..d102b1f Binary files /dev/null and b/Net/MbedObj/Win64/pem.o differ diff --git a/Net/MbedObj/Win64/pk.o b/Net/MbedObj/Win64/pk.o new file mode 100644 index 0000000..f4caf01 Binary files /dev/null and b/Net/MbedObj/Win64/pk.o differ diff --git a/Net/MbedObj/Win64/pk_wrap.o b/Net/MbedObj/Win64/pk_wrap.o new file mode 100644 index 0000000..0fdd3a0 Binary files /dev/null and b/Net/MbedObj/Win64/pk_wrap.o differ diff --git a/Net/MbedObj/Win64/pkcs11.o b/Net/MbedObj/Win64/pkcs11.o new file mode 100644 index 0000000..8b50a7c Binary files /dev/null and b/Net/MbedObj/Win64/pkcs11.o differ diff --git a/Net/MbedObj/Win64/pkcs12.o b/Net/MbedObj/Win64/pkcs12.o new file mode 100644 index 0000000..0f4d07e Binary files /dev/null and b/Net/MbedObj/Win64/pkcs12.o differ diff --git a/Net/MbedObj/Win64/pkcs5.o b/Net/MbedObj/Win64/pkcs5.o new file mode 100644 index 0000000..49c7c85 Binary files /dev/null and b/Net/MbedObj/Win64/pkcs5.o differ diff --git a/Net/MbedObj/Win64/pkparse.o b/Net/MbedObj/Win64/pkparse.o new file mode 100644 index 0000000..fe13950 Binary files /dev/null and b/Net/MbedObj/Win64/pkparse.o differ diff --git a/Net/MbedObj/Win64/pkwrite.o b/Net/MbedObj/Win64/pkwrite.o new file mode 100644 index 0000000..7a0699b Binary files /dev/null and b/Net/MbedObj/Win64/pkwrite.o differ diff --git a/Net/MbedObj/Win64/platform.o b/Net/MbedObj/Win64/platform.o new file mode 100644 index 0000000..a69e638 Binary files /dev/null and b/Net/MbedObj/Win64/platform.o differ diff --git a/Net/MbedObj/Win64/platform_util.o b/Net/MbedObj/Win64/platform_util.o new file mode 100644 index 0000000..fb56979 Binary files /dev/null and b/Net/MbedObj/Win64/platform_util.o differ diff --git a/Net/MbedObj/Win64/poly1305.o b/Net/MbedObj/Win64/poly1305.o new file mode 100644 index 0000000..d8ae338 Binary files /dev/null and b/Net/MbedObj/Win64/poly1305.o differ diff --git a/Net/MbedObj/Win64/ripemd160.o b/Net/MbedObj/Win64/ripemd160.o new file mode 100644 index 0000000..576dc5f Binary files /dev/null and b/Net/MbedObj/Win64/ripemd160.o differ diff --git a/Net/MbedObj/Win64/rsa.o b/Net/MbedObj/Win64/rsa.o new file mode 100644 index 0000000..913b6ac Binary files /dev/null and b/Net/MbedObj/Win64/rsa.o differ diff --git a/Net/MbedObj/Win64/rsa_internal.o b/Net/MbedObj/Win64/rsa_internal.o new file mode 100644 index 0000000..2096b28 Binary files /dev/null and b/Net/MbedObj/Win64/rsa_internal.o differ diff --git a/Net/MbedObj/Win64/sha1.o b/Net/MbedObj/Win64/sha1.o new file mode 100644 index 0000000..e7675f7 Binary files /dev/null and b/Net/MbedObj/Win64/sha1.o differ diff --git a/Net/MbedObj/Win64/sha256.o b/Net/MbedObj/Win64/sha256.o new file mode 100644 index 0000000..12b87fa Binary files /dev/null and b/Net/MbedObj/Win64/sha256.o differ diff --git a/Net/MbedObj/Win64/sha512.o b/Net/MbedObj/Win64/sha512.o new file mode 100644 index 0000000..cf81a8a Binary files /dev/null and b/Net/MbedObj/Win64/sha512.o differ diff --git a/Net/MbedObj/Win64/ssl_cache.o b/Net/MbedObj/Win64/ssl_cache.o new file mode 100644 index 0000000..795e823 Binary files /dev/null and b/Net/MbedObj/Win64/ssl_cache.o differ diff --git a/Net/MbedObj/Win64/ssl_ciphersuites.o b/Net/MbedObj/Win64/ssl_ciphersuites.o new file mode 100644 index 0000000..f5414f2 Binary files /dev/null and b/Net/MbedObj/Win64/ssl_ciphersuites.o differ diff --git a/Net/MbedObj/Win64/ssl_cli.o b/Net/MbedObj/Win64/ssl_cli.o new file mode 100644 index 0000000..1f8dd31 Binary files /dev/null and b/Net/MbedObj/Win64/ssl_cli.o differ diff --git a/Net/MbedObj/Win64/ssl_cookie.o b/Net/MbedObj/Win64/ssl_cookie.o new file mode 100644 index 0000000..eb1ab21 Binary files /dev/null and b/Net/MbedObj/Win64/ssl_cookie.o differ diff --git a/Net/MbedObj/Win64/ssl_srv.o b/Net/MbedObj/Win64/ssl_srv.o new file mode 100644 index 0000000..717dec8 Binary files /dev/null and b/Net/MbedObj/Win64/ssl_srv.o differ diff --git a/Net/MbedObj/Win64/ssl_ticket.o b/Net/MbedObj/Win64/ssl_ticket.o new file mode 100644 index 0000000..287cef9 Binary files /dev/null and b/Net/MbedObj/Win64/ssl_ticket.o differ diff --git a/Net/MbedObj/Win64/ssl_tls.o b/Net/MbedObj/Win64/ssl_tls.o new file mode 100644 index 0000000..a4458f6 Binary files /dev/null and b/Net/MbedObj/Win64/ssl_tls.o differ diff --git a/Net/MbedObj/Win64/threading.o b/Net/MbedObj/Win64/threading.o new file mode 100644 index 0000000..98548c9 Binary files /dev/null and b/Net/MbedObj/Win64/threading.o differ diff --git a/Net/MbedObj/Win64/timing.o b/Net/MbedObj/Win64/timing.o new file mode 100644 index 0000000..b84db4a Binary files /dev/null and b/Net/MbedObj/Win64/timing.o differ diff --git a/Net/MbedObj/Win64/version.o b/Net/MbedObj/Win64/version.o new file mode 100644 index 0000000..c736cf7 Binary files /dev/null and b/Net/MbedObj/Win64/version.o differ diff --git a/Net/MbedObj/Win64/version_features.o b/Net/MbedObj/Win64/version_features.o new file mode 100644 index 0000000..0a25a32 Binary files /dev/null and b/Net/MbedObj/Win64/version_features.o differ diff --git a/Net/MbedObj/Win64/x509.o b/Net/MbedObj/Win64/x509.o new file mode 100644 index 0000000..80248ef Binary files /dev/null and b/Net/MbedObj/Win64/x509.o differ diff --git a/Net/MbedObj/Win64/x509_create.o b/Net/MbedObj/Win64/x509_create.o new file mode 100644 index 0000000..301a3ab Binary files /dev/null and b/Net/MbedObj/Win64/x509_create.o differ diff --git a/Net/MbedObj/Win64/x509_crl.o b/Net/MbedObj/Win64/x509_crl.o new file mode 100644 index 0000000..664084c Binary files /dev/null and b/Net/MbedObj/Win64/x509_crl.o differ diff --git a/Net/MbedObj/Win64/x509_crt.o b/Net/MbedObj/Win64/x509_crt.o new file mode 100644 index 0000000..620e403 Binary files /dev/null and b/Net/MbedObj/Win64/x509_crt.o differ diff --git a/Net/MbedObj/Win64/x509_csr.o b/Net/MbedObj/Win64/x509_csr.o new file mode 100644 index 0000000..31c99c8 Binary files /dev/null and b/Net/MbedObj/Win64/x509_csr.o differ diff --git a/Net/MbedObj/Win64/x509write_crt.o b/Net/MbedObj/Win64/x509write_crt.o new file mode 100644 index 0000000..dc8d570 Binary files /dev/null and b/Net/MbedObj/Win64/x509write_crt.o differ diff --git a/Net/MbedObj/Win64/x509write_csr.o b/Net/MbedObj/Win64/x509write_csr.o new file mode 100644 index 0000000..d2312a6 Binary files /dev/null and b/Net/MbedObj/Win64/x509write_csr.o differ diff --git a/Net/MbedObj/Win64/xtea.o b/Net/MbedObj/Win64/xtea.o new file mode 100644 index 0000000..e361a35 Binary files /dev/null and b/Net/MbedObj/Win64/xtea.o differ diff --git a/Net/MbedObj/iOSDevice64/libmbedtls.a b/Net/MbedObj/iOSDevice64/libmbedtls.a new file mode 100644 index 0000000..dae368a Binary files /dev/null and b/Net/MbedObj/iOSDevice64/libmbedtls.a differ diff --git a/Net/Net.CrossHttpParams.pas b/Net/Net.CrossHttpParams.pas index 77e08a0..8716a0f 100644 --- a/Net/Net.CrossHttpParams.pas +++ b/Net/Net.CrossHttpParams.pas @@ -12,10 +12,17 @@ interface uses - System.SysUtils, System.Classes, System.Generics.Collections, - System.Generics.Defaults, System.NetEncoding, System.IOUtils, - System.RegularExpressions, System.SyncObjs, System.Diagnostics, - System.DateUtils, Net.CrossHttpUtils; + System.SysUtils, + System.Classes, + System.Generics.Collections, + System.Generics.Defaults, + System.NetEncoding, + System.IOUtils, + System.RegularExpressions, + System.SyncObjs, + System.Diagnostics, + System.DateUtils, + Net.CrossHttpUtils; type TNameValue = record @@ -331,7 +338,6 @@ TFormField = class FFilePath: string; FContentType: string; FContentTransferEncoding: string; - FAutoDeleteFile: Boolean; public constructor Create; destructor Destroy; override; @@ -374,11 +380,6 @@ TFormField = class /// property FilePath: string read FFilePath; - /// - /// ͷʱԶɾϴļ - /// - property AutoDeleteFile: Boolean read FAutoDeleteFile write FAutoDeleteFile; - /// /// ֻͣļиԣ /// @@ -503,6 +504,11 @@ TEnumerator = class(TEnumerator) procedure SetExpiryTime(const Value: Integer); procedure SetValue(const AName, AValue: string); + /// + /// ʱ + /// + procedure Touch; + /// /// Ƿѹ /// @@ -559,6 +565,7 @@ TSessionBase = class abstract(TInterfacedObject, ISession) public constructor Create(const ASessionID: string); virtual; abstract; + procedure Touch; virtual; function Expired: Boolean; virtual; property SessionID: string read GetSessionID write SetSessionID; @@ -809,7 +816,8 @@ TSessions = class(TSessionsBase) implementation uses - Utils.Utils, Utils.DateTime; + Utils.Utils, + Utils.DateTime; { TNameValue } @@ -1268,9 +1276,6 @@ destructor TFormField.Destroy; begin FreeValue; - if FAutoDeleteFile and (FFilePath <> '') and TFile.Exists(FFilePath) then - TFile.Delete(FFilePath); - inherited; end; @@ -1352,7 +1357,18 @@ destructor THttpMultiPartFormData.Destroy; end; procedure THttpMultiPartFormData.Clear; +var + LField: TFormField; begin + for LField in FPartFields do + begin + if FAutoDeleteFiles and TFile.Exists(LField.FilePath) then + begin + LField.FreeValue; + TFile.Delete(LField.FilePath); + end; + end; + FPartFields.Clear; end; @@ -1550,7 +1566,6 @@ function THttpMultiPartFormData.Decode(const ABuf: Pointer; ALen: Integer): Inte LPartHeader := TEncoding.UTF8.GetString(FCurrentPartHeader.Bytes, 0, FCurrentPartHeader.Size - 4{#13#10#13#10}); FCurrentPartHeader.Clear; FCurrentPartField := TFormField.Create; - FCurrentPartField.AutoDeleteFile := FAutoDeleteFiles; __InitFormFieldByHeader(FCurrentPartField, LPartHeader); FPartFields.Add(FCurrentPartField); @@ -1694,6 +1709,11 @@ function TSessionBase.Expired: Boolean; Result := (Now.SecondsDiffer(LastAccessTime) >= ExpiryTime); end; +procedure TSessionBase.Touch; +begin + LastAccessTime := Now; +end; + { TSession } constructor TSession.Create(const ASessionID: string); diff --git a/Net/Net.CrossHttpRouter.pas b/Net/Net.CrossHttpRouter.pas index 0c375c9..7b7a9ac 100644 --- a/Net/Net.CrossHttpRouter.pas +++ b/Net/Net.CrossHttpRouter.pas @@ -41,6 +41,17 @@ TNetCrossRouter = class /// Ŀ¼ /// class function Dir(const APath, ALocalDir, ADirParamName: string): TCrossHttpRouterProc2; static; + + /// + /// Ĭҳļľ̬ļ· + /// + /// + /// ĬҳļıĿ¼ + /// + /// + /// Ĭϵҳļ,˳ѡ,ҵĸʹĸ + /// + class function Index(const ALocalDir, AFileParamName: string; const ADefIndexFiles: TArray): TCrossHttpRouterProc2; static; end; implementation @@ -50,6 +61,58 @@ implementation { TNetCrossRouter } +class function TNetCrossRouter.Index(const ALocalDir, AFileParamName: string; + const ADefIndexFiles: TArray): TCrossHttpRouterProc2; +var + LDefIndexFiles: TArray; +begin + if (ADefIndexFiles <> nil) then + LDefIndexFiles := ADefIndexFiles + else + LDefIndexFiles := [ + 'index.html', + 'main.html', + 'index.js', + 'main.js', + 'index.htm', + 'main.htm' + ]; + + Result := + procedure(ARequest: ICrossHttpRequest; AResponse: ICrossHttpResponse; var AHandled: Boolean) + var + LPath, LFile, LDefMainFile: string; + begin + LPath := ALocalDir; + LFile := ARequest.Params[AFileParamName]; + + if (LFile = '') then + begin + for LDefMainFile in LDefIndexFiles do + begin + LFile := TPath.Combine(LPath, LDefMainFile); + if TFile.Exists(LFile) then + begin + AResponse.SendFile(LFile); + AHandled := True; + Exit; + end; + end; + end else + begin + LFile := TPath.Combine(LPath, LFile); + if TFile.Exists(LFile) then + begin + AResponse.SendFile(LFile); + AHandled := True; + Exit; + end; + end; + + AHandled := False; + end; +end; + class function TNetCrossRouter.Static( const ALocalDir, AFileParamName: string): TCrossHttpRouterProc2; begin @@ -173,8 +236,8 @@ function BuildDirList(const ARealPath, ARequestPath, AHome: string): string; LPath := _NormalizePath(APath); LHome := _NormalizePath(AHome); - LPathArr := LPath.Split(['/', '\'], ExcludeEmpty); - LHomeArr := LHome.Split(['/', '\'], ExcludeEmpty); + LPathArr := LPath.Split(['/', '\'], TStringSplitOptions.ExcludeEmpty); + LHomeArr := LHome.Split(['/', '\'], TStringSplitOptions.ExcludeEmpty); if Length(LHomeArr) > Length(LPathArr) then Exit(''); I := 0; diff --git a/Net/Net.CrossHttpServer.pas b/Net/Net.CrossHttpServer.pas index c676369..13a08a3 100644 --- a/Net/Net.CrossHttpServer.pas +++ b/Net/Net.CrossHttpServer.pas @@ -34,9 +34,8 @@ interface Net.CrossSocket, Net.CrossServer, {$IFDEF __CROSS_SSL__} - Net.OpenSSL, - Net.CrossSslSocket, - Net.CrossSslServer, + Net.CrossSslSocket, + Net.CrossSslServer, {$ENDIF} Net.CrossHttpParams, Net.CrossHttpUtils, @@ -51,8 +50,8 @@ ECrossHttpException = class(Exception) private FStatusCode: Integer; public - constructor Create(const AMessage: string; AStatusCode: Integer = 500); reintroduce; virtual; - constructor CreateFmt(const AMessage: string; const AArgs: array of const; AStatusCode: Integer = 500); reintroduce; virtual; + constructor Create(const AMessage: string; AStatusCode: Integer = 400); reintroduce; virtual; + constructor CreateFmt(const AMessage: string; const AArgs: array of const; AStatusCode: Integer = 400); reintroduce; virtual; property StatusCode: Integer read FStatusCode write FStatusCode; end; @@ -986,6 +985,31 @@ ECrossHttpException = class(Exception) procedure SetOnPostData(const Value: TCrossHttpDataEvent); procedure SetOnPostDataEnd(const Value: TCrossHttpConnEvent); + /// + /// 创建路由对象 + /// + /// + /// 请求方式 + /// + /// + /// 请求路径 + /// + /// + /// 路由匿名函数 + /// + /// + /// 路由方法 + /// + /// + /// 路由匿名函数 + /// + /// + /// 路由方法 + /// + function CreateRouter(const AMethod, APath: string; + ARouterProc: TCrossHttpRouterProc; ARouterMethod: TCrossHttpRouterMethod; + ARouterProc2: TCrossHttpRouterProc2; ARouterMethod2: TCrossHttpRouterMethod2): ICrossHttpRouter; + /// /// 注册中间件 /// @@ -1532,6 +1556,20 @@ ECrossHttpException = class(Exception) /// function Dir(const APath, ALocalDir: string): ICrossHttpServer; + /// + /// 注册含有默认首页文件的静态文件路由 + /// + /// + /// 请求路径 + /// + /// + /// 含有默认首页文件的本地目录 + /// + /// + /// 默认的首页文件,按顺序选择,先找到哪个就使用哪个 + /// + function Index(const APath, ALocalDir: string; const ADefIndexFiles: TArray): ICrossHttpServer; + /// /// 删除指定路由 /// @@ -1992,6 +2030,10 @@ TCrossHttpServer = class({$IFDEF __CROSS_SSL__}TCrossSslServer{$ELSE}TCrossSer function CreateConnection(AOwner: ICrossSocket; AClientSocket: THandle; AConnectType: TConnectType): ICrossConnection; override; + function CreateRouter(const AMethod, APath: string; + ARouterProc: TCrossHttpRouterProc; ARouterMethod: TCrossHttpRouterMethod; + ARouterProc2: TCrossHttpRouterProc2; ARouterMethod2: TCrossHttpRouterMethod2): ICrossHttpRouter; virtual; + procedure LogicReceived(AConnection: ICrossConnection; ABuf: Pointer; ALen: Integer); override; protected procedure TriggerPostDataBegin(AConnection: ICrossHttpConnection); virtual; @@ -2066,6 +2108,7 @@ TCrossHttpServer = class({$IFDEF __CROSS_SSL__}TCrossSslServer{$ELSE}TCrossSer function &Static(const APath, ALocalStaticDir: string): ICrossHttpServer; function Dir(const APath, ALocalDir: string): ICrossHttpServer; + function Index(const APath, ALocalDir: string; const ADefIndexFiles: TArray): ICrossHttpServer; function RemoveRouter(const AMethod, APath: string): ICrossHttpServer; function ClearRouter: ICrossHttpServer; @@ -2427,6 +2470,16 @@ function TCrossHttpServer.CreateConnection(AOwner: ICrossSocket; Result := TCrossHttpConnection.Create(AOwner, AClientSocket, AConnectType); end; +function TCrossHttpServer.CreateRouter(const AMethod, APath: string; + ARouterProc: TCrossHttpRouterProc; ARouterMethod: TCrossHttpRouterMethod; + ARouterProc2: TCrossHttpRouterProc2; + ARouterMethod2: TCrossHttpRouterMethod2): ICrossHttpRouter; +begin + Result := TCrossHttpRouter.Create(AMethod, APath, + ARouterProc, ARouterMethod, + ARouterProc2, ARouterMethod2); +end; + destructor TCrossHttpServer.Destroy; begin Stop; @@ -2754,6 +2807,18 @@ function TCrossHttpServer.Static(const APath, Result := Get(LReqPath, TNetCrossRouter.Static(ALocalStaticDir, 'file')); end; +function TCrossHttpServer.Index(const APath, ALocalDir: string; + const ADefIndexFiles: TArray): ICrossHttpServer; +var + LReqPath: string; +begin + LReqPath := APath; + if not LReqPath.EndsWith('/') then + LReqPath := LReqPath + '/'; + LReqPath := LReqPath + ':file(*)'; + Result := Get(LReqPath, TNetCrossRouter.Index(ALocalDir, 'file', ADefIndexFiles)); +end; + function TCrossHttpServer.IsValidHttpRequest(ABuf: Pointer; ALen: Integer): Boolean; var @@ -3045,9 +3110,9 @@ function TCrossHttpServer.RegisterMiddleware(const AMethod, APath: string; AMiddlewareProc2: TCrossHttpRouterProc2; AMiddlewareMethod2: TCrossHttpRouterMethod2): TCrossHttpServer; var - LMiddleware: TCrossHttpRouter; + LMiddleware: ICrossHttpRouter; begin - LMiddleware := TCrossHttpRouter.Create(AMethod, APath, + LMiddleware := CreateRouter(AMethod, APath, AMiddlewareProc, AMiddlewareMethod, AMiddlewareProc2, AMiddlewareMethod2); FMiddlewaresLock.BeginWrite; @@ -3065,7 +3130,7 @@ function TCrossHttpServer.RegisterRouter(const AMethod, APath: string; var LRouter: ICrossHttpRouter; begin - LRouter := TCrossHttpRouter.Create(AMethod, APath, + LRouter := CreateRouter(AMethod, APath, ARouterProc, ARouterMethod, ARouterProc2, ARouterMethod2); FRoutersLock.BeginWrite; @@ -3108,7 +3173,7 @@ function TCrossHttpServer.RemoveRouter(const AMethod, APath: string): ICrossHttp FRoutersLock.BeginWrite; try for I := FRouters.Count - 1 downto 0 do - if SameText(TCrossHttpRouter(FRouters[I]).FMethod, AMethod) and SameText(TCrossHttpRouter(FRouters[I]).FPath, APath) then + if SameText(FRouters[I].Method, AMethod) and SameText(FRouters[I].Path, APath) then FRouters.Delete(I); finally FRoutersLock.EndWrite; @@ -4421,7 +4486,7 @@ procedure TCrossHttpResponse.SendZCompress( LZFlush := Z_NO_FLUSH; if (deflateInit2(LZStream, Z_DEFAULT_COMPRESSION, - Z_DEFLATED, WINDOW_BITS[ACompressType], 8, Z_DEFAULT_STRATEGY) <> Z_OK) then + Z_DEFLATED, WINDOW_BITS[ACompressType], 8, Z_DEFAULT_STRATEGY) <> Z_OK) then begin if Assigned(ACallback) then ACallback(FConnection, False); diff --git a/Net/Net.CrossServer.pas b/Net/Net.CrossServer.pas index b396e51..8c0b1b1 100644 --- a/Net/Net.CrossServer.pas +++ b/Net/Net.CrossServer.pas @@ -13,7 +13,6 @@ interface uses System.SysUtils, - Net.SocketAPI, Net.CrossSocket.Base, Net.CrossSocket; diff --git a/Net/Net.CrossSslServer.pas b/Net/Net.CrossSslServer.pas index 9614058..fb4e0bf 100644 --- a/Net/Net.CrossSslServer.pas +++ b/Net/Net.CrossSslServer.pas @@ -15,6 +15,7 @@ interface System.SysUtils, Net.SocketAPI, Net.CrossSocket.Base, + Net.CrossSslSocket.Base, Net.CrossSslSocket; type @@ -68,8 +69,6 @@ implementation constructor TCrossSslServer.Create(AIoThreads: Integer); begin inherited; - - InitSslCtx(SSLv23_server); end; function TCrossSslServer.GetActive: Boolean; diff --git a/Net/Net.CrossSslSocket.Base.pas b/Net/Net.CrossSslSocket.Base.pas new file mode 100644 index 0000000..fdb67c6 --- /dev/null +++ b/Net/Net.CrossSslSocket.Base.pas @@ -0,0 +1,85 @@ +unit Net.CrossSslSocket.Base; + +interface + +uses + Net.CrossSocket.Base; + +type + /// + /// SSL Socket + /// + /// + /// ȷʹò: + /// + /// + /// SetCertificateificate SetCertificateificateFile + /// + /// + /// SetPrivateKey SetPrivateKeyFile, ͻ˲Ҫһ + /// + /// + /// Connect / Listen + /// + /// + /// + ICrossSslSocket = interface(ICrossSocket) + ['{A4765486-A0F1-4EFD-BC39-FA16AED21A6A}'] + /// + /// ڴ֤ + /// + /// + /// ֤黺 + /// + /// + /// ֤黺С + /// + procedure SetCertificate(ACertBuf: Pointer; ACertBufSize: Integer); overload; + + /// + /// ַ֤ + /// + /// + /// ַ֤ + /// + procedure SetCertificate(const ACertStr: string); overload; + + /// + /// ļ֤ + /// + /// + /// ֤ļ + /// + procedure SetCertificateFile(const ACertFile: string); + + /// + /// ڴ˽Կ + /// + /// + /// ˽Կ + /// + /// + /// ˽ԿС + /// + procedure SetPrivateKey(APKeyBuf: Pointer; APKeyBufSize: Integer); overload; + + /// + /// ַ˽Կ + /// + /// + /// ˽Կַ + /// + procedure SetPrivateKey(const APKeyStr: string); overload; + + /// + /// ļ˽Կ + /// + /// + /// ˽Կļ + /// + procedure SetPrivateKeyFile(const APKeyFile: string); + end; + +implementation + +end. diff --git a/Net/Net.CrossSslSocket.MbedTls.pas b/Net/Net.CrossSslSocket.MbedTls.pas new file mode 100644 index 0000000..7bc84fe --- /dev/null +++ b/Net/Net.CrossSslSocket.MbedTls.pas @@ -0,0 +1,535 @@ +{******************************************************************************} +{ } +{ Delphi cross platform socket library } +{ } +{ Copyright (c) 2017 WiNDDRiVER(soulawing@gmail.com) } +{ } +{ Homepage: https://github.com/winddriver/Delphi-Cross-Socket } +{ } +{******************************************************************************} +unit Net.CrossSslSocket.MbedTls; + +{ + SSL通讯基本流程: + 1. 当连接建立时进行 SSL 握手, 收到数据时也要检查握手状态 + 2. 发送数据: 用 SSL_write 写入原数据, BIO_read 读取加密后的数据进行发送 + 3. 接收数据: 用 BIO_write 写入收到的数据, 用 SSL_read 读取解密后的数据 + + 传输层安全协议: + https://zh.wikipedia.org/wiki/%E5%82%B3%E8%BC%B8%E5%B1%A4%E5%AE%89%E5%85%A8%E5%8D%94%E8%AD%B0 +} + +interface + +uses + System.SysUtils, + System.Classes, + System.IOUtils, + Net.CrossSocket.Base, + Net.CrossSocket, + Net.CrossSslSocket.Base, + Net.MbedTls, + Net.MbedBIO; + +const + DEFAULT_CIPHERSUITES_SERVER: array [0..12] of Integer = ( + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + + MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, + + 0); + + DEFAULT_CIPHERSUITES_CLIENT: array [0..18] of Integer = ( + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + + MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + + MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, + + MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, + + 0); + +type + EMbedTls = class(Exception) + private + FCode: Integer; + public + constructor Create(const ACode: Integer; const AMessage: string); reintroduce; overload; + constructor Create(const ACode: Integer; const AFmt: string; const AArgs: array of const); reintroduce; overload; + + property Code: Integer read FCode; + end; + + TCrossMbedTlsConnection = class(TCrossConnection) + private + FSsl: TMbedtls_SSL_Context; + FSslBIO, FAppBIO: PBIO; + + procedure _Lock; inline; + procedure _Unlock; inline; + + function _SslHandshake: Boolean; + procedure _SendBIOPendingData(const ACallback: TProc = nil); + protected + procedure DirectSend(ABuffer: Pointer; ACount: Integer; + const ACallback: TProc = nil); override; + public + constructor Create(AOwner: ICrossSocket; AClientSocket: THandle; + AConnectType: TConnectType); override; + destructor Destroy; override; + end; + + /// + /// 若要继承该类, 请重载 LogicXXX, 而不是 TriggerXXX + /// + TCrossMbedTlsSocket = class(TCrossSocket, ICrossSslSocket) + private const + SSL_BUF_SIZE = 32768; + private class threadvar + FSslInBuf: array [0..SSL_BUF_SIZE-1] of Byte; + private + FSrvConf, FCliConf: TMbedtls_SSL_Config; + FEntropy: TMbedtls_Entropy_Context; + FCtrDrbg: TMbedtls_CTR_DRBG_Context ; + FCert: TMbedtls_X509_CRT; + FPKey: TMbedtls_PK_Context; + FCache: TMbedtls_SSL_Cache_Context; + + procedure _InitSslConf; + procedure _FreeSslConf; + + function _MbedCert(const ACertStr: string): string; inline; + procedure _UpdateCert; + protected + procedure TriggerConnected(AConnection: ICrossConnection); override; + procedure TriggerReceived(AConnection: ICrossConnection; ABuf: Pointer; ALen: Integer); override; + + function CreateConnection(AOwner: ICrossSocket; AClientSocket: THandle; + AConnectType: TConnectType): ICrossConnection; override; + public + constructor Create(AIoThreads: Integer); override; + destructor Destroy; override; + + procedure SetCertificate(ACertBuf: Pointer; ACertBufSize: Integer); overload; + procedure SetCertificate(const ACertStr: string); overload; + procedure SetCertificateFile(const ACertFile: string); + + procedure SetPrivateKey(APKeyBuf: Pointer; APKeyBufSize: Integer); overload; + procedure SetPrivateKey(const APKeyStr: string); overload; + procedure SetPrivateKeyFile(const APKeyFile: string); + end; + +implementation + +{ EMbedTls } + +constructor EMbedTls.Create(const ACode: Integer; const AMessage: string); +var + LMessage: string; +begin + FCode := ACode; + + if (AMessage <> '') then + LMessage := AMessage + MbedErrToStr(ACode) + else + LMessage := MbedErrToStr(ACode); + + inherited Create(LMessage); +end; + +constructor EMbedTls.Create(const ACode: Integer; const AFmt: string; + const AArgs: array of const); +begin + Create(ACode, Format(AFmt, AArgs)); +end; + +function MbedCheck(const ACode: Integer; const AErrMsg: string = ''): Integer; +begin + Result := ACode; + + if (ACode >= 0) then Exit; + + case ACode of + MBEDTLS_ERR_SSL_WANT_READ, MBEDTLS_ERR_SSL_WANT_WRITE:; + else + raise EMbedTls.Create(ACode, AErrMsg); + end; +end; + +{ TCrossMbedTlsConnection } + +constructor TCrossMbedTlsConnection.Create(AOwner: ICrossSocket; + AClientSocket: THandle; AConnectType: TConnectType); +begin + inherited; + + mbedtls_ssl_init(@FSsl); + + if (ConnectType = ctAccept) then + MbedCheck(mbedtls_ssl_setup(@Fssl, @TCrossMbedTlsSocket(Owner).FSrvConf), 'mbedtls_ssl_setup Accept:') + else + MbedCheck(mbedtls_ssl_setup(@Fssl, @TCrossMbedTlsSocket(Owner).FCliConf), 'mbedtls_ssl_setup Connect:'); + + FSslBIO := SSL_BIO_new(BIO_BIO); + FAppBIO := SSL_BIO_new(BIO_BIO); + BIO_make_bio_pair(FSslBIO, FAppBIO); + + mbedtls_ssl_set_bio(@FSsl, FSslBIO, BIO_net_send, BIO_net_recv, nil); +end; + +destructor TCrossMbedTlsConnection.Destroy; +begin + mbedtls_ssl_free(@FSsl); + BIO_free_all(FSslBIO); + BIO_free_all(FAppBIO); + + inherited; +end; + +procedure TCrossMbedTlsConnection._Lock; +begin + // mbedtls 的多线程支持比 openssl 完善 + // 调用 mbedtls_threading_set_alt 设置了相应的线程同步函数之后不用再自己 + // _Lock _Unlock 了 +// System.TMonitor.Enter(Self); +end; + +procedure TCrossMbedTlsConnection._SendBIOPendingData( + const ACallback: TProc); +var + LConnection: ICrossConnection; + LRetCode: Integer; + LBuffer: TBytesStream; + + procedure _Success; + begin + if (LBuffer <> nil) then + FreeAndNil(LBuffer); + if Assigned(ACallback) then + ACallback(LConnection, True); + end; + +begin + LConnection := Self; + LBuffer := nil; + + {$region '将BIO中已加密的数据全部读到缓存中'} + // 检查 BIO 中是否有数据 + LRetCode := BIO_ctrl_pending(FAppBIO); + if (LRetCode <= 0) then + begin + _Success; + Exit; + end; + + LBuffer := TBytesStream.Create(nil); + while (LRetCode > 0) do + begin + LBuffer.Size := LBuffer.Size + LRetCode; + + // 读取加密后的数据 + LRetCode := BIO_read(FAppBIO, PByte(LBuffer.Memory) + LBuffer.Position, LRetCode); + if (LRetCode <= 0) then Break; + + LBuffer.Position := LBuffer.Position + LRetCode; + + // 检查 BIO 中是否还有数据 + LRetCode := BIO_ctrl_pending(FAppBIO); + end; + + if (LBuffer.Memory = nil) or (LBuffer.Size <= 0) then + begin + _Success; + Exit; + end; + {$endregion} + + {$region '发送缓存中已加密的数据'} + inherited DirectSend(LBuffer.Memory, LBuffer.Size, + procedure(AConnection: ICrossConnection; ASuccess: Boolean) + begin + FreeAndNil(LBuffer); + if Assigned(ACallback) then + ACallback(AConnection, ASuccess); + end); + {$endregion} +end; + +procedure TCrossMbedTlsConnection.DirectSend(ABuffer: Pointer; ACount: Integer; + const ACallback: TProc); +var + LRetCode: Integer; +begin + LRetCode := mbedtls_ssl_write(@FSsl, ABuffer, ACount); + if (LRetCode <> ACount) then + begin + _Log('mbedtls_ssl_write, %d / %d', [LRetCode, ACount]); + end; + + // 将待发送数据加密后发送 + if (MbedCheck(LRetCode, 'mbedtls_ssl_write DirectSend:') > 0) then + _SendBIOPendingData(ACallback); +end; + +function TCrossMbedTlsConnection._SslHandshake: Boolean; +begin + // 开始握手 + Result := (MbedCheck(mbedtls_ssl_handshake(@FSsl), 'mbedtls_ssl_handshake _SslHandshake:') = 0); + _SendBIOPendingData; +end; + +procedure TCrossMbedTlsConnection._Unlock; +begin +// System.TMonitor.Exit(Self); +end; + +{ TCrossMbedTlsSocket } + +constructor TCrossMbedTlsSocket.Create(AIoThreads: Integer); +begin + inherited; + + _InitSslConf; +end; + +destructor TCrossMbedTlsSocket.Destroy; +begin + inherited; + + _FreeSslConf; +end; + +function TCrossMbedTlsSocket.CreateConnection(AOwner: ICrossSocket; + AClientSocket: THandle; AConnectType: TConnectType): ICrossConnection; +begin + Result := TCrossMbedTlsConnection.Create(AOwner, AClientSocket, AConnectType); +end; + +procedure TCrossMbedTlsSocket.SetCertificate(ACertBuf: Pointer; ACertBufSize: Integer); +begin + MbedCheck(mbedtls_x509_crt_parse(@FCert, ACertBuf, ACertBufSize), 'mbedtls_x509_crt_parse SetCertificate:'); + + _UpdateCert; +end; + +procedure TCrossMbedTlsSocket.SetCertificate(const ACertStr: string); +var + LCertBytes: TBytes; +begin + LCertBytes := TEncoding.ANSI.GetBytes(_MbedCert(ACertStr)); + + SetCertificate(Pointer(LCertBytes), Length(LCertBytes)); +end; + +procedure TCrossMbedTlsSocket.SetCertificateFile(const ACertFile: string); +var + LCertBytes: TBytes; +begin + LCertBytes := TFile.ReadAllBytes(ACertFile); + + SetCertificate(Pointer(LCertBytes), Length(LCertBytes)); +end; + +procedure TCrossMbedTlsSocket.SetPrivateKey(APKeyBuf: Pointer; APKeyBufSize: Integer); +begin + MbedCheck(mbedtls_pk_parse_key(@FPKey, APKeyBuf, APKeyBufSize, nil, 0), 'mbedtls_pk_parse_key SetPrivateKey:'); + + _UpdateCert; +end; + +procedure TCrossMbedTlsSocket.SetPrivateKey(const APKeyStr: string); +var + LPKeyBytes: TBytes; +begin + LPKeyBytes := TEncoding.ANSI.GetBytes(_MbedCert(APKeyStr)); + + SetPrivateKey(Pointer(LPKeyBytes), Length(LPKeyBytes)); +end; + +procedure TCrossMbedTlsSocket.SetPrivateKeyFile(const APKeyFile: string); +var + LPKeyBytes: TBytes; +begin + LPKeyBytes := TFile.ReadAllBytes(APKeyFile); + + SetPrivateKey(Pointer(LPKeyBytes), Length(LPKeyBytes)); +end; + +procedure TCrossMbedTlsSocket.TriggerConnected(AConnection: ICrossConnection); +var + LConnection: TCrossMbedTlsConnection; +begin + LConnection := AConnection as TCrossMbedTlsConnection; + + // 网络连接已建立, 等待握手 + LConnection.ConnectStatus := csHandshaking; + + if LConnection._SslHandshake then + begin + LConnection.ConnectStatus := csConnected; + inherited TriggerConnected(AConnection); + end; +end; + +procedure TCrossMbedTlsSocket.TriggerReceived(AConnection: ICrossConnection; + ABuf: Pointer; ALen: Integer); +var + LConnection: TCrossMbedTlsConnection; + LRetCode: Integer; +begin + LConnection := AConnection as TCrossMbedTlsConnection; + + LConnection._Lock; + try + // 将收到的加密数据写入 BIO + LRetCode := BIO_write(LConnection.FAppBIO, ABuf, ALen); + if (LRetCode <= 0) then + begin + _Log('BIO_write, error: %d', [LRetCode]); + LConnection.Close; + Exit; + end; + + if (LRetCode <> ALen) then + begin + _Log('BIO_write, %d / %d', [LRetCode, ALen]); + end; + + // 握手 + if (LConnection.ConnectStatus = csHandshaking) then + begin + // 已完成握手才视为连接真正建立 + if LConnection._SslHandshake then + begin + LConnection.ConnectStatus := csConnected; + inherited TriggerConnected(AConnection); + end else + Exit; + end; + + while True do + begin + // 读取解密后的数据 + LRetCode := mbedtls_ssl_read(@LConnection.FSsl, @FSslInBuf, SSL_BUF_SIZE); + + if (LRetCode > 0) then + begin + inherited TriggerReceived(AConnection, @FSslInBuf, LRetCode); + end else + begin + case LRetCode of + MBEDTLS_ERR_SSL_WANT_READ, MBEDTLS_ERR_SSL_WANT_WRITE:; + else + _Log('mbedtls_ssl_read, error: %d', [LRetCode]); + LConnection.Close; + end; + Break; + end; + end; + finally + LConnection._Unlock; + end; +end; + +procedure TCrossMbedTlsSocket._FreeSslConf; +begin + mbedtls_ssl_config_free(@FSrvConf); + mbedtls_ssl_config_free(@FCliConf); + + mbedtls_x509_crt_free(@FCert); + mbedtls_pk_free(@FPKey); + + mbedtls_ctr_drbg_free(@FCtrDrbg); + mbedtls_entropy_free(@FEntropy); + mbedtls_ssl_cache_free(@FCache); +end; + +procedure TCrossMbedTlsSocket._InitSslConf; +begin + mbedtls_x509_crt_init(@FCert); + mbedtls_pk_init(@FPKey); + mbedtls_ctr_drbg_init(@FCtrDrbg); + mbedtls_entropy_init(@FEntropy); + mbedtls_ssl_cache_init(@FCache); + + MbedCheck(mbedtls_ctr_drbg_seed(@FCtrDrbg, mbedtls_entropy_func, @FEntropy, nil, 0), 'mbedtls_ctr_drbg_seed:'); + + {$region '服务端SSL配置'} + mbedtls_ssl_config_init(@FSrvConf); + mbedtls_ssl_conf_rng(@FSrvConf, mbedtls_ctr_drbg_random, @FCtrDrbg); + mbedtls_ssl_conf_authmode(@FSrvConf, MBEDTLS_SSL_VERIFY_OPTIONAL); + mbedtls_ssl_conf_session_cache(@FSrvConf, @FCache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set); // 仅服务端有效 + mbedtls_ssl_conf_ciphersuites(@FSrvConf, PInteger(@DEFAULT_CIPHERSUITES_SERVER)); + mbedtls_ssl_conf_min_version(@FSrvConf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); // TLS v1.2 + MbedCheck(mbedtls_ssl_config_defaults(@FSrvConf, + MBEDTLS_SSL_IS_SERVER, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT), 'mbedtls_ssl_config_defaults FSrvConf:'); + {$endregion} + + {$region '客户端SSL配置'} + mbedtls_ssl_config_init(@FCliConf); + mbedtls_ssl_conf_rng(@FCliConf, mbedtls_ctr_drbg_random, @FCtrDrbg); + mbedtls_ssl_conf_authmode(@FCliConf, MBEDTLS_SSL_VERIFY_OPTIONAL); + MbedCheck(mbedtls_ssl_config_defaults(@FCliConf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT), 'mbedtls_ssl_config_defaults FCliConf:'); + mbedtls_ssl_conf_ciphersuites(@FCliConf, PInteger(@DEFAULT_CIPHERSUITES_CLIENT)); + {$endregion} +end; + +function TCrossMbedTlsSocket._MbedCert(const ACertStr: string): string; +begin + // MbedTls 要求证书必须以 #0 结束 + if ACertStr.EndsWith(#0) then + Result := ACertStr + else + Result := ACertStr + #0; +end; + +procedure TCrossMbedTlsSocket._UpdateCert; +begin + // 尚未加载证书 + if (FCert.version = 0) then Exit; + + mbedtls_ssl_conf_ca_chain(@FCliConf, @FCert, nil); + + // 尚未加载私钥 + if (FPKey.pk_info = nil) then Exit; + + if (FCert.next <> nil) then + mbedtls_ssl_conf_ca_chain(@FSrvConf, FCert.next, nil); + + MbedCheck(mbedtls_ssl_conf_own_cert(@FSrvConf, @FCert, @FPKey), 'mbedtls_ssl_conf_own_cert:'); +end; + +end. diff --git a/Net/Net.CrossSslSocket.OpenSSL.pas b/Net/Net.CrossSslSocket.OpenSSL.pas new file mode 100644 index 0000000..a54007f --- /dev/null +++ b/Net/Net.CrossSslSocket.OpenSSL.pas @@ -0,0 +1,507 @@ +{******************************************************************************} +{ } +{ Delphi cross platform socket library } +{ } +{ Copyright (c) 2017 WiNDDRiVER(soulawing@gmail.com) } +{ } +{ Homepage: https://github.com/winddriver/Delphi-Cross-Socket } +{ } +{******************************************************************************} +unit Net.CrossSslSocket.OpenSSL; + +{ + SSL通讯基本流程: + 1. 当连接建立时进行 SSL 握手, 收到数据时也要检查握手状态 + 2. 发送数据: 用 SSL_write 写入原数据, BIO_read 读取加密后的数据进行发送 + 3. 接收数据: 用 BIO_write 写入收到的数据, 用 SSL_read 读取解密后的数据 + + OpenSSL 的 SSL 对象不是线程安全的!!!!!!!!!!!!!!!!! + 即便初始化 OpenSSL 时设置了那几个线程相关的回调也一样, + 一定要保证同一时间不能有两个或以上的线程访问到同一个 SSL 对象 + 或者与其绑定的 BIO 对象 + + 由于收发数据需要解密及加密, 还需要用临界区保护 SSL 对象, + 所以效率比不使用 SSL 时会下降很多, 这是无法避免的 + + 传输层安全协议: + https://zh.wikipedia.org/wiki/%E5%82%B3%E8%BC%B8%E5%B1%A4%E5%AE%89%E5%85%A8%E5%8D%94%E8%AD%B0 +} + +interface + +uses + System.SysUtils, + System.Classes, + Net.CrossSocket.Base, + Net.CrossSocket, + Net.CrossSslSocket.Base, + Net.OpenSSL; + +type + TCrossOpenSslConnection = class(TCrossConnection) + private + FSsl: PSSL; + FBIOIn, FBIOOut: PBIO; + FSslLock: TObject; + + procedure _SslLock; inline; + procedure _SslUnlock; inline; + + function _SslHandshake: Boolean; + procedure _WriteBioToSocket(const ACallback: TProc = nil); + protected + procedure DirectSend(ABuffer: Pointer; ACount: Integer; + const ACallback: TProc = nil); override; + public + constructor Create(AOwner: ICrossSocket; AClientSocket: THandle; + AConnectType: TConnectType); override; + destructor Destroy; override; + end; + + /// + /// 若要继承该类, 请重载 LogicXXX, 而不是 TriggerXXX + /// + TCrossOpenSslSocket = class(TCrossSocket, ICrossSslSocket) + private const + SSL_BUF_SIZE = 32768; + private class threadvar + FSslInBuf: array [0..SSL_BUF_SIZE-1] of Byte; + private + FSslCtx: PSSL_CTX; + + procedure _InitSslCtx; + procedure _FreeSslCtx; + protected + procedure TriggerConnected(AConnection: ICrossConnection); override; + procedure TriggerReceived(AConnection: ICrossConnection; ABuf: Pointer; ALen: Integer); override; + + function CreateConnection(AOwner: ICrossSocket; AClientSocket: THandle; + AConnectType: TConnectType): ICrossConnection; override; + public + constructor Create(AIoThreads: Integer); override; + destructor Destroy; override; + + procedure SetCertificate(ACertBuf: Pointer; ACertBufSize: Integer); overload; + procedure SetCertificate(const ACertStr: string); overload; + procedure SetCertificateFile(const ACertFile: string); + + procedure SetPrivateKey(APKeyBuf: Pointer; APKeyBufSize: Integer); overload; + procedure SetPrivateKey(const APKeyStr: string); overload; + procedure SetPrivateKeyFile(const APKeyFile: string); + end; + +implementation + +{ TCrossOpenSslConnection } + +constructor TCrossOpenSslConnection.Create(AOwner: ICrossSocket; + AClientSocket: THandle; AConnectType: TConnectType); +begin + inherited; + + FSslLock := TObject.Create; + + FSsl := SSL_new(TCrossOpenSslSocket(Owner).FSslCtx); + FBIOIn := BIO_new(BIO_s_mem()); + FBIOOut := BIO_new(BIO_s_mem()); + SSL_set_bio(FSsl, FBIOIn, FBIOOut); + + if (ConnectType = ctAccept) then + SSL_set_accept_state(FSsl) // 服务端连接 + else + SSL_set_connect_state(FSsl); // 客户端连接 +end; + +destructor TCrossOpenSslConnection.Destroy; +begin + _SslLock; + try + if (SSL_shutdown(FSsl) = 0) then + SSL_shutdown(FSsl); + SSL_free(FSsl); + finally + _SslUnlock; + end; + FreeAndNil(FSslLock); + + inherited; +end; + +procedure TCrossOpenSslConnection._WriteBioToSocket( + const ACallback: TProc); +var + LConnection: ICrossConnection; + ret, error: Integer; + LBuffer: TBytesStream; + + procedure _Success; + begin + if (LBuffer <> nil) then + FreeAndNil(LBuffer); + if Assigned(ACallback) then + ACallback(LConnection, True); + end; + + procedure _Failed; + begin + if (LBuffer <> nil) then + FreeAndNil(LBuffer); + LConnection.Close; + if Assigned(ACallback) then + ACallback(LConnection, False); + end; + +begin + LConnection := Self; + LBuffer := nil; + + {$region '将BIO中已加密的数据全部读到缓存中'} + // 从BIO中读取数据这一段必须全读出来再发送 + // 因为SSL对象本身并不是线程安全的, 如果读取数据的同时, 另一个线程尝试操作SSL对象 + // 就会引起异常, 所以这里将读取数据和发送数据分成两部分, 将数据全读出来之后 + // 再调用异步发送, 方便在外层包裹加锁 + ret := BIO_pending(FBIOOut); + if (ret <= 0) then + begin + _Success; + Exit; + end; + + LBuffer := TBytesStream.Create(nil); + while (ret > 0) do + begin + LBuffer.Size := LBuffer.Size + ret; + + // 读取加密后的数据 + ret := BIO_read(FBIOOut, PByte(LBuffer.Memory) + LBuffer.Position, ret); + error := SSL_get_error(FSsl, ret); + if ssl_is_fatal_error(error) then + begin + _Failed; + Exit; + end; + + if (ret <= 0) then Break; + + LBuffer.Position := LBuffer.Position + ret; + + // 检查 BIO 中是否有数据 + ret := BIO_pending(FBIOOut); + end; + + if (LBuffer.Memory = nil) or (LBuffer.Size <= 0) then + begin + _Success; + Exit; + end; + {$endregion} + + {$region '发送缓存中已加密的数据'} + inherited DirectSend(LBuffer.Memory, LBuffer.Size, + procedure(AConnection: ICrossConnection; ASuccess: Boolean) + begin + FreeAndNil(LBuffer); + if Assigned(ACallback) then + ACallback(AConnection, ASuccess); + end); + {$endregion} +end; + +procedure TCrossOpenSslConnection.DirectSend(ABuffer: Pointer; ACount: Integer; + const ACallback: TProc); +var + LConnection: ICrossConnection; + ret, error: Integer; + + procedure _Failed; + begin + if Assigned(ACallback) then + ACallback(LConnection, False); + end; + +begin + LConnection := Self; + + // 将待发送数据加密 + // SSL_write 默认会将全部数据写入成功才返回, + // 除非调用 SSL_CTX_set_mode 设置了 SSL_MODE_ENABLE_PARTIAL_WRITE 参数 + // 才会出现部分写入成功即返回的情况。这里并没有设置该参数,所以无需做 + // 部分数据的处理,只需要一次 SSL_Write 调用即可。 + _SslLock; + try + ret := SSL_write(FSsl, ABuffer, ACount); + if (ret > 0) then + _WriteBioToSocket(ACallback) + else + begin + error := SSL_get_error(FSsl, ret); + _Log('SSL_write error %d %s', [error, ssl_error_message(error)]); + case error of + SSL_ERROR_WANT_READ:; + SSL_ERROR_WANT_WRITE: _WriteBioToSocket; + else + _Failed; + end; + end; + finally + _SslUnlock; + end; +end; + +procedure TCrossOpenSslConnection._SslLock; +begin + TMonitor.Enter(FSslLock); +end; + +procedure TCrossOpenSslConnection._SslUnlock; +begin + TMonitor.Exit(FSslLock); +end; + +function TCrossOpenSslConnection._SslHandshake: Boolean; +var + ret, error: Integer; +begin + Result := False; + + _SslLock; + try + // 开始握手 + ret := SSL_do_handshake(FSsl); + if (ret = 1) then + begin + _WriteBioToSocket; + Exit(True); + end; + + error := SSL_get_error(FSsl, ret); + if ssl_is_fatal_error(error) then + begin + {$IFDEF DEBUG} + _Log('SSL_do_handshake error %s', [ssl_error_message(error)]); + {$ENDIF} + Close; + end else + _WriteBioToSocket; + finally + _SslUnlock; + end; +end; + +{ TCrossOpenSslSocket } + +constructor TCrossOpenSslSocket.Create(AIoThreads: Integer); +begin + inherited; + + TSSLTools.LoadSSL; + _InitSslCtx; +end; + +destructor TCrossOpenSslSocket.Destroy; +begin + inherited; + + _FreeSslCtx; + TSSLTools.UnloadSSL; +end; + +function TCrossOpenSslSocket.CreateConnection(AOwner: ICrossSocket; + AClientSocket: THandle; AConnectType: TConnectType): ICrossConnection; +begin + Result := TCrossOpenSslConnection.Create(AOwner, AClientSocket, AConnectType); +end; + +procedure TCrossOpenSslSocket._InitSslCtx; +var + LEcdh: PEC_KEY; +begin + if (FSslCtx <> nil) then Exit; + + FSslCtx := TSSLTools.NewCTX(SSLv23_method()); + + SSL_CTX_set_verify(FSslCtx, SSL_VERIFY_NONE, nil); + + SSL_CTX_set_mode(FSslCtx, SSL_MODE_AUTO_RETRY); + + {$region '采用新型加密套件进行加密'} + SSL_CTX_set_options(FSslCtx, + // 不使用已经不安全的 SSLv2 和 SSv3 + SSL_OP_NO_SSLv2 or SSL_OP_NO_SSLv3 or + // 启用各种漏洞解决方案(适用于 0.9.7 之前的版本) + SSL_OP_ALL or + // 总是使用 SSL_CTX_set_tmp_ecdh/SSL_set_tmp_ecdh 设置的参数创建新 KEY + SSL_OP_SINGLE_ECDH_USE or + // 根据服务器偏好选择加密套件 + SSL_OP_CIPHER_SERVER_PREFERENCE + ); + + // 设置加密套件的使用顺序 + SSL_CTX_set_cipher_list(FSslCtx, + // from nodejs(node_constants.h) + // #define DEFAULT_CIPHER_LIST_CORE + 'ECDHE-ECDSA-AES128-GCM-SHA256:' + + 'ECDHE-RSA-AES128-GCM-SHA256:' + + 'ECDHE-RSA-AES256-GCM-SHA384:' + + 'ECDHE-ECDSA-AES256-GCM-SHA384:' + + 'DHE-RSA-AES128-GCM-SHA256:' + + 'ECDHE-RSA-AES128-SHA256:' + + 'DHE-RSA-AES128-SHA256:' + + 'ECDHE-RSA-AES256-SHA384:' + + 'DHE-RSA-AES256-SHA384:' + + 'ECDHE-RSA-AES256-SHA256:' + + 'DHE-RSA-AES256-SHA256:' + + 'HIGH:' + + '!aNULL:' + + '!eNULL:' + + '!EXPORT:' + + '!DES:' + + '!RC4:' + + '!MD5:' + + '!PSK:' + + '!SRP:' + + '!CAMELLIA' + ); + + LEcdh := EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + if (LEcdh <> nil) then + begin + SSL_CTX_set_tmp_ecdh(FSslCtx, LEcdh); + EC_KEY_free(LEcdh); + end; + {$endregion} +end; + +procedure TCrossOpenSslSocket._FreeSslCtx; +begin + if (FSslCtx = nil) then Exit; + + TSSLTools.FreeCTX(FSslCtx); +end; + +procedure TCrossOpenSslSocket.SetCertificate(ACertBuf: Pointer; + ACertBufSize: Integer); +begin + TSSLTools.SetCertificate(FSslCtx, ACertBuf, ACertBufSize); +end; + +procedure TCrossOpenSslSocket.SetCertificate(const ACertStr: string); +begin + TSSLTools.SetCertificate(FSslCtx, ACertStr); +end; + +procedure TCrossOpenSslSocket.SetCertificateFile(const ACertFile: string); +begin + TSSLTools.SetCertificateFile(FSslCtx, ACertFile); +end; + +procedure TCrossOpenSslSocket.SetPrivateKey(APKeyBuf: Pointer; + APKeyBufSize: Integer); +begin + TSSLTools.SetPrivateKey(FSslCtx, APKeyBuf, APKeyBufSize); +end; + +procedure TCrossOpenSslSocket.SetPrivateKey(const APKeyStr: string); +begin + TSSLTools.SetPrivateKey(FSslCtx, APKeyStr); +end; + +procedure TCrossOpenSslSocket.SetPrivateKeyFile(const APKeyFile: string); +begin + TSSLTools.SetPrivateKeyFile(FSslCtx, APKeyFile); +end; + +procedure TCrossOpenSslSocket.TriggerConnected(AConnection: ICrossConnection); +var + LConnection: TCrossOpenSslConnection; +begin + LConnection := AConnection as TCrossOpenSslConnection; + + LConnection._SslLock; + try + // 网络连接已建立, 等待握手 + LConnection.ConnectStatus := csHandshaking; + + // 已完成握手才视为连接真正建立 + if LConnection._SslHandshake then + begin + LConnection.ConnectStatus := csConnected; + inherited TriggerConnected(AConnection); + end; + finally + LConnection._SslUnlock; + end; +end; + +procedure TCrossOpenSslSocket.TriggerReceived(AConnection: ICrossConnection; + ABuf: Pointer; ALen: Integer); +var + LConnection: TCrossOpenSslConnection; + ret, error: Integer; + LBuffer: TBytesStream; +begin + LConnection := AConnection as TCrossOpenSslConnection; + LConnection._SslLock; + try + // 将收到的加密数据写入 BIO, 让 OpenSSL 对其解密 + while True do + begin + ret := BIO_write(LConnection.FBIOIn, ABuf, ALen); +// _Log('recv %d, bio_write %d', [ALen, ret]); + if (ret > 0) then Break; + + if not BIO_should_retry(LConnection.FBIOIn) then + begin + LConnection.Close; + Exit; + end; + end; + + // 未完成初始化, 继续握手 + if not SSL_is_init_finished(LConnection.FSsl) then + begin + // 已完成握手才视为连接真正建立 + if LConnection._SslHandshake + and (LConnection.ConnectStatus = csHandshaking) then + begin + LConnection.ConnectStatus := csConnected; + inherited TriggerConnected(AConnection); + end; + Exit; + end; + + LBuffer := TBytesStream.Create(nil); + try + while True do + begin + // 貌似每次读出来的数据都不会超过 16K + ret := SSL_read(LConnection.FSsl, @FSslInBuf[0], SSL_BUF_SIZE); + if (ret > 0) then + LBuffer.Write(FSslInBuf[0], ret) + else + begin + error := SSL_get_error(LConnection.FSsl, ret); +// _Log('SSL_read error %d %s', [error, ssl_error_message(error)]); + + if ssl_is_fatal_error(error) then + begin + {$IFDEF DEBUG} + _Log('SSL_read error %d %s', [error, ssl_error_message(error)]); + {$ENDIF} + LConnection.Close; + end; + Break; + end; + end; + + if (LBuffer.Size > 0) then + inherited TriggerReceived(AConnection, LBuffer.Memory, LBuffer.Size); + finally + FreeAndNil(LBuffer); + end; + finally + LConnection._SslUnlock; + end; +end; + +end. diff --git a/Net/Net.CrossSslSocket.pas b/Net/Net.CrossSslSocket.pas index 45e42db..de277ba 100644 --- a/Net/Net.CrossSslSocket.pas +++ b/Net/Net.CrossSslSocket.pas @@ -1,707 +1,31 @@ -{******************************************************************************} -{ } -{ Delphi cross platform socket library } -{ } -{ Copyright (c) 2017 WiNDDRiVER(soulawing@gmail.com) } -{ } -{ Homepage: https://github.com/winddriver/Delphi-Cross-Socket } -{ } -{******************************************************************************} unit Net.CrossSslSocket; -{ - SSL通讯基本流程: - 1. 当连接建立时进行 SSL 握手, 收到数据时也要检查握手状态 - 2. 发送数据: 用 SSL_write 写入原数据, BIO_read 读取加密后的数据进行发送 - 3. 接收数据: 用 BIO_write 写入收到的数据, 用 SSL_read 读取解密后的数据 - - OpenSSL 的 SSL 对象不是线程安全的!!!!!!!!!!!!!!!!! - 即便初始化 OpenSSL 时设置了那几个线程相关的回调也一样, - 一定要保证同一时间不能有两个或以上的线程访问到同一个 SSL 对象 - 或者与其绑定的 BIO 对象 - - 由于收发数据需要解密及加密, 还需要用临界区保护 SSL 对象, - 所以效率比不使用 SSL 时会下降很多, 这是无法避免的 - - 传输层安全协议: - https://zh.wikipedia.org/wiki/%E5%82%B3%E8%BC%B8%E5%B1%A4%E5%AE%89%E5%85%A8%E5%8D%94%E8%AD%B0 -} - interface uses - System.SysUtils, - System.Classes, Net.CrossSocket.Base, - Net.CrossSocket, - Net.OpenSSL; + Net.CrossSslSocket.Base + {$IFDEF __MBED_TLS__} + ,Net.CrossSslSocket.MbedTls + {$ELSE} + ,Net.CrossSslSocket.OpenSSL + {$ENDIF}; type - /// - /// - /// 加密方法 - /// - /// - /// TLS 比 SSL 安全性高一些 - /// - /// - /// 目前 SSLv2 及 SSLv3 已被淘汰, 在新的 OpenSSL 库中即便使用 SSLxx 也会被自动映射到 TLSxx - /// - /// - /// OpenSSL 1.01+ 支持 TLS1.2 - /// - /// - /// - /// - /// - /// 若要保持最好的兼容性, 请在服务端使用 SSv23_server, 这种情况服务端会根据客户端的支持情况使用最合适的加密套件, - /// 同时兼容 TLS1.0 TLS1.1, TLS1.2; - /// - /// - /// 若要最高的安全性, 不考虑兼容, 请在服务端使用 TLSv1_2_server - /// - /// - /// - TSslMethod = ( - /// - /// OpenSSL 0.9+, 客户端 + 服务端 - /// - SSLv23, - - /// - /// OpenSSL 0.9+, 客户端 - /// - SSLv23_client, - - /// - /// OpenSSL 0.9+, 服务端 - /// - SSLv23_server, - - /// - /// OpenSSL 0.9+, 客户端 + 服务端 - /// - TLSv1, - - /// - /// OpenSSL 0.9+, 客户端 - /// - TLSv1_client, - - /// - /// OpenSSL 0.9+, 服务端 - /// - TLSv1_server, - - /// - /// OpenSSL 1.0.1+, 客户端 + 服务端 - /// - TLSv1_2, - - /// - /// OpenSSL 1.0.1+, 客户端 - /// - TLSv1_2_client, - - /// - /// OpenSSL 1.0.1+, 服务端 - /// - TLSv1_2_server); - - /// - /// SSL Socket - /// - /// - /// 正确的使用步骤: - /// - /// - /// InitSslCtx - /// - /// - /// SetCertificate 或 SetCertificateFile - /// - /// - /// SetPrivateKey 或 SetPrivateKeyFile - /// - /// - /// Connect / Listen - /// - /// - /// - ICrossSslSocket = interface(ICrossSocket) - ['{A4765486-A0F1-4EFD-BC39-FA16AED21A6A}'] - /// - /// OpenSSL 库版本号 - /// - function SSLVersion: Longword; - - /// - /// 初始化 SSL 上下文对象 - /// - /// - /// 加密方法 - /// - procedure InitSslCtx(ASslMethod: TSslMethod); - - /// - /// 释放 SSL 上下文对象 - /// - procedure FreeSslCtx; - - /// - /// 从内存加载证书 - /// - /// - /// 证书缓冲区 - /// - /// - /// 证书缓冲区大小 - /// - procedure SetCertificate(ACertBuf: Pointer; ACertBufSize: Integer); overload; - - /// - /// 从字符串加载证书 - /// - /// - /// 证书字符串 - /// - procedure SetCertificate(const ACertStr: string); overload; - - /// - /// 从文件加载证书 - /// - /// - /// 证书文件 - /// - procedure SetCertificateFile(const ACertFile: string); - - /// - /// 从内存加载私钥 - /// - /// - /// 私钥缓冲区 - /// - /// - /// 私钥缓冲区大小 - /// - procedure SetPrivateKey(APKeyBuf: Pointer; APKeyBufSize: Integer); overload; - - /// - /// 从字符串加载私钥 - /// - /// - /// 私钥字符串 - /// - procedure SetPrivateKey(const APKeyStr: string); overload; - - /// - /// 从文件加载私钥 - /// - /// - /// 私钥文件 - /// - procedure SetPrivateKeyFile(const APKeyFile: string); - end; - - TCrossSslConnection = class(TCrossConnection) - private - FSsl: PSSL; - FBIOIn, FBIOOut: PBIO; - FSslLock: TObject; - - procedure _SslLock; inline; - procedure _SslUnlock; inline; - - function _SslHandshake: Boolean; - procedure _WriteBioToSocket(const ACallback: TProc = nil); - protected - procedure DirectSend(ABuffer: Pointer; ACount: Integer; - const ACallback: TProc = nil); override; - public - constructor Create(AOwner: ICrossSocket; AClientSocket: THandle; - AConnectType: TConnectType); override; - destructor Destroy; override; - end; - - /// - /// 若要继承该类, 请重载 LogicXXX, 而不是 TriggerXXX - /// - TCrossSslSocket = class(TCrossSocket, ICrossSslSocket) - private const - SSL_BUF_SIZE = 32768; - private class threadvar - FSslInBuf: array [0..SSL_BUF_SIZE-1] of Byte; - private - FSslCtx: PSSL_CTX; - protected - procedure TriggerConnected(AConnection: ICrossConnection); override; - procedure TriggerReceived(AConnection: ICrossConnection; ABuf: Pointer; ALen: Integer); override; - - function CreateConnection(AOwner: ICrossSocket; AClientSocket: THandle; - AConnectType: TConnectType): ICrossConnection; override; - public - constructor Create(AIoThreads: Integer); override; - destructor Destroy; override; - - function SSLVersion: Longword; - - procedure InitSslCtx(ASslMethod: TSslMethod); - procedure FreeSslCtx; - - procedure SetCertificate(ACertBuf: Pointer; ACertBufSize: Integer); overload; - procedure SetCertificate(const ACertStr: string); overload; - procedure SetCertificateFile(const ACertFile: string); - - procedure SetPrivateKey(APKeyBuf: Pointer; APKeyBufSize: Integer); overload; - procedure SetPrivateKey(const APKeyStr: string); overload; - procedure SetPrivateKeyFile(const APKeyFile: string); - end; + TCrossSslConnection = + {$IFDEF __MBED_TLS__} + TCrossMbedTlsConnection + {$ELSE} + TCrossOpenSslConnection + {$ENDIF}; + + TCrossSslSocket = + {$IFDEF __MBED_TLS__} + TCrossMbedTlsSocket + {$ELSE} + TCrossOpenSslSocket + {$ENDIF}; implementation -{ TCrossSslConnection } - -constructor TCrossSslConnection.Create(AOwner: ICrossSocket; - AClientSocket: THandle; AConnectType: TConnectType); -begin - inherited; - - FSslLock := TObject.Create; - - FSsl := SSL_new(TCrossSslSocket(Owner).FSslCtx); - FBIOIn := BIO_new(BIO_s_mem()); - FBIOOut := BIO_new(BIO_s_mem()); - SSL_set_bio(FSsl, FBIOIn, FBIOOut); - - if (ConnectType = ctAccept) then - SSL_set_accept_state(FSsl) // 服务端连接 - else - SSL_set_connect_state(FSsl); // 客户端连接 -end; - -destructor TCrossSslConnection.Destroy; -begin - _SslLock; - try - if (SSL_shutdown(FSsl) = 0) then - SSL_shutdown(FSsl); - SSL_free(FSsl); - finally - _SslUnlock; - end; - FreeAndNil(FSslLock); - - inherited; -end; - -procedure TCrossSslConnection._WriteBioToSocket( - const ACallback: TProc); -var - LConnection: ICrossConnection; - ret, error: Integer; - LBuffer: TBytesStream; - - procedure _Success; - begin - if (LBuffer <> nil) then - FreeAndNil(LBuffer); - if Assigned(ACallback) then - ACallback(LConnection, True); - end; - - procedure _Failed; - begin - if (LBuffer <> nil) then - FreeAndNil(LBuffer); - LConnection.Close; - if Assigned(ACallback) then - ACallback(LConnection, False); - end; - -begin - LConnection := Self; - LBuffer := nil; - - {$region '将BIO中已加密的数据全部读到缓存中'} - // 从BIO中读取数据这一段必须全读出来再发送 - // 因为SSL对象本身并不是线程安全的, 如果读取数据的同时, 另一个线程尝试操作SSL对象 - // 就会引起异常, 所以这里将读取数据和发送数据分成两部分, 将数据全读出来之后 - // 再调用异步发送, 方便在外层包裹加锁 - ret := BIO_pending(FBIOOut); - if (ret <= 0) then - begin - _Success; - Exit; - end; - - LBuffer := TBytesStream.Create(nil); - while (ret > 0) do - begin - LBuffer.Size := LBuffer.Size + ret; - - // 读取加密后的数据 - ret := BIO_read(FBIOOut, PByte(LBuffer.Memory) + LBuffer.Position, ret); - error := SSL_get_error(FSsl, ret); - if ssl_is_fatal_error(error) then - begin - _Failed; - Exit; - end; - - if (ret <= 0) then Break; - - LBuffer.Position := LBuffer.Position + ret; - - // 检查 BIO 中是否有数据 - ret := BIO_pending(FBIOOut); - end; - - if (LBuffer.Memory = nil) or (LBuffer.Size <= 0) then - begin - _Success; - Exit; - end; - {$endregion} - - {$region '发送缓存中已加密的数据'} - inherited DirectSend(LBuffer.Memory, LBuffer.Size, - procedure(AConnection: ICrossConnection; ASuccess: Boolean) - begin - FreeAndNil(LBuffer); - if Assigned(ACallback) then - ACallback(AConnection, ASuccess); - end); - {$endregion} -end; - -procedure TCrossSslConnection.DirectSend(ABuffer: Pointer; ACount: Integer; - const ACallback: TProc); -var - LConnection: ICrossConnection; - ret, error: Integer; - - procedure _Failed; - begin - if Assigned(ACallback) then - ACallback(LConnection, False); - end; - -begin - LConnection := Self; - - // 将待发送数据加密 - // SSL_write 默认会将全部数据写入成功才返回, - // 除非调用 SSL_CTX_set_mode 设置了 SSL_MODE_ENABLE_PARTIAL_WRITE 参数 - // 才会出现部分写入成功即返回的情况。这里并没有设置该参数,所以无需做 - // 部分数据的处理,只需要一次 SSL_Write 调用即可。 - _SslLock; - try - ret := SSL_write(FSsl, ABuffer, ACount); - if (ret > 0) then - _WriteBioToSocket(ACallback) - else - begin - error := SSL_get_error(FSsl, ret); - _Log('SSL_write error %d %s', [error, ssl_error_message(error)]); - case error of - SSL_ERROR_WANT_READ:; - SSL_ERROR_WANT_WRITE: _WriteBioToSocket; - else - _Failed; - end; - end; - finally - _SslUnlock; - end; -end; - -procedure TCrossSslConnection._SslLock; -begin - TMonitor.Enter(FSslLock); -end; - -procedure TCrossSslConnection._SslUnlock; -begin - TMonitor.Exit(FSslLock); -end; - -function TCrossSslConnection._SslHandshake: Boolean; -var - ret, error: Integer; -begin - Result := False; - - _SslLock; - try - // 开始握手 - ret := SSL_do_handshake(FSsl); - if (ret = 1) then - begin - _WriteBioToSocket; - Exit(True); - end; - - error := SSL_get_error(FSsl, ret); - if ssl_is_fatal_error(error) then - begin - {$IFDEF DEBUG} - _Log('SSL_do_handshake error %s', [ssl_error_message(error)]); - {$ENDIF} - Close; - end else - _WriteBioToSocket; - finally - _SslUnlock; - end; -end; - -{ TCrossSslSocket } - -constructor TCrossSslSocket.Create(AIoThreads: Integer); -begin - inherited; - - TSSLTools.LoadSSL; -end; - -destructor TCrossSslSocket.Destroy; -begin - inherited; - - FreeSslCtx; - TSSLTools.UnloadSSL; -end; - -function TCrossSslSocket.CreateConnection(AOwner: ICrossSocket; - AClientSocket: THandle; AConnectType: TConnectType): ICrossConnection; -begin - Result := TCrossSslConnection.Create(AOwner, AClientSocket, AConnectType); -end; - -procedure TCrossSslSocket.InitSslCtx(ASslMethod: TSslMethod); -var - LEcdh: PEC_KEY; -begin - if (FSslCtx <> nil) then Exit; - - case ASslMethod of - SSLv23: - FSslCtx := TSSLTools.NewCTX(SSLv23_method()); - - SSLv23_client: - FSslCtx := TSSLTools.NewCTX(SSLv23_client_method()); - - SSLv23_server: - FSslCtx := TSSLTools.NewCTX(SSLv23_server_method()); - - TLSv1: - FSslCtx := TSSLTools.NewCTX(TLSv1_method()); - - TLSv1_client: - FSslCtx := TSSLTools.NewCTX(TLSv1_client_method()); - - TLSv1_server: - FSslCtx := TSSLTools.NewCTX(TLSv1_server_method()); - - TLSv1_2: - FSslCtx := TSSLTools.NewCTX(TLSv1_2_method()); - - TLSv1_2_client: - FSslCtx := TSSLTools.NewCTX(TLSv1_2_client_method()); - - TLSv1_2_server: - FSslCtx := TSSLTools.NewCTX(TLSv1_2_server_method()); - else - FSslCtx := TSSLTools.NewCTX(SSLv23_method()); - end; - - SSL_CTX_set_verify(FSslCtx, SSL_VERIFY_NONE, nil); - - SSL_CTX_set_mode(FSslCtx, SSL_MODE_AUTO_RETRY); - - {$region '采用新型加密套件进行加密'} - SSL_CTX_set_options(FSslCtx, - // 不使用已经不安全的 SSLv2 和 SSv3 - SSL_OP_NO_SSLv2 or SSL_OP_NO_SSLv3 or - // 启用各种漏洞解决方案(适用于 0.9.7 之前的版本) - SSL_OP_ALL or - // 总是使用 SSL_CTX_set_tmp_ecdh/SSL_set_tmp_ecdh 设置的参数创建新 KEY - SSL_OP_SINGLE_ECDH_USE or - // 根据服务器偏好选择加密套件 - SSL_OP_CIPHER_SERVER_PREFERENCE - ); - - // 设置加密套件的使用顺序 - SSL_CTX_set_cipher_list(FSslCtx, - // from nodejs(node_constants.h) - // #define DEFAULT_CIPHER_LIST_CORE - 'ECDHE-ECDSA-AES128-GCM-SHA256:' + - 'ECDHE-RSA-AES128-GCM-SHA256:' + - 'ECDHE-RSA-AES256-GCM-SHA384:' + - 'ECDHE-ECDSA-AES256-GCM-SHA384:' + - 'DHE-RSA-AES128-GCM-SHA256:' + - 'ECDHE-RSA-AES128-SHA256:' + - 'DHE-RSA-AES128-SHA256:' + - 'ECDHE-RSA-AES256-SHA384:' + - 'DHE-RSA-AES256-SHA384:' + - 'ECDHE-RSA-AES256-SHA256:' + - 'DHE-RSA-AES256-SHA256:' + - 'HIGH:' + - '!aNULL:' + - '!eNULL:' + - '!EXPORT:' + - '!DES:' + - '!RC4:' + - '!MD5:' + - '!PSK:' + - '!SRP:' + - '!CAMELLIA' - ); - - LEcdh := EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); - if (LEcdh <> nil) then - begin - SSL_CTX_set_tmp_ecdh(FSslCtx, LEcdh); - EC_KEY_free(LEcdh); - end; - {$endregion} -end; - -function TCrossSslSocket.SSLVersion: Longword; -begin - Result := TSSLTools.SSLVersion; -end; - -procedure TCrossSslSocket.FreeSslCtx; -begin - if (FSslCtx = nil) then Exit; - - TSSLTools.FreeCTX(FSslCtx); -end; - -procedure TCrossSslSocket.SetCertificate(ACertBuf: Pointer; - ACertBufSize: Integer); -begin - TSSLTools.SetCertificate(FSslCtx, ACertBuf, ACertBufSize); -end; - -procedure TCrossSslSocket.SetCertificate(const ACertStr: string); -begin - TSSLTools.SetCertificate(FSslCtx, ACertStr); -end; - -procedure TCrossSslSocket.SetCertificateFile(const ACertFile: string); -begin - TSSLTools.SetCertificateFile(FSslCtx, ACertFile); -end; - -procedure TCrossSslSocket.SetPrivateKey(APKeyBuf: Pointer; - APKeyBufSize: Integer); -begin - TSSLTools.SetPrivateKey(FSslCtx, APKeyBuf, APKeyBufSize); -end; - -procedure TCrossSslSocket.SetPrivateKey(const APKeyStr: string); -begin - TSSLTools.SetPrivateKey(FSslCtx, APKeyStr); -end; - -procedure TCrossSslSocket.SetPrivateKeyFile(const APKeyFile: string); -begin - TSSLTools.SetPrivateKeyFile(FSslCtx, APKeyFile); -end; - -procedure TCrossSslSocket.TriggerConnected(AConnection: ICrossConnection); -var - LConnection: TCrossSslConnection; -begin - LConnection := AConnection as TCrossSslConnection; - - LConnection._SslLock; - try - // 网络连接已建立, 等待握手 - LConnection.ConnectStatus := csHandshaking; - - // 已完成握手才视为连接真正建立 - if LConnection._SslHandshake then - begin - LConnection.ConnectStatus := csConnected; - inherited TriggerConnected(AConnection); - end; - finally - LConnection._SslUnlock; - end; -end; - -procedure TCrossSslSocket.TriggerReceived(AConnection: ICrossConnection; - ABuf: Pointer; ALen: Integer); -var - LConnection: TCrossSslConnection; - ret, error: Integer; - LBuffer: TBytesStream; -begin - LConnection := AConnection as TCrossSslConnection; - LConnection._SslLock; - try - // 将收到的加密数据写入 BIO, 让 OpenSSL 对其解密 - while True do - begin - ret := BIO_write(LConnection.FBIOIn, ABuf, ALen); -// _Log('recv %d, bio_write %d', [ALen, ret]); - if (ret > 0) then Break; - - if not BIO_should_retry(LConnection.FBIOIn) then - begin - LConnection.Close; - Exit; - end; - end; - - // 未完成初始化, 继续握手 - if not SSL_is_init_finished(LConnection.FSsl) then - begin - // 已完成握手才视为连接真正建立 - if LConnection._SslHandshake - and (LConnection.ConnectStatus = csHandshaking) then - begin - LConnection.ConnectStatus := csConnected; - inherited TriggerConnected(AConnection); - end; - Exit; - end; - - LBuffer := TBytesStream.Create(nil); - try - while True do - begin - // 貌似每次读出来的数据都不会超过 16K - ret := SSL_read(LConnection.FSsl, @FSslInBuf[0], SSL_BUF_SIZE); - if (ret > 0) then - LBuffer.Write(FSslInBuf[0], ret) - else - begin - error := SSL_get_error(LConnection.FSsl, ret); -// _Log('SSL_read error %d %s', [error, ssl_error_message(error)]); - - if ssl_is_fatal_error(error) then - begin - {$IFDEF DEBUG} - _Log('SSL_read error %d %s', [error, ssl_error_message(error)]); - {$ENDIF} - LConnection.Close; - end; - Break; - end; - end; - - if (LBuffer.Size > 0) then - inherited TriggerReceived(AConnection, LBuffer.Memory, LBuffer.Size); - finally - FreeAndNil(LBuffer); - end; - finally - LConnection._SslUnlock; - end; -end; - end. diff --git a/Net/Net.CrossWebSocketServer.pas b/Net/Net.CrossWebSocketServer.pas index 290feaa..02b0969 100644 --- a/Net/Net.CrossWebSocketServer.pas +++ b/Net/Net.CrossWebSocketServer.pas @@ -52,6 +52,7 @@ interface System.Hash, System.NetEncoding, System.Math, + System.Generics.Collections, Net.CrossSocket.Base, Net.CrossHttpServer; @@ -297,9 +298,9 @@ TCrossWebSocketConnection = class(TCrossHttpConnection, ICrossWebSocketConnect TNetCrossWebSocketServer = class(TCrossHttpServer, ICrossWebSocketServer) private - FOnOpen: TWsOnOpen; - FOnMessage: TWsOnMessage; - FOnClose: TWsOnClose; + FOnOpenEvents: TList; + FOnMessageEvents: TList; + FOnCloseEvents: TList; procedure _WebSocketHandshake(AConnection: ICrossWebSocketConnection; ACallback: TProc); @@ -319,6 +320,9 @@ TNetCrossWebSocketServer = class(TCrossHttpServer, ICrossWebSocketServer) procedure TriggerWsRequest(AConnection: ICrossWebSocketConnection; ARequestType: TWsRequestType; const ARequestData: TBytes); virtual; public + constructor Create(AIoThreads: Integer); override; + destructor Destroy; override; + function OnOpen(ACallback: TWsOnOpen): ICrossWebSocketServer; function OnMessage(ACallback: TWsOnMessage): ICrossWebSocketServer; function OnClose(ACallback: TWsOnClose): ICrossWebSocketServer; @@ -868,6 +872,24 @@ procedure TCrossWebSocketConnection._WsSend(AOpCode: Byte; AFin: Boolean; { TNetCrossWebSocketServer } +constructor TNetCrossWebSocketServer.Create(AIoThreads: Integer); +begin + inherited; + + FOnOpenEvents := TList.Create; + FOnMessageEvents := TList.Create; + FOnCloseEvents := TList.Create; +end; + +destructor TNetCrossWebSocketServer.Destroy; +begin + FreeAndNil(FOnOpenEvents); + FreeAndNil(FOnMessageEvents); + FreeAndNil(FOnCloseEvents); + + inherited; +end; + procedure TNetCrossWebSocketServer.LogicDisconnected( AConnection: ICrossConnection); var @@ -894,19 +916,37 @@ procedure TNetCrossWebSocketServer.LogicReceived(AConnection: ICrossConnection; function TNetCrossWebSocketServer.OnClose(ACallback: TWsOnClose): ICrossWebSocketServer; begin - FOnClose := ACallback; + System.TMonitor.Enter(FOnCloseEvents); + try + FOnCloseEvents.Add(ACallback); + finally + System.TMonitor.Exit(FOnCloseEvents); + end; + Result := Self; end; function TNetCrossWebSocketServer.OnMessage(ACallback: TWsOnMessage): ICrossWebSocketServer; begin - FOnMessage := ACallback; + System.TMonitor.Enter(FOnMessageEvents); + try + FOnMessageEvents.Add(ACallback); + finally + System.TMonitor.Exit(FOnMessageEvents); + end; + Result := Self; end; function TNetCrossWebSocketServer.OnOpen(ACallback: TWsOnOpen): ICrossWebSocketServer; begin - FOnOpen := ACallback; + System.TMonitor.Enter(FOnOpenEvents); + try + FOnOpenEvents.Add(ACallback); + finally + System.TMonitor.Exit(FOnOpenEvents); + end; + Result := Self; end; @@ -919,24 +959,57 @@ procedure TNetCrossWebSocketServer.TriggerWsRequest( procedure TNetCrossWebSocketServer._OnClose( AConnection: ICrossWebSocketConnection); +var + LOnCloseEvents: TArray; + LOnCloseEvent: TWsOnClose; begin - if Assigned(FOnClose) then - FOnClose(AConnection); + System.TMonitor.Enter(FOnCloseEvents); + try + LOnCloseEvents := FOnCloseEvents.ToArray; + finally + System.TMonitor.Exit(FOnCloseEvents); + end; + + for LOnCloseEvent in LOnCloseEvents do + if Assigned(LOnCloseEvent) then + LOnCloseEvent(AConnection); end; procedure TNetCrossWebSocketServer._OnMessage( AConnection: ICrossWebSocketConnection; ARequestType: TWsRequestType; const ARequestData: TBytes); +var + LOnMessageEvents: TArray; + LOnMessageEvent: TWsOnMessage; begin - if Assigned(FOnMessage) then - FOnMessage(AConnection, ARequestType, ARequestData); + System.TMonitor.Enter(FOnMessageEvents); + try + LOnMessageEvents := FOnMessageEvents.ToArray; + finally + System.TMonitor.Exit(FOnMessageEvents); + end; + + for LOnMessageEvent in LOnMessageEvents do + if Assigned(LOnMessageEvent) then + LOnMessageEvent(AConnection, ARequestType, ARequestData); end; procedure TNetCrossWebSocketServer._OnOpen( AConnection: ICrossWebSocketConnection); +var + LOnOpenEvents: TArray; + LOnOpenEvent: TWsOnOpen; begin - if Assigned(FOnOpen) then - FOnOpen(AConnection); + System.TMonitor.Enter(FOnOpenEvents); + try + LOnOpenEvents := FOnOpenEvents.ToArray; + finally + System.TMonitor.Exit(FOnOpenEvents); + end; + + for LOnOpenEvent in LOnOpenEvents do + if Assigned(LOnOpenEvent) then + LOnOpenEvent(AConnection); end; procedure TNetCrossWebSocketServer._WebSocketHandshake( diff --git a/Net/Net.MbedBIO.pas b/Net/Net.MbedBIO.pas new file mode 100644 index 0000000..9e019dc --- /dev/null +++ b/Net/Net.MbedBIO.pas @@ -0,0 +1,381 @@ +unit Net.MbedBIO; + +interface + +uses + System.SysUtils, + System.IOUtils, + Net.MbedTls; + +const + SSL_BIO_ERROR = -1; + SSL_BIO_UNSET = -2; + SSL_BIO_SIZE = 16384; // default BIO write size if not set + + SSL_FAILED = -1; + SSL_SUCCESS = 0; + + // BIO_TYPE + BIO_BUFFER = 1; + BIO_SOCKET = 2; + BIO_SSL = 3; + BIO_MEMORY = 4; + BIO_BIO = 5; + BIO_FILE = 6; + +type + PBIO = ^BIO; + + BIO = record + prev: PBIO; // previous in chain + next: PBIO; // next in chain + pair: PBIO; // BIO paired with + mem: PByte; // memory buffer + wrSz: Integer; // write buffer size (mem) + wrIdx: Integer; // current index for write buffer + rdIdx: Integer; // current read index + readRq: Integer; // read request + memLen: Integer; // memory buffer length + &type: Integer; // method type + end; + + // 抽象 IO API +function SSL_BIO_new(&type: Integer): PBIO; +function BIO_make_bio_pair(b1, b2: PBIO): Integer; + +function BIO_ctrl_pending(BIO: PBIO): Integer; +function BIO_set_write_buf_size(BIO: PBIO; size: Integer): Integer; + +function BIO_read(BIO: PBIO; buf: Pointer; size: Integer): Integer; +function BIO_write(BIO: PBIO; buf: Pointer; size: Integer): Integer; + +function BIO_free(BIO: PBIO): Integer; +function BIO_free_all(BIO: PBIO): Integer; + +function BIO_net_recv(ctx: Pointer; buf: Pointer; size: Size_T): Integer; cdecl; +function BIO_net_send(ctx: Pointer; buf: Pointer; size: Size_T): Integer; cdecl; + +implementation + +// Return the number of pending bytes in read and write buffers +function BIO_ctrl_pending(BIO: PBIO): Integer; +var + pair: PBIO; +begin + if (BIO = nil) then + Exit(0); + + if (BIO.&type = BIO_MEMORY) then + Exit(BIO.memLen); + + // type BIO_BIO then check paired buffer + if (BIO.&type = BIO_BIO) and (BIO.pair <> nil) then + begin + pair := BIO.pair; + if (pair.wrIdx > 0) and (pair.wrIdx <= pair.rdIdx) then + // in wrap around state where begining of buffer is being overwritten + Exit(pair.wrSz - pair.rdIdx + pair.wrIdx) + else + // simple case where has not wrapped around + Exit(pair.wrIdx - pair.rdIdx); + end; + + Result := 0; +end; + +function BIO_set_write_buf_size(BIO: PBIO; size: Integer): Integer; +begin + if (BIO = nil) or (BIO.&type <> BIO_BIO) or (size < 0) then + Exit(SSL_FAILED); + + // if already in pair then do not change size + if BIO.pair <> nil then + Exit(SSL_FAILED); + + BIO.wrSz := size; + if (BIO.wrSz < 0) then + Exit(SSL_FAILED); + + if (BIO.mem <> nil) then + FreeMem(BIO.mem); + + GetMem(BIO.mem, BIO.wrSz); + if (BIO.mem = nil) then + Exit(SSL_FAILED); + + BIO.wrIdx := 0; + BIO.rdIdx := 0; + Result := SSL_SUCCESS; +end; + +{ * Joins two BIO_BIO types. The write of b1 goes to the read of b2 and vise + * versa. Creating something similar to a two way pipe. + * Reading and writing between the two BIOs is not thread safe, they are + * expected to be used by the same thread. + * } +function BIO_make_bio_pair(b1, b2: PBIO): Integer; +begin + if (b1 = nil) or (b2 = nil) then + Exit(SSL_FAILED); + + // both are expected to be of type BIO and not already paired + if (b1.&type <> BIO_BIO) + or (b2.&type <> BIO_BIO) or (b1.pair <> nil) or (b2.pair <> nil) then + Exit(SSL_FAILED); + + // set default write size if not already set + if (b1.mem = nil) + and (BIO_set_write_buf_size(b1, SSL_BIO_SIZE) <> SSL_SUCCESS) then + Exit(SSL_FAILED); + + if (b2.mem = nil) + and (BIO_set_write_buf_size(b2, SSL_BIO_SIZE) <> SSL_SUCCESS) then + Exit(SSL_FAILED); + + b1.pair := b2; + b2.pair := b1; + Result := SSL_SUCCESS; +end; + +// Does not advance read index pointer +function BIO_nread0(BIO: PBIO; buf: PPointer): Integer; +var + pair: PBIO; +begin + if (BIO = nil) or (buf = nil) then + Exit(0); + + // if paired read from pair + if (BIO.pair <> nil) then + begin + pair := BIO.pair; + + // case where have wrapped around write buffer + buf^ := pair.mem + pair.rdIdx; + if (pair.wrIdx > 0) and (pair.rdIdx >= pair.wrIdx) then + Exit(pair.wrSz - pair.rdIdx) + else + Exit(pair.wrIdx - pair.rdIdx); + end; + + Result := 0; +end; + +function BIO_nread(BIO: PBIO; buf: PPointer; num: Integer): Integer; +var + sz: Integer; +begin + sz := SSL_BIO_UNSET; + if (BIO = nil) or (buf = nil) then + Exit(SSL_FAILED); + + if (BIO.pair <> nil) then + begin + // special case if asking to read 0 bytes + if (num = 0) then + begin + buf^ := BIO.pair.mem + BIO.pair.rdIdx; + Exit(0); + end; + + // get amount able to read and set buffer pointer + sz := BIO_nread0(BIO, buf); + if (sz = 0) then + Exit(SSL_BIO_ERROR); + + if (num < sz) then + sz := num; + + BIO.pair.rdIdx := BIO.pair.rdIdx + sz; + + // check if have read to the end of the buffer and need to reset + if (BIO.pair.rdIdx = BIO.pair.wrSz) then + begin + BIO.pair.rdIdx := 0; + if (BIO.pair.wrIdx = BIO.pair.wrSz) then + BIO.pair.wrIdx := 0; + end; + + // check if read up to write index, if so then reset indexs + if (BIO.pair.rdIdx = BIO.pair.wrIdx) then + begin + BIO.pair.rdIdx := 0; + BIO.pair.wrIdx := 0; + end; + end; + + Result := sz; +end; + +function BIO_nwrite(BIO: PBIO; buf: PPointer; num: Integer): Integer; +var + sz: Integer; +begin + sz := SSL_BIO_UNSET; + if (BIO = nil) or (buf = nil) then + Exit(0); + + if (BIO.pair <> nil) then + begin + if num = 0 then + begin + buf^ := BIO.mem + BIO.wrIdx; + Exit(0); + end; + if (BIO.wrIdx < BIO.rdIdx) then + // if wrapped around only write up to read index. In this case + // rdIdx is always greater then wrIdx so sz will not be negative. + sz := BIO.rdIdx - BIO.wrIdx + else if (BIO.rdIdx > 0) and (BIO.wrIdx = BIO.rdIdx) then + Exit(SSL_BIO_ERROR) // no more room to write + else + begin + // write index is past read index so write to end of buffer + sz := BIO.wrSz - BIO.wrIdx; + if (sz <= 0) then + begin + // either an error has occured with write index or it is at the + // end of the write buffer. + if (BIO.rdIdx = 0) then + // no more room, nothing has been read + Exit(SSL_BIO_ERROR); + + BIO.wrIdx := 0; + + // check case where read index is not at 0 + if (BIO.rdIdx > 0) then + sz := BIO.rdIdx // can write up to the read index + else + sz := BIO.wrSz; // no restriction other then buffer size + end; + end; + + if (num < sz) then + sz := num; + + buf^ := BIO.mem + BIO.wrIdx; + BIO.wrIdx := BIO.wrIdx + sz; + + // if at the end of the buffer and space for wrap around then set + // write index back to 0 + if (BIO.wrIdx = BIO.wrSz) and (BIO.rdIdx > 0) then + BIO.wrIdx := 0; + end; + + Result := sz; +end; + +// Reset BIO to initial state +function BIO_reset(BIO: PBIO): Integer; +begin + if (BIO = nil) then + // -1 is consistent failure even for FILE type + Exit(SSL_BIO_ERROR); + + case BIO.&type of + BIO_BIO: + begin + BIO.rdIdx := 0; + BIO.wrIdx := 0; + Exit(0); + end; + end; + + Result := SSL_BIO_ERROR; +end; + +function BIO_read(BIO: PBIO; buf: Pointer; size: Integer): Integer; +var + sz: Integer; + pt: PPointer; +begin + sz := BIO_nread(BIO, @pt, size); + if (sz > 0) then + Move(pt^, buf^, sz); + + Result := sz; +end; + +function BIO_write(BIO: PBIO; buf: Pointer; size: Integer): Integer; +var + sz: Integer; + data: Pointer; +begin + // internal function where arguments have already been sanity checked + sz := BIO_nwrite(BIO, @data, size); + + // test space for write + if (sz <= 0) then + Exit(sz); + + Move(buf^, data^, sz); + Result := sz; +end; + +// support bio type only +function SSL_BIO_new(&type: Integer): PBIO; +begin + GetMem(Result, SizeOf(BIO)); + FillChar(Result^, SizeOf(BIO), 0); + Result.&type := &type; +end; + +function BIO_free(BIO: PBIO): Integer; +begin + // unchain?, doesn't matter in goahead since from free all + if (BIO <> nil) then + begin + // remove from pair by setting the paired bios pair to nil + if (BIO.pair <> nil) then + BIO.pair.pair := nil; + + if (BIO.mem <> nil) then + FreeMem(BIO.mem); + + FreeMem(BIO); + end; + + Result := 0; +end; + +function BIO_free_all(BIO: PBIO): Integer; +var + next: PBIO; +begin + while (BIO <> nil) do + begin + next := BIO.next; + BIO_free(BIO); + BIO := next; + end; + + Result := 0; +end; + +function BIO_net_send(ctx: Pointer; buf: Pointer; size: Size_T): Integer; +var + BIO: PBIO; + sz: Integer; +begin + BIO := PBIO(ctx); + sz := BIO_write(BIO, buf, size); + if (sz <= 0) then + Exit(MBEDTLS_ERR_SSL_WANT_WRITE); + + Result := sz; +end; + +function BIO_net_recv(ctx: Pointer; buf: Pointer; size: Size_T): Integer; +var + BIO: PBIO; + sz: Integer; +begin + BIO := PBIO(ctx); + sz := BIO_read(BIO, buf, size); + if (sz <= 0) then + Exit(MBEDTLS_ERR_SSL_WANT_READ); + + Result := sz; +end; + +end. diff --git a/Net/Net.MbedTls.pas b/Net/Net.MbedTls.pas new file mode 100644 index 0000000..e073d3c --- /dev/null +++ b/Net/Net.MbedTls.pas @@ -0,0 +1,1642 @@ +{ ****************************************************************************** } +{ } +{ Delphi cross platform socket library } +{ } +{ Copyright (c) 2017 WiNDDRiVER(soulawing@gmail.com) } +{ } +{ Homepage: https://github.com/winddriver/Delphi-Cross-Socket } +{ } +{ ****************************************************************************** } +unit Net.MbedTls; + +{ + MbedTls 库编译说明 + + > Windows + 用 C++ Builder 打开 mbedtls.cbproj 工程文件 + Win32编译时一定要设置 Use 'classic' Borland compiler 为 true + Win64编译的 Release 目标文件链接到 Delphi 中时, aes.o 会报告错误的文件格式 + 使用 Debug 版本的 aes.o 代替则不会报错, 测试了 C++ Builder 10.2.3 和 10.3 生成的 aes.o 文件均有该问题 + + > Linux iOS Android + 使用 Make 命令进行编译 +} + +interface + +uses +{$IFDEF MSWINDOWS} + Winapi.Windows, + System.Win.Crtl, +{$ENDIF} + System.SysUtils; + +// C 语言中枚举类型大小为 4 字节 +{$Z4} + +const +{$IF defined(WIN32)} + _PU = '_'; +{$ELSE} + _PU = ''; +{$ENDIF} + +{$IF defined(WIN32)} + {$DEFINE __HAS_MBED_TLS_OBJ__} +{$ELSEIF defined(WIN64)} + {$DEFINE __HAS_MBED_TLS_O__} +{$ELSE} // POSIX + {$DEFINE __HAS_MBED_TLS_LIB__} +{$ENDIF} + +{$IFDEF __HAS_MBED_TLS_LIB__} + {$IF defined(IOS) or defined(ANDROID)} + LIB_MBED_CRYPTO = 'libmbedtls.a'; + LIB_MBED_TLS = 'libmbedtls.a'; + LIB_MBED_X509 = 'libmbedtls.a'; + {$ELSEIF defined(OSX)} + LIB_MBED_CRYPTO = 'libmbedcrypto.dylib'; + LIB_MBED_TLS = 'libmbedtls.dylib'; + LIB_MBED_X509 = 'libmbedx509.dylib'; + {$ELSE} // LINUX + LIB_MBED_CRYPTO = 'libmbedcrypto.so'; + LIB_MBED_TLS = 'libmbedtls.so'; + LIB_MBED_X509 = 'libmbedx509.so'; + {$ENDIF} +{$ENDIF} + +{$REGION 'MbedTls定义'} +const + MBEDTLS_SSL_VERIFY_DATA_MAX_LEN = 36; + MBEDTLS_ENTROPY_MAX_SOURCES = 20; // *< Maximum number of sources supported + MBEDTLS_HAVEGE_COLLECT_SIZE = 1024; + DEBUG_LEVEL = 0; + + MBEDTLS_TLS_RSA_WITH_NULL_MD5 = $01; + MBEDTLS_TLS_RSA_WITH_NULL_SHA = $02; + MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 = $04; + MBEDTLS_TLS_RSA_WITH_RC4_128_SHA = $05; + MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA = $09; + MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA = $0A; + MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA = $15; + MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = $16; + MBEDTLS_TLS_PSK_WITH_NULL_SHA = $2C; + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA = $2D; + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA = $2E; + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA = $2F; + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA = $33; + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA = $35; + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA = $39; + MBEDTLS_TLS_RSA_WITH_NULL_SHA256 = $3B; + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 = $3C; + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 = $3D; + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA = $41; + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA = $45; + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = $67; + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = $6B; + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA = $84; + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA = $88; + MBEDTLS_TLS_PSK_WITH_RC4_128_SHA = $8A; + MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA = $8B; + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA = $8C; + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA = $8D; + MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA = $8E; + MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA = $8F; + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA = $90; + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA = $91; + MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA = $92; + MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA = $93; + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA = $94; + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA = $95; + MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 = $9C; + MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 = $9D; + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = $9E; + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = $9F; + MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 = $A8; + MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 = $A9; + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = $AA; + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = $AB; + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 = $AC; + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 = $AD; + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 = $AE; + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 = $AF; + MBEDTLS_TLS_PSK_WITH_NULL_SHA256 = $B0; + MBEDTLS_TLS_PSK_WITH_NULL_SHA384 = $B1; + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 = $B2; + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 = $B3; + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 = $B4; + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 = $B5; + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 = $B6; + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 = $B7; + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 = $B8; + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 = $B9; + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 = $BA; + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = $BE; + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 = $C0; + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = $C4; + MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA = $C001; + MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA = $C002; + MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = $C003; + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = $C004; + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = $C005; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA = $C006; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = $C007; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = $C008; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = $C009; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = $C00A; + MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA = $C00B; + MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA = $C00C; + MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = $C00D; + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = $C00E; + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = $C00F; + MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA = $C010; + MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA = $C011; + MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = $C012; + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = $C013; + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = $C014; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = $C023; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = $C024; + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = $C025; + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = $C026; + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = $C027; + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = $C028; + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = $C029; + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = $C02A; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = $C02B; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = $C02C; + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = $C02D; + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = $C02E; + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = $C02F; + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = $C030; + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = $C031; + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = $C032; + MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA = $C033; + MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA = $C034; + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA = $C035; + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA = $C036; + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 = $C037; + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 = $C038; + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA = $C039; + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 = $C03A; + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 = $C03B; + MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 = $C03C; + MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 = $C03D; + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 = $C044; + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 = $C045; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 = $C048; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 = $C049; + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 = $C04A; + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 = $C04B; + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 = $C04C; + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 = $C04D; + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 = $C04E; + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 = $C04F; + MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 = $C050; + MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 = $C051; + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 = $C052; + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 = $C053; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 = $C05C; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 = $C05D; + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 = $C05E; + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 = $C05F; + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 = $C060; + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 = $C061; + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 = $C062; + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 = $C063; + MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 = $C064; + MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 = $C065; + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 = $C066; + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 = $C067; + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 = $C068; + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 = $C069; + MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 = $C06A; + MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 = $C06B; + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 = $C06C; + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 = $C06D; + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 = $C06E; + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 = $C06F; + MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 = $C070; + MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 = $C071; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = $C072; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = $C073; + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = $C074; + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = $C075; + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = $C076; + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 = $C077; + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = $C078; + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 = $C079; + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 = $C07A; + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 = $C07B; + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = $C07C; + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = $C07D; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = $C086; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = $C087; + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = $C088; + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = $C089; + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = $C08A; + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = $C08B; + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = $C08C; + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = $C08D; + MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 = $C08E; + MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 = $C08F; + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 = $C090; + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 = $C091; + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 = $C092; + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 = $C093; + MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 = $C094; + MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 = $C095; + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = $C096; + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = $C097; + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 = $C098; + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 = $C099; + MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = $C09A; + MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = $C09B; + MBEDTLS_TLS_RSA_WITH_AES_128_CCM = $C09C; + MBEDTLS_TLS_RSA_WITH_AES_256_CCM = $C09D; + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM = $C09E; + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM = $C09F; + MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 = $C0A0; + MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 = $C0A1; + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 = $C0A2; + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 = $C0A3; + MBEDTLS_TLS_PSK_WITH_AES_128_CCM = $C0A4; + MBEDTLS_TLS_PSK_WITH_AES_256_CCM = $C0A5; + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM = $C0A6; + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM = $C0A7; + MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 = $C0A8; + MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 = $C0A9; + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 = $C0AA; + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 = $C0AB; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM = $C0AC; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM = $C0AD; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = $C0AE; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 = $C0AF; + MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 = $C0FF; + MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = $CCA8; + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = $CCA9; + MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = $CCAA; + MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 = $CCAB; + MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = $CCAC; + MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = $CCAD; + MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 = $CCAE; + +type + TMbedtls_SSL_States = Integer; + // 定义完整的 TMbedtls_SSL_States 枚举类型在编译 Win64 执行文件时会报错 + // [dcc64 Error] Net.MbedTls.pas(1638): E2068 Illegal reference to symbol 'MBEDTLS_SSL_HANDSHAKE_WRAPUP' in object file 'D:\Design\Delphi\VclFmxRtl\zLib\Net\MbedTls\Win64\Release\ssl_cli.o' + // 这显然是编译器的问题, 经测试 Delphi 10.2.3 和 Delphi 10.3 均有该问题 +// TMbedtls_SSL_States = ( +// MBEDTLS_SSL_HELLO_REQUEST = 0, +// MBEDTLS_SSL_CLIENT_HELLO, +// MBEDTLS_SSL_SERVER_HELLO, +// MBEDTLS_SSL_SERVER_CERTIFICATE, +// MBEDTLS_SSL_SERVER_KEY_EXCHANGE, +// MBEDTLS_SSL_CERTIFICATE_REQUEST, +// MBEDTLS_SSL_SERVER_HELLO_DONE, +// MBEDTLS_SSL_CLIENT_CERTIFICATE, +// MBEDTLS_SSL_CLIENT_KEY_EXCHANGE, +// MBEDTLS_SSL_CERTIFICATE_VERIFY, +// MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC, +// MBEDTLS_SSL_CLIENT_FINISHED, +// MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC, +// MBEDTLS_SSL_SERVER_FINISHED, +// MBEDTLS_SSL_FLUSH_BUFFERS, +// MBEDTLS_SSL_HANDSHAKE_WRAPUP, +// MBEDTLS_SSL_HANDSHAKE_OVER, +// MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET, +// MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT +// ); + + Size_T = NativeUInt; + PSize_T = ^Size_T; + UInt32_T = UInt32; + PUint32_T = ^UInt32_T; + UInt16_T = UInt16; + UInt64_T = UInt64; + UInt8_T = UInt8; + + PMbedtls_SSL_Session = Pointer; + PMbedtls_SSL_Transform = Pointer; + PMbedtls_SSL_Handshake_Params = Pointer; + PMbedtls_MD_Info = Pointer; // opaque + PMbedtls_X509_Crl = Pointer; + PMbedtls_Cipher_Info = Pointer; + + PMbedtls_SSL_Send = Pointer; + PMbedtls_SSL_Recv = Pointer; + PMbedtls_SSL_Recv_Timeout = Pointer; + PMbedtls_SSL_Set_Timer = Pointer; + PMbedtls_SSL_Get_Timer = Pointer; + + PMbedtls_SSL_Cache_Entry = Pointer; + + TMbedtls_MPI = record + s: Integer; // integer sign + n: Size_T; // total # of limbs + p: Pointer; // pointer to limbs + end; + + // + // SSL/TLS configuration to be shared between mbedtls_ssl_context structures. + // + PMbedtls_SSL_Config = ^TMbedtls_SSL_Config; + TMbedtls_SSL_Config = record + // Group items by size (largest first) to minimize padding overhead + + // + // Pointers + // + + ciphersuite_list: array [0 .. 3] of PInteger; + // allowed ciphersuites per version + + // Callback for printing debug output + f_dbg: Pointer; + p_dbg: Pointer; // !< context for the debug function + + // ** Callback for getting (pseudo-)random numbers + f_rng: Pointer; + p_rng: Pointer; // !< context for the RNG function + + // ** Callback to retrieve a session from the cache + f_get_cache: Pointer; + // ** Callback to store a session into the cache + f_set_cache: Pointer; + p_cache: Pointer; // !< context for cache callbacks + + // ** Callback for setting cert according to SNI extension + f_sni: Pointer; + p_sni: Pointer; // !< context for SNI callback + + // ** Callback to customize X.509 certificate chain verification + f_vrfy: Pointer; + p_vrfy: Pointer; // !< context for X.509 verify calllback + + // ** Callback to retrieve PSK key from identity + f_psk: Pointer; + p_psk: Pointer; // !< context for PSK callback + + // ** Callback to create & write a cookie for ClientHello veirifcation + f_cookie_write: Pointer; + // ** Callback to verify validity of a ClientHello cookie + f_cookie_check: Pointer; + p_cookie: Pointer; // !< context for the cookie callbacks + + // ** Callback to create & write a session ticket + f_ticket_write: Pointer; + // ** Callback to parse a session ticket into a session structure + f_ticket_parse: Pointer; + p_ticket: Pointer; // !< context for the ticket callbacks + + // ** Callback to export key block and master secret + f_export_keys: Pointer; + p_export_keys: Pointer; // !< context for key export callback + + cert_profile: Pointer; // !< verification profile + key_cert: Pointer; // !< own certificate/key pair(s) + ca_chain: Pointer; // !< trusted CAs + ca_crl: Pointer; // !< trusted CAs CRLs + + f_async_sign_start: Pointer; // !< start asynchronous signature operation + f_async_decrypt_start: Pointer; // !< start asynchronous decryption operation + f_async_resume: Pointer; // !< resume asynchronous operation + f_async_cancel: Pointer; // !< cancel asynchronous operation + p_async_config_data: Pointer; // !< Configuration data set by mbedtls_ssl_conf_async_private_cb(). + + sig_hashes: PInteger; // !< allowed signature hashes + + curve_list: Pointer; // !< allowed curves + + dhm_P: TMbedtls_MPI; // !< prime modulus for DHM + dhm_G: TMbedtls_MPI; // !< generator for DHM + + psk: PByte; // !< pre-shared key. This field should + // only be set via + // mbedtls_ssl_conf_psk() + psk_len: Size_T; // !< length of the pre-shared key. This + // field should only be set via + // mbedtls_ssl_conf_psk() + psk_identity: PByte; // !< identity for PSK negotiation. This + // field should only be set via + // mbedtls_ssl_conf_psk() + psk_identity_len: Size_T; // !< length of identity. This field should + // only be set via + // mbedtls_ssl_conf_psk() + + alpn_list: PMarshaledAString; // !< ordered list of protocols + + // + // * Numerical settings (int then char) + // + + read_timeout: UInt32_T; // !< timeout for mbedtls_ssl_read (ms) + + hs_timeout_min: UInt32_T; // !< initial value of the handshake + // retransmission timeout (ms) + hs_timeout_max: UInt32_T; // !< maximum value of the handshake + // retransmission timeout (ms) + + renego_max_records: Integer; // !< grace period for renegotiation + renego_period: array [0 .. 7] of UInt8_T; // !< value of the record counters + // that triggers renegotiation + + badmac_limit: UInt32_T; // !< limit of records with a bad MAC + + dhm_min_bitlen: UInt32_T; // !< min. bit length of the DHM prime + + max_major_ver: UInt8_T; // !< max. major version used + max_minor_ver: UInt8_T; // !< max. minor version used + min_major_ver: UInt8_T; // !< min. major version used + min_minor_ver: UInt8_T; // !< min. minor version used + + // + // * Flags (bitfields) + // + Flag: UInt32_T; + end; + + PMbedtls_SSL_Context = ^TMbedtls_SSL_Context; + TMbedtls_SSL_Context = record + conf: PMbedtls_SSL_Config; // !< configuration information + + // + // * Miscellaneous + // + state: Integer; // !< SSL handshake: current state + renego_status: Integer; // !< Initial, in progress, pending? + renego_records_seen: Integer; // !< Records since renego request, or with DTLS, + // number of retransmissions of request if + // renego_max_records is < 0 + + major_ver: Integer; // !< equal to MBEDTLS_SSL_MAJOR_VERSION_3 + minor_ver: Integer; // !< either 0 (SSL3) or 1 (TLS1.0) + + badmac_seen: Cardinal; // !< records with a bad MAC received + + f_send: PMbedtls_SSL_Send; // !< Callback for network send + f_recv: PMbedtls_SSL_Recv; // !< Callback for network receive + f_recv_timeout: PMbedtls_SSL_Recv_Timeout; // !< Callback for network receive with timeout + + p_bio: Pointer; // !< context for I/O operations + + // + // * Session layer + // + session_in: PMbedtls_SSL_Session; // !< current session data (in) + session_out: PMbedtls_SSL_Session; // !< current session data (out) + session: PMbedtls_SSL_Session; // !< negotiated session data + session_negotiate: PMbedtls_SSL_Session; // !< session data in negotiation + + handshake: PMbedtls_SSL_Handshake_Params; // !< params required only during + // the handshake process + + // + // * Record layer transformations + // + transform_in: PMbedtls_SSL_Transform; // !< current transform params (in) + transform_out: PMbedtls_SSL_Transform; // !< current transform params (in) + transform: PMbedtls_SSL_Transform; // !< negotiated transform params + transform_negotiate: PMbedtls_SSL_Transform; // !< transform params in negotiation + + // + // * Timers + // + p_timer: Pointer; // !< context for the timer callbacks + + f_set_timer: PMbedtls_SSL_Set_Timer; // !< set timer callback + f_get_timer: PMbedtls_SSL_Get_Timer; // !< get timer callback + + // + // * Record layer (incoming data) + // + in_buf: PByte; // !< input buffer + in_ctr: PByte; // !< 64-bit incoming message counter + // TLS: maintained by us + // DTLS: read from peer + in_hdr: PByte; // !< start of record header + in_len: PByte; // !< two-bytes message length field + in_iv: PByte; // !< ivlen-byte IV + in_msg: PByte; // !< message contents (in_iv+ivlen) + in_offt: PByte; // !< read offset in application data + + in_msgtype: Integer; // !< record header: message type + in_msglen: Size_T; // !< record header: message length + in_left: Size_T; // !< amount of data read so far + in_epoch: UInt16_T; // !< DTLS epoch for incoming records + next_record_offset: Size_T; // !< offset of the next record in datagram + // (equal to in_left if none) + in_window_top: UInt64_T; // !< last validated record seq_num + in_window: UInt64_T; // !< bitmask for replay detection + + in_hslen: Size_T; // !< current handshake message length, + // including the handshake header + nb_zero: Integer; // !< # of 0-length encrypted messages + + keep_current_message: Integer; // !< drop or reuse current message + // on next call to record layer? + + disable_datagram_packing: UInt8_T; // !< Disable packing multiple records + // within a single datagram. + + // + // * Record layer (outgoing data) + // + out_buf: PByte; // !< output buffer + out_ctr: PByte; // !< 64-bit outgoing message counter + out_hdr: PByte; // !< start of record header + out_len: PByte; // !< two-bytes message length field + out_iv: PByte; // !< ivlen-byte IV + out_msg: PByte; // !< message contents (out_iv+ivlen) + + out_msgtype: Integer; // !< record header: message type + out_msglen: Size_T; // !< record header: message length + out_left: Size_T; // !< amount of data not yet written + + cur_out_ctr: array [0 .. 7] of Byte; // !< Outgoing record sequence number. + + mtu: UInt16_T; // !< path mtu, used to fragment outgoing messages + + compress_buf: PByte; // !< zlib data buffer + split_done: Byte; // !< current record already splitted? + + // + // * PKI layer + // + client_auth: Integer; // !< flag for client auth. + + // + // * User settings + // + hostname: MarshaledAString; // !< expected peer CN for verification + // (and SNI if available) + + alpn_chosen: MarshaledAString; // !< negotiated protocol + + // + // * Information for DTLS hello verify + // + cli_id: PByte; // !< transport-level ID of the client + cli_id_len: Size_T; // !< length of cli_id + + // + // * Secure renegotiation + // + // needed to know when to send extension on server + secure_renegotiation: Integer; // !< does peer support legacy or + // secure renegotiation + verify_data_len: Size_T; // !< length of verify data stored + own_verify_data: array [0 .. MBEDTLS_SSL_VERIFY_DATA_MAX_LEN - 1] of Byte; // !< previous handshake verify data + peer_verify_data: array [0 .. MBEDTLS_SSL_VERIFY_DATA_MAX_LEN - 1] of Byte; // !< previous handshake verify data + end; + + PMbedtls_SSL_Cache_Context = ^TMbedtls_SSL_Cache_Context; + TMbedtls_SSL_Cache_Context = record + chain: PMbedtls_SSL_Cache_Entry; // !< start of the chain + timeout: Integer; // !< cache entry timeout + max_entries: Integer; // !< maximum entries + mutex: Pointer; // !< mutex + end; + + TMbedtls_Asn1_Buf = record + tag: Integer; // **< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. + len: Size_T; // **< ASN1 length, in octets. + p: PByte; // **< ASN1 data, e.g. in ASCII. + end; + + TMbedtls_X509_Buf = TMbedtls_Asn1_Buf; + + PMbedtls_Asn1_Named_Data = ^TMbedtls_Asn1_Named_Data; + TMbedtls_Asn1_Named_Data = record + oid: TMbedtls_Asn1_Buf; // **< The object identifier. + val: TMbedtls_Asn1_Buf; // **< The named value. + next: PMbedtls_Asn1_Named_Data; // **< The next entry in the sequence. + next_merged: Byte; // **< Merge next item into the current one? + end; + + TMbedtls_X509_Name = TMbedtls_Asn1_Named_Data; + + TMbedtls_X509_Time = record + year, mon, day: Integer; // **< Date. + hour, min, sec: Integer; // **< Time. + end; + + TMbedtls_PK_Type = ( + MBEDTLS_PK_NONE = 0, + MBEDTLS_PK_RSA, + MBEDTLS_PK_ECKEY, + MBEDTLS_PK_ECKEY_DH, + MBEDTLS_PK_ECDSA, + MBEDTLS_PK_RSA_ALT, + MBEDTLS_PK_RSASSA_PSS + ); + + PMbedtls_PK_Info = ^TMbedtls_PK_Info; + TMbedtls_PK_Info = record + // ** Public key type + &type: TMbedtls_PK_Type; + + // ** Type name + name: MarshaledAString; + + // ** Get key size in bits + get_bitlen: Pointer; + + // ** Tell if the context implements this type (e.g. ECKEY can do ECDSA) + can_do: Pointer; + + // ** Verify signature + verify_func: Pointer; + + // ** Make signature + sign_func: Pointer; + + // ** Decrypt message + decrypt_func: Pointer; + + // ** Encrypt message + encrypt_func: Pointer; + + // ** Check public-private key pair + check_pair_func: Pointer; + + // ** Allocate a new context + ctx_alloc_func: Pointer; + + // ** Free the given context + ctx_free_func: Pointer; + + // ** Interface with the debug module + debug_func: Pointer; + end; + + PMbedtls_PK_Context = ^TMbedtls_PK_Context; + TMbedtls_PK_Context = record + pk_info: PMbedtls_PK_Info; // **< Public key informations + pk_ctx: Pointer; // **< Underlying public key context + end; + + PMbedtls_Asn1_Sequence = ^TMbedtls_Asn1_Sequence; + TMbedtls_Asn1_Sequence = record + buf: TMbedtls_Asn1_Buf; // **< Buffer containing the given ASN.1 item. + next: PMbedtls_Asn1_Sequence; // **< The next entry in the sequence. + end; + + TMbedtls_X509_Sequence = TMbedtls_Asn1_Sequence; + + TMbedtls_MD_Type = ( + MBEDTLS_MD_NONE = 0, // **< None. + MBEDTLS_MD_MD2, // **< The MD2 message digest. + MBEDTLS_MD_MD4, // **< The MD4 message digest. + MBEDTLS_MD_MD5, // **< The MD5 message digest. + MBEDTLS_MD_SHA1, // **< The SHA-1 message digest. + MBEDTLS_MD_SHA224, // **< The SHA-224 message digest. + MBEDTLS_MD_SHA256, // **< The SHA-256 message digest. + MBEDTLS_MD_SHA384, // **< The SHA-384 message digest. + MBEDTLS_MD_SHA512, // **< The SHA-512 message digest. + MBEDTLS_MD_RIPEMD160 // **< The RIPEMD-160 message digest. + ); + + PMbedtls_X509_CRT = ^TMbedtls_X509_CRT; + TMbedtls_X509_CRT = record + raw: TMbedtls_X509_Buf; // **< The raw certificate data (DER). + tbs: TMbedtls_X509_Buf; // **< The raw certificate body (DER). The part that is To Be Signed. + + version: Integer; // **< The X.509 version. (1=v1, 2=v2, 3=v3) + serial: TMbedtls_X509_Buf; // **< Unique id for certificate issued by a specific CA. + sig_oid: TMbedtls_X509_Buf; // **< Signature algorithm, e.g. sha1RSA + + issuer_raw: TMbedtls_X509_Buf; // **< The raw issuer data (DER). Used for quick comparison. + subject_raw: TMbedtls_X509_Buf; // **< The raw subject data (DER). Used for quick comparison. + + issuer: TMbedtls_X509_Name; // **< The parsed issuer data (named information object). + subject: TMbedtls_X509_Name; // **< The parsed subject data (named information object). + + valid_from: TMbedtls_X509_Time; // **< Start time of certificate validity. + valid_to: TMbedtls_X509_Time; // **< End time of certificate validity. + + pk: TMbedtls_PK_Context; // **< Container for the public key context. + + issuer_id: TMbedtls_X509_Buf; // **< Optional X.509 v2/v3 issuer unique identifier. + subject_id: TMbedtls_X509_Buf; // **< Optional X.509 v2/v3 subject unique identifier. + v3_ext: TMbedtls_X509_Buf; // **< Optional X.509 v3 extensions. + subject_alt_names: TMbedtls_X509_Sequence; // **< Optional list of Subject Alternative Names (Only dNSName supported). + + ext_types: Integer; // **< Bit string containing detected and parsed extensions + ca_istrue: Integer; // **< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. + max_pathlen: Integer; // **< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ + + key_usage: UInt32_T; // **< Optional key usage extension value: See the values in x509.h + + ext_key_usage: TMbedtls_X509_Sequence; // **< Optional list of extended key usage OIDs. + + ns_cert_type: Byte; // **< Optional Netscape certificate type extension value: See the values in x509.h + + sig: TMbedtls_X509_Buf; // **< Signature: hash of the tbs part signed with the private key. + sig_md: TMbedtls_MD_Type; // **< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 + sig_pk: TMbedtls_PK_Type; // **< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA + sig_opts: Pointer; // **< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS + + next: PMbedtls_X509_CRT; // **< Next certificate in the CA-chain. + end; + + TMbedtls_SHA512_Context = record + total: array [0 .. 1] of UInt64_T; // !< The number of Bytes processed. + state: array [0 .. 7] of UInt64_T; // !< The intermediate digest state. + buffer: array [0 .. 127] of Byte; // !< The data block being processed. + is384: Integer; // !< Determines which function to use: + // 0: Use SHA-512, or 1: Use SHA-384. + end; + + TMbedtls_Entropy_Source_State = record + f_source: Pointer; // **< The entropy source callback + p_source: Pointer; // **< The callback data pointer + size: Size_T; // **< Amount received in bytes + threshold: Size_T; // **< Minimum bytes required before release + strong: Integer; // **< Is the source strong? + end; + + TMbedtls_Havege_State = record + PT1: Integer; + PT2: Integer; + offset: array [0 .. 1] of Integer; + pool: array [0 .. MBEDTLS_HAVEGE_COLLECT_SIZE - 1] of Integer; + WALK: array [0 .. 8191] of Integer; + end; + + PMbedtls_Entropy_Context = ^TMbedtls_Entropy_Context; + TMbedtls_Entropy_Context = record + accumulator_started: Integer; + accumulator: TMbedtls_SHA512_Context; + source_count: Integer; + source: array [0 .. MBEDTLS_ENTROPY_MAX_SOURCES - 1] of TMbedtls_Entropy_Source_State; + havege_data: TMbedtls_Havege_State; + mutex: Pointer; // !< mutex + initial_entropy_run: Integer; + end; + + TMbedtls_AES_Context = record + nr: Integer; // !< The number of rounds. + rk: PUint32_T; // !< AES round keys. + buf: array [0 .. 67] of UInt32_T; // !< Unaligned data buffer. This buffer can + // hold 32 extra Bytes, which can be used for + // one of the following purposes: + //
  • Alignment if VIA padlock is + // used.
  • + //
  • Simplifying key expansion in the 256-bit + // case by generating an extra round key. + //
+ end; + + PMbedtls_CTR_DRBG_Context = ^TMbedtls_CTR_DRBG_Context; + TMbedtls_CTR_DRBG_Context = record + counter: array [0 .. 15] of Byte; // !< The counter (V). + reseed_counter: Integer; // !< The reseed counter. + prediction_resistance: Integer; // !< This determines whether prediction + // resistance is enabled, that is + // whether to systematically reseed before + // each random generation. + entropy_len: Size_T; // !< The amount of entropy grabbed on each + // seed or reseed operation. + reseed_interval: Integer; // !< The reseed interval. + + aes_ctx: TMbedtls_AES_Context; // !< The AES context. + + // + // * Callbacks (Entropy) + // + f_entropy: Pointer; // !< The entropy callback function. + + p_entropy: Pointer; // !< The context for the entropy function. + + mutex: Pointer; + end; + + TEntropyFunc = function(data: Pointer; output: MarshaledAString; len: Size_T): Integer; cdecl; + PEntropyFunc = ^TEntropyFunc; + TrngFunc = function(data: Pointer; output: MarshaledAString; len: Size_T): Integer; cdecl; + TdbgFunc = procedure(data: Pointer; i: Integer; c: MarshaledAString; i2: Integer; c2: MarshaledAString); cdecl; + TNetSendFunc = function(ctx: Pointer; buf: Pointer; len: Size_T): Integer; cdecl; + TNetRecvFunc = function(ctx: Pointer; buf: Pointer; len: Size_T): Integer; cdecl; + TNetRecvTimeoutFunc = function(ctx: Pointer; buf: Pointer; len: Size_T; timeout: UInt32_T): Integer; cdecl; + TGetTimerFunc = function(ctx: Pointer): Integer; cdecl; + TSetTimerFunc = procedure(ctx: Pointer; int_ms: UInt32_T; fin_ms: UInt32_T); cdecl; + + TGetCacheFunc = function(data: Pointer; session: PMbedtls_SSL_Session): Integer; cdecl; + TSetCacheFunc = function(data: Pointer; const session: PMbedtls_SSL_Session): Integer; cdecl; + +const + // SSL Error codes - actually negative of these + MBEDTLS_ERR_MPI_FILE_IO_ERROR = -$0002; // An error occurred while reading from or writing to a file. + MBEDTLS_ERR_MPI_BAD_INPUT_DATA = -$0004; // Bad input parameters to function. + MBEDTLS_ERR_MPI_INVALID_CHARACTER = -$0006; // There is an invalid character in the digit string. + MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL = -$0008; // The buffer is too small to write to. + MBEDTLS_ERR_MPI_NEGATIVE_VALUE = -$000A; // The input arguments are negative or result in illegal output. + MBEDTLS_ERR_MPI_DIVISION_BY_ZERO = -$000C; // The input argument for division is zero, which is not allowed. + MBEDTLS_ERR_MPI_NOT_ACCEPTABLE = -$000E; // The input arguments are not acceptable. + MBEDTLS_ERR_MPI_ALLOC_FAILED = -$0010; // Memory allocation failed. + + MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG = -$0003; // Too many random requested in single call. + MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG = -$0005; // Input too large (Entropy + additional). + MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR = -$0007; // Read/write error in file. + MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED = -$0009; // The entropy source failed. + + MBEDTLS_ERR_CCM_BAD_INPUT = -$000D; // Bad input parameters to the function. + MBEDTLS_ERR_CCM_AUTH_FAILED = -$000F; // Authenticated decryption failed. + MBEDTLS_ERR_CCM_HW_ACCEL_FAILED = -$0011; // CCM hardware accelerator failed. + + MBEDTLS_ERR_GCM_AUTH_FAILED = -$0012; // Authenticated decryption failed. + MBEDTLS_ERR_GCM_HW_ACCEL_FAILED = -$0013; // GCM hardware accelerator failed. + MBEDTLS_ERR_GCM_BAD_INPUT = -$0014; // Bad input parameters to function. + + MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH = -$0016; // Invalid key length. + MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED = -$0017; // Blowfish hardware accelerator failed. + MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH = -$0018; // Invalid data input length. + + MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED = -$0019; // ARC4 hardware accelerator failed. + + MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE = -$001A; // The selected feature is not available. + MBEDTLS_ERR_THREADING_BAD_INPUT_DATA = -$001C; // Bad input parameters to function. + MBEDTLS_ERR_THREADING_MUTEX_ERROR = -$001E; // Locking / unlocking / free failed with error code. + + MBEDTLS_ERR_AES_INVALID_KEY_LENGTH = -$0020; // Invalid key length. + MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH = -$0022; // Invalid data input length. + + MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE = -$0023; // Feature not available. For example, an unsupported AES key size. + MBEDTLS_ERR_AES_HW_ACCEL_FAILED = -$0025; // AES hardware accelerator failed. + + MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH = -$0024; // Invalid key length. + MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH = -$0026; // Invalid data input length. + MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED = -$0027; // Camellia hardware accelerator failed. + + MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH = -$0028; // The data input has an invalid length. + MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED = -$0029; // XTEA hardware accelerator failed. + + MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL = -$002A; // Output buffer too small. + MBEDTLS_ERR_BASE64_INVALID_CHARACTER = -$002C; // Invalid character in input. + + MBEDTLS_ERR_MD2_HW_ACCEL_FAILED = -$002B; // MD2 hardware accelerator failed + MBEDTLS_ERR_MD4_HW_ACCEL_FAILED = -$002D; // MD4 hardware accelerator failed + MBEDTLS_ERR_MD5_HW_ACCEL_FAILED = -$002F; // MD5 hardware accelerator failed + + MBEDTLS_ERR_OID_NOT_FOUND = -$002E; // OID is not found. + MBEDTLS_ERR_OID_BUF_TOO_SMALL = -$000B; // output buffer is too small + + MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED = -$0030; // Input data should be aligned. + + MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED = -$0031; // RIPEMD160 hardware accelerator failed + + MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH = -$0032; // The data input has an invalid length. + MBEDTLS_ERR_DES_HW_ACCEL_FAILED = -$0033; // DES hardware accelerator failed. + + MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED = -$0034; // The entropy source failed. + MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG = -$0036; // The requested random buffer length is too big. + MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG = -$0038; // The input (entropy + additional data) is too large. + MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR = -$003A; // Read or write error in file. + + MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED = -$0035; // SHA-1 hardware accelerator failed + MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED = -$0037; // SHA-256 hardware accelerator failed + MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED = -$0039; // SHA-512 hardware accelerator failed + + MBEDTLS_ERR_ENTROPY_SOURCE_FAILED = -$003C; // Critical entropy source failure. + MBEDTLS_ERR_ENTROPY_MAX_SOURCES = -$003E; // No more sources can be added. + MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED = -$0040; // No sources have been added to poll. + MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE = -$003D; // No strong sources have been added to poll. + MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR = -$003F; // Read/write error in file. + + MBEDTLS_ERR_NET_SOCKET_FAILED = -$0042; // Failed to open a socket. + MBEDTLS_ERR_NET_CONNECT_FAILED = -$0044; // The connection to the given server / port failed. + MBEDTLS_ERR_NET_BIND_FAILED = -$0046; // Binding of the socket failed. + MBEDTLS_ERR_NET_LISTEN_FAILED = -$0048; // Could not listen on the socket. + MBEDTLS_ERR_NET_ACCEPT_FAILED = -$004A; // Could not accept the incoming connection. + MBEDTLS_ERR_NET_RECV_FAILED = -$004C; // Reading information from the socket failed. + MBEDTLS_ERR_NET_SEND_FAILED = -$004E; // Sending information through the socket failed. + MBEDTLS_ERR_NET_CONN_RESET = -$0050; // Connection was reset by peer. + MBEDTLS_ERR_NET_UNKNOWN_HOST = -$0052; // Failed to get an IP address for the given hostname. + MBEDTLS_ERR_NET_BUFFER_TOO_SMALL = -$0043; // Buffer is too small to hold the data. + MBEDTLS_ERR_NET_INVALID_CONTEXT = -$0045; // The context is invalid, eg because it was free()ed. + + MBEDTLS_ERR_ASN1_OUT_OF_DATA = -$0060; // Out of data when parsing an ASN1 data structure. + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG = -$0062; // ASN1 tag was of an unexpected value. + MBEDTLS_ERR_ASN1_INVALID_LENGTH = -$0064; // Error when trying to determine the length or invalid length. + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH = -$0066; // Actual length differs from expected length. + MBEDTLS_ERR_ASN1_INVALID_DATA = -$0068; // Data is invalid. (not used) + MBEDTLS_ERR_ASN1_ALLOC_FAILED = -$006A; // Memory allocation failed + MBEDTLS_ERR_ASN1_BUF_TOO_SMALL = -$006C; // Buffer too small when writing ASN.1 data structure. + + MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED = -$007A; // CMAC hardware accelerator failed. + + MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT = -$1080; // No PEM header or footer found. + MBEDTLS_ERR_PEM_INVALID_DATA = -$1100; // PEM string is not as expected. + MBEDTLS_ERR_PEM_ALLOC_FAILED = -$1180; // Failed to allocate memory. + MBEDTLS_ERR_PEM_INVALID_ENC_IV = -$1200; // RSA IV is not in hex-format. + MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG = -$1280; // Unsupported key encryption algorithm. + MBEDTLS_ERR_PEM_PASSWORD_REQUIRED = -$1300; // Private key password can't be empty. + MBEDTLS_ERR_PEM_PASSWORD_MISMATCH = -$1380; // Given private key password does not allow for correct decryption. + MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE = -$1400; // Unavailable feature, e.g. hashing/encryption combination. + MBEDTLS_ERR_PEM_BAD_INPUT_DATA = -$1480; // Bad input parameters to function. + + MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA = -$1F80; // Bad input parameters to function. + MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE = -$1F00; // Feature not available, e.g. unsupported encryption scheme. + MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT = -$1E80; // PBE ASN.1 data not as expected. + MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH = -$1E00; // Given private key password does not allow for correct decryption. + + MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE = -$2080; // Unavailable feature, e.g. RSA hashing/encryption combination. + MBEDTLS_ERR_X509_UNKNOWN_OID = -$2100; // Requested OID is unknown. + MBEDTLS_ERR_X509_INVALID_FORMAT = -$2180; // The CRT/CRL/CSR format is invalid, e.g. different type expected. + MBEDTLS_ERR_X509_INVALID_VERSION = -$2200; // The CRT/CRL/CSR version element is invalid. + MBEDTLS_ERR_X509_INVALID_SERIAL = -$2280; // The serial tag or value is invalid. + MBEDTLS_ERR_X509_INVALID_ALG = -$2300; // The algorithm tag or value is invalid. + MBEDTLS_ERR_X509_INVALID_NAME = -$2380; // The name tag or value is invalid. + MBEDTLS_ERR_X509_INVALID_DATE = -$2400; // The date tag or value is invalid. + MBEDTLS_ERR_X509_INVALID_SIGNATURE = -$2480; // The signature tag or value invalid. + MBEDTLS_ERR_X509_INVALID_EXTENSIONS = -$2500; // The extension tag or value is invalid. + MBEDTLS_ERR_X509_UNKNOWN_VERSION = -$2580; // CRT/CRL/CSR has an unsupported version number. + MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG = -$2600; // Signature algorithm (oid) is unsupported. + MBEDTLS_ERR_X509_SIG_MISMATCH = -$2680; // Signature algorithms do not match. (see \c ::mbedtls_x509_crt sig_oid) + MBEDTLS_ERR_X509_CERT_VERIFY_FAILED = -$2700; // Certificate verification failed, e.g. CRL, CA or signature check failed. + MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT = -$2780; // Format not recognized as DER or PEM. + MBEDTLS_ERR_X509_BAD_INPUT_DATA = -$2800; // Input invalid. + MBEDTLS_ERR_X509_ALLOC_FAILED = -$2880; // Allocation of memory failed. + MBEDTLS_ERR_X509_FILE_IO_ERROR = -$2900; // Read/write of file failed. + MBEDTLS_ERR_X509_BUFFER_TOO_SMALL = -$2980; // Destination buffer is too small. + MBEDTLS_ERR_X509_FATAL_ERROR = -$3000; // A fatal error occured, eg the chain is too long or the vrfy callback failed. + + MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA = -$2F80; // Bad input parameters to function. + MBEDTLS_ERR_PKCS5_INVALID_FORMAT = -$2F00; // Unexpected ASN.1 data. + MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE = -$2E80; // Requested encryption or digest alg not available. + MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH = -$2E00; // Given private key password does not allow for correct decryption. + + MBEDTLS_ERR_DHM_BAD_INPUT_DATA = -$3080; // Bad input parameters. + MBEDTLS_ERR_DHM_READ_PARAMS_FAILED = -$3100; // Reading of the DHM parameters failed. + MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED = -$3180; // Making of the DHM parameters failed. + MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED = -$3200; // Reading of the public values failed. + MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED = -$3280; // Making of the public value failed. + MBEDTLS_ERR_DHM_CALC_SECRET_FAILED = -$3300; // Calculation of the DHM secret failed. + MBEDTLS_ERR_DHM_INVALID_FORMAT = -$3380; // The ASN.1 data is not formatted correctly. + MBEDTLS_ERR_DHM_ALLOC_FAILED = -$3400; // Allocation of memory failed. + MBEDTLS_ERR_DHM_FILE_IO_ERROR = -$3480; // Read or write of file failed. + MBEDTLS_ERR_DHM_HW_ACCEL_FAILED = -$3500; // DHM hardware accelerator failed. + MBEDTLS_ERR_DHM_SET_GROUP_FAILED = -$3580; // Setting the modulus and generator failed. + + MBEDTLS_ERR_PK_ALLOC_FAILED = -$3F80; // Memory allocation failed. + MBEDTLS_ERR_PK_TYPE_MISMATCH = -$3F00; // Type mismatch, eg attempt to encrypt with an ECDSA key + MBEDTLS_ERR_PK_BAD_INPUT_DATA = -$3E80; // Bad input parameters to function. + MBEDTLS_ERR_PK_FILE_IO_ERROR = -$3E00; // Read/write of file failed. + MBEDTLS_ERR_PK_KEY_INVALID_VERSION = -$3D80; // Unsupported key version + MBEDTLS_ERR_PK_KEY_INVALID_FORMAT = -$3D00; // Invalid key tag or value. + MBEDTLS_ERR_PK_UNKNOWN_PK_ALG = -$3C80; // Key algorithm is unsupported (only RSA and EC are supported). + MBEDTLS_ERR_PK_PASSWORD_REQUIRED = -$3C00; // Private key password can't be empty. + MBEDTLS_ERR_PK_PASSWORD_MISMATCH = -$3B80; // Given private key password does not allow for correct decryption. + MBEDTLS_ERR_PK_INVALID_PUBKEY = -$3B00; // The pubkey tag or value is invalid (only RSA and EC are supported). + MBEDTLS_ERR_PK_INVALID_ALG = -$3A80; // The algorithm tag or value is invalid. + MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE = -$3A00; // Elliptic curve is unsupported (only NIST curves are supported). + MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE = -$3980; // Unavailable feature, e.g. RSA disabled for RSA key. + MBEDTLS_ERR_PK_SIG_LEN_MISMATCH = -$3900; // The signature is valid but its length is less than expected. + MBEDTLS_ERR_PK_HW_ACCEL_FAILED = -$3880; // PK hardware accelerator failed. + + MBEDTLS_ERR_RSA_BAD_INPUT_DATA = -$4080; // Bad input parameters to function. + MBEDTLS_ERR_RSA_INVALID_PADDING = -$4100; // Input data contains invalid padding and is rejected. + MBEDTLS_ERR_RSA_KEY_GEN_FAILED = -$4180; // Something failed during generation of a key. + MBEDTLS_ERR_RSA_KEY_CHECK_FAILED = -$4200; // Key failed to pass the validity check of the library. + MBEDTLS_ERR_RSA_PUBLIC_FAILED = -$4280; // The public key operation failed. + MBEDTLS_ERR_RSA_PRIVATE_FAILED = -$4300; // The private key operation failed. + MBEDTLS_ERR_RSA_VERIFY_FAILED = -$4380; // The PKCS#1 verification failed. + MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE = -$4400; // The output buffer for decryption is not large enough. + MBEDTLS_ERR_RSA_RNG_FAILED = -$4480; // The random generator failed to generate non-zeros. + MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION = -$4500; // The implementation does not offer the requested operation, for example, because of security violations or lack of functionality. + MBEDTLS_ERR_RSA_HW_ACCEL_FAILED = -$4580; // RSA hardware accelerator failed. + + MBEDTLS_ERR_ECP_BAD_INPUT_DATA = -$4F80; // Bad input parameters to function. + MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL = -$4F00; // The buffer is too small to write to. + MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE = -$4E80; // Requested curve not available. + MBEDTLS_ERR_ECP_VERIFY_FAILED = -$4E00; // The signature is not valid. + MBEDTLS_ERR_ECP_ALLOC_FAILED = -$4D80; // Memory allocation failed. + MBEDTLS_ERR_ECP_RANDOM_FAILED = -$4D00; // Generation of random value, such as (ephemeral) key, failed. + MBEDTLS_ERR_ECP_INVALID_KEY = -$4C80; // Invalid private or public key. + MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH = -$4C00; // Signature is valid but shorter than the user-supplied length. + MBEDTLS_ERR_ECP_HW_ACCEL_FAILED = -$4B80; // ECP hardware accelerator failed. + + MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE = -$5080; // The selected feature is not available. + MBEDTLS_ERR_MD_BAD_INPUT_DATA = -$5100; // Bad input parameters to function. + MBEDTLS_ERR_MD_ALLOC_FAILED = -$5180; // Failed to allocate memory. + MBEDTLS_ERR_MD_FILE_IO_ERROR = -$5200; // Opening or reading of file failed. + MBEDTLS_ERR_MD_HW_ACCEL_FAILED = -$5280; // MD hardware accelerator failed. + + MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE = -$6080; // The selected feature is not available. + MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA = -$6100; // Bad input parameters. + MBEDTLS_ERR_CIPHER_ALLOC_FAILED = -$6180; // Failed to allocate memory. + MBEDTLS_ERR_CIPHER_INVALID_PADDING = -$6200; // Input data contains invalid padding and is rejected. + MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED = -$6280; // Decryption of block requires a full block. + MBEDTLS_ERR_CIPHER_AUTH_FAILED = -$6300; // Authentication failed (for AEAD modes). + MBEDTLS_ERR_CIPHER_INVALID_CONTEXT = -$6380; // The context is invalid. For example, because it was freed. + MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED = -$6400; // Cipher hardware accelerator failed. + + MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE = -$7080; // The requested feature is not available. + MBEDTLS_ERR_SSL_BAD_INPUT_DATA = -$7100; // Bad input parameters to function. + MBEDTLS_ERR_SSL_INVALID_MAC = -$7180; // Verification of the message MAC failed. + MBEDTLS_ERR_SSL_INVALID_RECORD = -$7200; // An invalid SSL record was received. + MBEDTLS_ERR_SSL_CONN_EOF = -$7280; // The connection indicated an EOF. + MBEDTLS_ERR_SSL_UNKNOWN_CIPHER = -$7300; // An unknown cipher was received. + MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN = -$7380; // The server has no ciphersuites in common with the client. + MBEDTLS_ERR_SSL_NO_RNG = -$7400; // No RNG was provided to the SSL module. + MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE = -$7480; // No client certification received from the client, but required by the authentication mode. + MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE = -$7500; // Our own certificate(s) is/are too large to send in an SSL message. + MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED = -$7580; // The own certificate is not set, but needed by the server. + MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED = -$7600; // The own private key or pre-shared key is not set, but needed. + MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED = -$7680; // No CA Chain is set, but required to operate. + MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE = -$7700; // An unexpected message was received from our peer. + MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE = -$7780; // A fatal alert message was received from our peer. + MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED = -$7800; // Verification of our peer failed. + MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY = -$7880; // The peer notified us that the connection is going to be closed. + MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO = -$7900; // Processing of the ClientHello handshake message failed. + MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO = -$7980; // Processing of the ServerHello handshake message failed. + MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE = -$7A00; // Processing of the Certificate handshake message failed. + MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST = -$7A80; // Processing of the CertificateRequest handshake message failed. + MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE = -$7B00; // Processing of the ServerKeyExchange handshake message failed. + MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE = -$7B80; // Processing of the ServerHelloDone handshake message failed. + MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE = -$7C00; // Processing of the ClientKeyExchange handshake message failed. + MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP = -$7C80; // Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. + MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS = -$7D00; // Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. + MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY = -$7D80; // Processing of the CertificateVerify handshake message failed. + MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC = -$7E00; // Processing of the ChangeCipherSpec handshake message failed. + MBEDTLS_ERR_SSL_BAD_HS_FINISHED = -$7E80; // Processing of the Finished handshake message failed. + MBEDTLS_ERR_SSL_ALLOC_FAILED = -$7F00; // Memory allocation failed + MBEDTLS_ERR_SSL_HW_ACCEL_FAILED = -$7F80; // Hardware acceleration function returned with error + MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH = -$6F80; // Hardware acceleration function skipped / left alone data + MBEDTLS_ERR_SSL_COMPRESSION_FAILED = -$6F00; // Processing of the compression / decompression failed + MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION = -$6E80; // Handshake protocol not within min/max boundaries + MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET = -$6E00; // Processing of the NewSessionTicket handshake message failed. + MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED = -$6D80; // Session ticket has expired. + MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH = -$6D00; // Public key type mismatch (eg, asked for RSA key exchange and presented EC key) + MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY = -$6C80; // Unknown identity received (eg, PSK identity) + MBEDTLS_ERR_SSL_INTERNAL_ERROR = -$6C00; // Internal error (eg, unexpected failure in lower-level module) + MBEDTLS_ERR_SSL_COUNTER_WRAPPING = -$6B80; // A counter would wrap (eg, too many messages exchanged). + MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO = -$6B00; // Unexpected message at ServerHello in renegotiation. + MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED = -$6A80; // DTLS client must retry for hello verification + MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL = -$6A00; // A buffer is too small to receive or write a message + MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE = -$6980; // None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). + MBEDTLS_ERR_SSL_WANT_READ = -$6900; // Connection requires a read call. + MBEDTLS_ERR_SSL_WANT_WRITE = -$6880; // Connection requires a write call. + MBEDTLS_ERR_SSL_TIMEOUT = -$6800; // The operation timed out. + MBEDTLS_ERR_SSL_CLIENT_RECONNECT = -$6780; // The client initiated a reconnect from the same port. + MBEDTLS_ERR_SSL_UNEXPECTED_RECORD = -$6700; // Record header looks valid but is not expected. + MBEDTLS_ERR_SSL_NON_FATAL = -$6680; // The alert message received indicates a non-fatal error. + MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH = -$6600; // Couldn't set the hash for verifying CertificateVerify + + // Various constants + + MBEDTLS_SSL_MAJOR_VERSION_3 = 3; + MBEDTLS_SSL_MINOR_VERSION_0 = 0; // SSL v3.0 + MBEDTLS_SSL_MINOR_VERSION_1 = 1; // TLS v1.0 + MBEDTLS_SSL_MINOR_VERSION_2 = 2; // TLS v1.1 + MBEDTLS_SSL_MINOR_VERSION_3 = 3; // TLS v1.2 + + MBEDTLS_SSL_TRANSPORT_STREAM = 0; // TLS + MBEDTLS_SSL_TRANSPORT_DATAGRAM = 1; // DTLS + + MBEDTLS_SSL_MAX_HOST_NAME_LEN = 255; // Maximum host name defined in RFC 1035 + + // RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c + // NONE must be zero so that memset()ing structure to zero works + + MBEDTLS_SSL_MAX_FRAG_LEN_NONE = 0; // don't use this extension + MBEDTLS_SSL_MAX_FRAG_LEN_512 = 1; // MaxFragmentLength 2^9 + MBEDTLS_SSL_MAX_FRAG_LEN_1024 = 2; // MaxFragmentLength 2^10 + MBEDTLS_SSL_MAX_FRAG_LEN_2048 = 3; // MaxFragmentLength 2^11 + MBEDTLS_SSL_MAX_FRAG_LEN_4096 = 4; // MaxFragmentLength 2^12 + MBEDTLS_SSL_MAX_FRAG_LEN_INVALID = 5; // first invalid value + + MBEDTLS_SSL_IS_CLIENT = 0; + MBEDTLS_SSL_IS_SERVER = 1; + + MBEDTLS_SSL_IS_NOT_FALLBACK = 0; + MBEDTLS_SSL_IS_FALLBACK = 1; + + MBEDTLS_SSL_EXTENDED_MS_DISABLED = 0; + MBEDTLS_SSL_EXTENDED_MS_ENABLED = 1; + + MBEDTLS_SSL_ETM_DISABLED = 0; + MBEDTLS_SSL_ETM_ENABLED = 1; + + MBEDTLS_SSL_COMPRESS_NULL = 0; + MBEDTLS_SSL_COMPRESS_DEFLATE = 1; + + MBEDTLS_SSL_VERIFY_NONE = 0; + MBEDTLS_SSL_VERIFY_OPTIONAL = 1; + MBEDTLS_SSL_VERIFY_REQUIRED = 2; + MBEDTLS_SSL_VERIFY_UNSET = 3; // Used only for sni_authmode + + MBEDTLS_SSL_LEGACY_RENEGOTIATION = 0; + MBEDTLS_SSL_SECURE_RENEGOTIATION = 1; + + MBEDTLS_SSL_RENEGOTIATION_DISABLED = 0; + MBEDTLS_SSL_RENEGOTIATION_ENABLED = 1; + + MBEDTLS_SSL_ANTI_REPLAY_DISABLED = 0; + MBEDTLS_SSL_ANTI_REPLAY_ENABLED = 1; + + MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED = -1; + MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT = 16; + + MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION = 0; + MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION = 1; + MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE = 2; + + MBEDTLS_SSL_TRUNC_HMAC_DISABLED = 0; + MBEDTLS_SSL_TRUNC_HMAC_ENABLED = 1; + MBEDTLS_SSL_TRUNCATED_HMAC_LEN = 10; // 80 bits, rfc 6066 section 7 + + MBEDTLS_SSL_SESSION_TICKETS_DISABLED = 0; + MBEDTLS_SSL_SESSION_TICKETS_ENABLED = 1; + + MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED = 0; + MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED = 1; + + MBEDTLS_SSL_ARC4_ENABLED = 0; + MBEDTLS_SSL_ARC4_DISABLED = 1; + + MBEDTLS_SSL_PRESET_DEFAULT = 0; + MBEDTLS_SSL_PRESET_SUITEB = 2; + + MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED = 1; + MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED = 0; + + // Default range for DTLS retransmission timer value, in milliseconds. + // RFC 6347 4.2.4.1 says from 1 second to 60 seconds. + + MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN = 1000; + MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX = 60000; + + MBEDTLS_SSL_INITIAL_HANDSHAKE = 0; + MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS = 1; // In progress + MBEDTLS_SSL_RENEGOTIATION_DONE = 2; // Done or aborted + MBEDTLS_SSL_RENEGOTIATION_PENDING = 3; // Requested (server only) + + MBEDTLS_SSL_RETRANS_PREPARING = 0; + MBEDTLS_SSL_RETRANS_SENDING = 1; + MBEDTLS_SSL_RETRANS_WAITING = 2; + MBEDTLS_SSL_RETRANS_FINISHED = 3; + + MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC = 20; + MBEDTLS_SSL_MSG_ALERT = 21; + MBEDTLS_SSL_MSG_HANDSHAKE = 22; + MBEDTLS_SSL_MSG_APPLICATION_DATA = 23; + + MBEDTLS_SSL_ALERT_LEVEL_WARNING = 1; + MBEDTLS_SSL_ALERT_LEVEL_FATAL = 2; + + MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY = 0; // 0x00 + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE = 10; // 0x0A + MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC = 20; // 0x14 + MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED = 21; // 0x15 + MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW = 22; // 0x16 + MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE = 30; // 0x1E + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE = 40; // 0x28 + MBEDTLS_SSL_ALERT_MSG_NO_CERT = 41; // 0x29 + MBEDTLS_SSL_ALERT_MSG_BAD_CERT = 42; // 0x2A + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT = 43; // 0x2B + MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED = 44; // 0x2C + MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED = 45; // 0x2D + MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN = 46; // 0x2E + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER = 47; // 0x2F + MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA = 48; // 0x30 + MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED = 49; // 0x31 + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR = 50; // 0x32 + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR = 51; // 0x33 + MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION = 60; // 0x3C + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION = 70; // 0x46 + MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY = 71; // 0x47 + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR = 80; // 0x50 + MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK = 86; // 0x56 + MBEDTLS_SSL_ALERT_MSG_USER_CANCELED = 90; // 0x5A + MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION = 100; // 0x64 + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT = 110; // 0x6E + MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME = 112; // 0x70 + MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY = 115; // 0x73 + MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL = 120; // 0x78 + + MBEDTLS_SSL_HS_HELLO_REQUEST = 0; + MBEDTLS_SSL_HS_CLIENT_HELLO = 1; + MBEDTLS_SSL_HS_SERVER_HELLO = 2; + MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST = 3; + MBEDTLS_SSL_HS_NEW_SESSION_TICKET = 4; + MBEDTLS_SSL_HS_CERTIFICATE = 11; + MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE = 12; + MBEDTLS_SSL_HS_CERTIFICATE_REQUEST = 13; + MBEDTLS_SSL_HS_SERVER_HELLO_DONE = 14; + MBEDTLS_SSL_HS_CERTIFICATE_VERIFY = 15; + MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE = 16; + MBEDTLS_SSL_HS_FINISHED = 20; + + // TLS extensions + MBEDTLS_TLS_EXT_SERVERNAME = 0; + MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME = 0; + MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH = 1; + MBEDTLS_TLS_EXT_TRUNCATED_HMAC = 4; + MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES = 10; + MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS = 11; + MBEDTLS_TLS_EXT_SIG_ALG = 13; + MBEDTLS_TLS_EXT_ALPN = 16; + MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC = 22; // 0x16 + MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET = $0017; // 23 + MBEDTLS_TLS_EXT_SESSION_TICKET = 35; + MBEDTLS_TLS_EXT_ECJPAKE_KKPP = 256; // experimental + MBEDTLS_TLS_EXT_RENEGOTIATION_INFO = $FF01; + + MBEDTLS_ENTROPY_SOURCE_STRONG = 1; // Entropy source is strong + MBEDTLS_ENTROPY_SOURCE_WEAK = 0; // Entropy source is weak + +{$REGION 'libmbedcrypto'} +function mbedtls_entropy_add_source(ctx: PMbedtls_Entropy_Context; f_source: TEntropyFunc; p_source: Pointer; threshold: Size_T; strong: Integer): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_CRYPTO{$ENDIF} name _PU + 'mbedtls_entropy_add_source'; +procedure mbedtls_entropy_free(ctx: PMbedtls_Entropy_Context); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_CRYPTO{$ENDIF} name _PU + 'mbedtls_entropy_free'; +function mbedtls_entropy_func(data: Pointer; output: MarshaledAString; len: Size_T): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_CRYPTO{$ENDIF} name _PU + 'mbedtls_entropy_func'; +procedure mbedtls_entropy_init(ctx: PMbedtls_Entropy_Context); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_CRYPTO{$ENDIF} name _PU + 'mbedtls_entropy_init'; + +procedure mbedtls_ctr_drbg_init(ctx: PMbedtls_CTR_DRBG_Context); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_CRYPTO{$ENDIF} name _PU + 'mbedtls_ctr_drbg_init'; +function mbedtls_ctr_drbg_seed(ctx: PMbedtls_CTR_DRBG_Context; f_entropy: TEntropyFunc; p_entropy: Pointer; custom: MarshaledAString; len: Size_T): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_CRYPTO{$ENDIF} name _PU + 'mbedtls_ctr_drbg_seed'; +function mbedtls_ctr_drbg_random_with_add(p_rng: Pointer; output: MarshaledAString; output_len: Size_T; additional: MarshaledAString; add_len: Size_T): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_CRYPTO{$ENDIF} name _PU + 'mbedtls_ctr_drbg_random_with_add'; +function mbedtls_ctr_drbg_random(p_rng: Pointer; output: MarshaledAString; output_len: Size_T): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_CRYPTO{$ENDIF} name _PU + 'mbedtls_ctr_drbg_random'; +procedure mbedtls_ctr_drbg_free(ctx: PMbedtls_CTR_DRBG_Context); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_CRYPTO{$ENDIF} name _PU + 'mbedtls_ctr_drbg_free'; + +function mbedtls_pk_parse_key(pk: PMbedtls_PK_Context; key: PByte; keylen: Size_T; pwd: PByte; pwdlen: Size_T): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_CRYPTO{$ENDIF} name _PU + 'mbedtls_pk_parse_key'; + +procedure mbedtls_pk_init(ctx: PMbedtls_PK_Context); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_CRYPTO{$ENDIF} name _PU + 'mbedtls_pk_init'; +procedure mbedtls_pk_free(ctx: PMbedtls_PK_Context); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_CRYPTO{$ENDIF} name _PU + 'mbedtls_pk_free'; + +function mbedtls_version_get_number: Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_CRYPTO{$ENDIF} name _PU + 'mbedtls_version_get_number'; +procedure mbedtls_version_get_string(string_: MarshaledAString); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_CRYPTO{$ENDIF} name _PU + 'mbedtls_version_get_string'; +procedure mbedtls_version_get_string_full(string_: MarshaledAString); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_CRYPTO{$ENDIF} name _PU + 'mbedtls_version_get_string_full'; + +procedure mbedtls_strerror(errnum: Integer; buffer: MarshaledAString; buflen: Size_T); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_CRYPTO{$ENDIF} name _PU + 'mbedtls_strerror'; + +procedure mbedtls_threading_set_alt(_mutex_init: Pointer; _mutex_free: Pointer; _mutex_lock: Pointer; _mutex_unlock: Pointer); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_CRYPTO{$ENDIF} name _PU + 'mbedtls_threading_set_alt'; +procedure mbedtls_threading_free_alt; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_CRYPTO{$ENDIF} name _PU + 'mbedtls_threading_free_alt'; +{$ENDREGION} + +{$REGION 'libmbedtls'} +function mbedtls_ssl_close_notify(ssl: PMbedtls_SSL_Context): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_close_notify'; +procedure mbedtls_ssl_free(ssl: PMbedtls_SSL_Context); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_free'; +function mbedtls_ssl_get_verify_result(ssl: PMbedtls_SSL_Context): UInt32_T; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_get_verify_result'; +function mbedtls_ssl_get_ciphersuite(const ssl: PMbedtls_SSL_Context): MarshaledAString; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_get_ciphersuite'; +function mbedtls_ssl_get_version(const ssl: PMbedtls_SSL_Context): MarshaledAString; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_get_version'; +function mbedtls_ssl_get_max_frag_len(const ssl: PMbedtls_SSL_Context): Size_T; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_get_max_frag_len'; +function mbedtls_ssl_get_peer_cert(const ssl: PMbedtls_SSL_Context): PMbedtls_X509_CRT; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_get_peer_cert'; +function mbedtls_ssl_get_session(const ssl: PMbedtls_SSL_Context; session: PMbedtls_SSL_Session): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_get_session'; +function mbedtls_ssl_get_ciphersuite_name(const ciphersuite_id: Integer): MarshaledAString; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_get_ciphersuite_name'; +function mbedtls_ssl_get_ciphersuite_id(const ciphersuite_name: MarshaledAString): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_get_ciphersuite_id'; +function mbedtls_ssl_handshake(ssl: PMbedtls_SSL_Context): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_handshake'; +procedure mbedtls_ssl_init(ssl: PMbedtls_SSL_Context); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_init'; +function mbedtls_ssl_list_ciphersuites: PInteger; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_list_ciphersuites'; +function mbedtls_ssl_read(ssl: PMbedtls_SSL_Context; buf: Pointer; len: Size_T): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_read'; +function mbedtls_ssl_set_hostname(ssl: PMbedtls_SSL_Context; hostname: MarshaledAString): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_set_hostname'; +procedure mbedtls_ssl_set_bio(ssl: PMbedtls_SSL_Context; p_bio: Pointer; f_send: TNetSendFunc; f_recv: TNetRecvFunc; f_recv_timeout: TNetRecvTimeoutFunc); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_set_bio'; +procedure mbedtls_ssl_set_timer_cb(ssl: PMbedtls_SSL_Context; p_timer: Pointer; f_set_timer: TSetTimerFunc; f_get_timer: TGetTimerFunc); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_set_timer_cb'; +function mbedtls_ssl_setup(ssl: PMbedtls_SSL_Context; conf: PMbedtls_SSL_Config): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_setup'; +function mbedtls_ssl_write(ssl: PMbedtls_SSL_Context; const buf: Pointer; len: Size_T): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_write'; + +procedure mbedtls_ssl_cache_init(cache: PMbedtls_SSL_Cache_Context); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_cache_init'; + +procedure mbedtls_ssl_config_init(conf: PMbedtls_SSL_Config); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_config_init'; +function mbedtls_ssl_config_defaults(conf: PMbedtls_SSL_Config; endpoint: Integer; transport: Integer; preset: Integer): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_config_defaults'; +procedure mbedtls_ssl_conf_authmode(conf: PMbedtls_SSL_Config; authmode: Integer); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_conf_authmode'; +procedure mbedtls_ssl_conf_ca_chain(conf: PMbedtls_SSL_Config; ca_chain: PMbedtls_X509_CRT; ca_crl: PMbedtls_X509_Crl); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_conf_ca_chain'; +procedure mbedtls_ssl_conf_transport(conf: PMbedtls_SSL_Config; transport: Integer); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_conf_transport'; +procedure mbedtls_ssl_conf_rng(conf: PMbedtls_SSL_Config; f_rng: TrngFunc; p_rng: Pointer); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_conf_rng'; +procedure mbedtls_ssl_conf_dbg(conf: PMbedtls_SSL_Config; f_dbg: TdbgFunc; p_dbg: Pointer); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_conf_dbg'; +procedure mbedtls_ssl_config_free(conf: PMbedtls_SSL_Config); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_config_free'; + +procedure mbedtls_ssl_conf_ciphersuites(conf: PMbedtls_SSL_Config; ciphersuites: PInteger); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_conf_ciphersuites'; + +function mbedtls_ssl_session_reset(ssl: PMbedtls_SSL_Context): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_session_reset'; +function mbedtls_ssl_set_session(ssl: PMbedtls_SSL_Context; const session: PMbedtls_SSL_Session): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_set_session'; +procedure mbedtls_ssl_conf_max_version(conf: PMbedtls_SSL_Config; major, minor: Integer); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_conf_max_version'; +procedure mbedtls_ssl_conf_min_version(conf: PMbedtls_SSL_Config; major, minor: Integer); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_conf_min_version'; +function mbedtls_ssl_get_bytes_avail(ssl: PMbedtls_SSL_Context): Size_T; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_get_bytes_avail'; + +procedure mbedtls_ssl_conf_session_cache(conf: PMbedtls_SSL_Config; p_cache: Pointer; f_get_cache: TGetCacheFunc; f_set_cache: TSetCacheFunc); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_conf_session_cache'; + +function mbedtls_ssl_cache_get(data: Pointer; session: PMbedtls_SSL_Session): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_cache_get'; +function mbedtls_ssl_cache_set(data: Pointer; const session: PMbedtls_SSL_Session): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_cache_set'; + +function mbedtls_ssl_conf_own_cert(conf: PMbedtls_SSL_Config; own_cert: PMbedtls_X509_CRT; pk_key: PMbedtls_PK_Context): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_conf_own_cert'; + +procedure mbedtls_ssl_cache_free(cache: PMbedtls_SSL_Cache_Context); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_cache_free'; +{$ENDREGION} + +{$REGION 'libmbedx509'} +procedure mbedtls_x509_crt_init(crt: PMbedtls_X509_CRT); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_X509{$ENDIF} name _PU + 'mbedtls_x509_crt_init'; +procedure mbedtls_x509_crt_free(crt: PMbedtls_X509_CRT); cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_X509{$ENDIF} name _PU + 'mbedtls_x509_crt_free'; +function mbedtls_x509_crt_parse(chain: PMbedtls_X509_CRT; buf: PByte; buflen: Size_T): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_X509{$ENDIF} name _PU + 'mbedtls_x509_crt_parse'; +function mbedtls_x509_crt_verify_info(buf: MarshaledAString; size_: Size_T; const prefix: MarshaledAString; flags: UInt32_T): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_X509{$ENDIF} name _PU + 'mbedtls_x509_crt_verify_info'; +{$ENDREGION} + +type + TMbedtls_Cipher_ID = ( + MBEDTLS_CIPHER_ID_NONE = 0, // **< Placeholder to mark the end of cipher ID lists. + MBEDTLS_CIPHER_ID_NULL, // **< The identity cipher, treated as a stream cipher. + MBEDTLS_CIPHER_ID_AES, // **< The AES cipher. + MBEDTLS_CIPHER_ID_DES, // **< The DES cipher. + MBEDTLS_CIPHER_ID_3DES, // **< The Triple DES cipher. + MBEDTLS_CIPHER_ID_CAMELLIA, // **< The Camellia cipher. + MBEDTLS_CIPHER_ID_BLOWFISH, // **< The Blowfish cipher. + MBEDTLS_CIPHER_ID_ARC4, // **< The RC4 cipher. + MBEDTLS_CIPHER_ID_ARIA, // **< The Aria cipher. + MBEDTLS_CIPHER_ID_CHACHA20 // **< The ChaCha20 cipher. + ); + + TMbedtls_Cipher_Mode = ( + MBEDTLS_MODE_NONE = 0, // **< None. + MBEDTLS_MODE_ECB, // **< The ECB cipher mode. + MBEDTLS_MODE_CBC, // **< The CBC cipher mode. + MBEDTLS_MODE_CFB, // **< The CFB cipher mode. + MBEDTLS_MODE_OFB, // **< The OFB cipher mode. + MBEDTLS_MODE_CTR, // **< The CTR cipher mode. + MBEDTLS_MODE_GCM, // **< The GCM cipher mode. + MBEDTLS_MODE_STREAM, // **< The stream cipher mode. + MBEDTLS_MODE_CCM, // **< The CCM cipher mode. + MBEDTLS_MODE_XTS, // **< The XTS cipher mode. + MBEDTLS_MODE_CHACHAPOLY // **< The ChaCha-Poly cipher mode. + ); + +function mbedtls_ssl_handshake_client_step(ssl: PMbedtls_SSL_Context): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_handshake_client_step'; + +function mbedtls_ssl_handshake_server_step(ssl: PMbedtls_SSL_Context): Integer; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_ssl_handshake_server_step'; + +function mbedtls_cipher_info_from_values(const cipher_id: TMbedtls_Cipher_ID; key_bitlen: Integer; const mode: TMbedtls_Cipher_Mode): PMbedtls_Cipher_Info; cdecl; external {$IFDEF __HAS_MBED_TLS_LIB__}LIB_MBED_TLS{$ENDIF} name _PU + 'mbedtls_cipher_info_from_values'; +{$ENDREGION} + +function MbedErrToStr(AErrCode: Integer): string; + +implementation + +{$IFDEF __HAS_MBED_TLS_OBJ__} + {$L aesni.obj} + {$L aria.obj} + {$L cmac.obj} + {$L ctr_drbg.obj} + {$L entropy.obj} + {$L entropy_poll.obj} + {$L error.obj} + {$L havege.obj} + {$L hkdf.obj} + {$L md2.obj} + {$L md4.obj} + {$L memory_buffer_alloc.obj} + {$L nist_kw.obj} + {$L pkcs11.obj} + {$L ssl_cache.obj} + {$L ssl_cookie.obj} + {$L ssl_ticket.obj} + {$L threading.obj} + {$L timing.obj} + {$L version.obj} + {$L version_features.obj} + {$L x509write_crt.obj} + {$L x509write_csr.obj} + {$L x509_create.obj} + {$L x509_crl.obj} + {$L x509_csr.obj} + {$L xtea.obj} + {$L asn1write.obj} + {$L pem.obj} + {$L platform.obj} + {$L pkwrite.obj} + {$L pkparse.obj} + {$L base64.obj} + {$L pkcs12.obj} + {$L pkcs5.obj} + {$L arc4.obj} + {$L ssl_cli.obj} + {$L ssl_srv.obj} + {$L ssl_tls.obj} + {$L ssl_ciphersuites.obj} + {$L debug.obj} + {$L x509_crt.obj} + {$L pk.obj} + {$L pk_wrap.obj} + {$L x509.obj} + {$L platform_util.obj} + {$L rsa.obj} + {$L rsa_internal.obj} + {$L oid.obj} + {$L ecjpake.obj} + {$L ecdsa.obj} + {$L ecdh.obj} + {$L ecp.obj} + {$L hmac_drbg.obj} + {$L dhm.obj} + {$L ecp_curves.obj} + {$L asn1parse.obj} + {$L md.obj} + {$L md_wrap.obj} + {$L cipher.obj} + {$L cipher_wrap.obj} + {$L ccm.obj} + {$L gcm.obj} + {$L aes.obj} + {$L camellia.obj} + {$L des.obj} + {$L blowfish.obj} + {$L chachapoly.obj} + {$L chacha20.obj} + {$L md5.obj} + {$L ripemd160.obj} + {$L sha1.obj} + {$L sha256.obj} + {$L sha512.obj} + {$L poly1305.obj} + {$L bignum.obj} +{$ENDIF} + +{$IFDEF __HAS_MBED_TLS_O__} + {$L aesni.o} + {$L aria.o} + {$L cmac.o} + {$L ctr_drbg.o} + {$L entropy.o} + {$L entropy_poll.o} + {$L error.o} + {$L havege.o} + {$L hkdf.o} + {$L md2.o} + {$L md4.o} + {$L memory_buffer_alloc.o} + {$L nist_kw.o} + {$L pkcs11.o} + {$L ssl_cache.o} + {$L ssl_cookie.o} + {$L ssl_ticket.o} + {$L threading.o} + {$L timing.o} + {$L version.o} + {$L version_features.o} + {$L x509write_crt.o} + {$L x509write_csr.o} + {$L x509_create.o} + {$L x509_crl.o} + {$L x509_csr.o} + {$L xtea.o} + {$L asn1write.o} + {$L pem.o} + {$L platform.o} + {$L pkwrite.o} + {$L pkparse.o} + {$L base64.o} + {$L pkcs12.o} + {$L pkcs5.o} + {$L arc4.o} + {$L ssl_cli.o} + {$L ssl_srv.o} + {$L ssl_tls.o} + {$L ssl_ciphersuites.o} + {$L debug.o} + {$L x509_crt.o} + {$L pk.o} + {$L pk_wrap.o} + {$L x509.o} + {$L platform_util.o} + {$L rsa.o} + {$L rsa_internal.o} + {$L oid.o} + {$L ecjpake.o} + {$L ecdsa.o} + {$L ecdh.o} + {$L ecp.o} + {$L hmac_drbg.o} + {$L dhm.o} + {$L ecp_curves.o} + {$L asn1parse.o} + {$L md.o} + {$L md_wrap.o} + {$L cipher.o} + {$L cipher_wrap.o} + {$L ccm.o} + {$L gcm.o} + {$L aes.o} + {$L camellia.o} + {$L des.o} + {$L blowfish.o} + {$L chachapoly.o} + {$L chacha20.o} + {$L md5.o} + {$L ripemd160.o} + {$L sha1.o} + {$L sha256.o} + {$L sha512.o} + {$L poly1305.o} + {$L bignum.o} +{$ENDIF} + +{$IFDEF MSWINDOWS} +type + HCRYPTPROV = ULONG_PTR; + +function CryptAcquireContextA(var phProv: HCRYPTPROV; pszContainer, pszProvider: LPCSTR; dwProvType, dwFlags: DWORD): BOOL; stdcall; external advapi32; + +function CryptGenRandom(hProv: HCRYPTPROV; dwLen: DWORD; pbBuffer: LPBYTE): BOOL; stdcall; external advapi32; + +function CryptReleaseContext(hProv: HCRYPTPROV; dwFlags: ULONG_PTR): BOOL; stdcall; external advapi32; +{$ENDIF} + +type + PTlsMutex = ^TTlsMutex; + TTlsMutex = record + Lock: TObject; + IsValid: Byte; + end; + +procedure _mutex_init(mutex: PTlsMutex); cdecl; +begin + mutex.Lock := TObject.Create; +end; + +procedure _mutex_free(mutex: PTlsMutex); cdecl; +begin + mutex.Lock.DisposeOf; +end; + +function _mutex_lock(mutex: PTlsMutex): Integer; cdecl; +begin + Result := 0; + System.TMonitor.Enter(mutex.Lock); +end; + +function _mutex_unlock(mutex: PTlsMutex): Integer; cdecl; +begin + Result := 0; + System.TMonitor.Exit(mutex.Lock); +end; + +function MbedErrToStr(AErrCode: Integer): string; +var + LBuf: array [0 .. 511] of Byte; +begin + mbedtls_strerror(AErrCode, @LBuf, 512); + Result := TMarshal.ReadStringAsAnsi(TPtrWrapper.Create(@LBuf)); +end; + +{$IFDEF WIN32} +function _calloc(nitems: Size_T; size: Size_T): Pointer; cdecl; +begin + Result := AllocMem(nitems * size); +end; + +procedure __llmul; cdecl; +asm + jmp System.@_llmul +end; + +procedure __lludiv; cdecl; +asm + jmp System.@_lludiv +end; + +procedure __llumod; cdecl; +asm + jmp System.@_llumod +end; + +procedure __lldiv; cdecl; +asm + jmp System.@_lldiv +end; + +procedure __llshl; cdecl; +asm + jmp System.@_llshl +end; +{$ENDIF} + +{$IFDEF WIN64} +function calloc(nitems: Size_T; size: Size_T): Pointer; cdecl; +begin + Result := AllocMem(nitems * size); +end; + +procedure __chkstk; +label + _loop1, _exit; +asm + lea r10, [rsp] + mov r11, r10 + sub r11, rax + and r11w, 0f000h + and r10w, 0f000h + _loop1: + sub r10, 01000h + cmp r10, r11 // more to go? + jl _exit + mov qword [r10], 0 // probe this page + jmp _loop1 + _exit: + ret +end; +{$ENDIF} + +initialization + mbedtls_threading_set_alt(@_mutex_init, @_mutex_free, @_mutex_lock, @_mutex_unlock); + +finalization + mbedtls_threading_free_alt; + +end. diff --git a/Net/Net.RawSocket.pas b/Net/Net.RawSocket.pas new file mode 100644 index 0000000..427905e --- /dev/null +++ b/Net/Net.RawSocket.pas @@ -0,0 +1,189 @@ +unit Net.RawSocket; + +interface + +uses + System.SysUtils, Net.SocketAPI, + {$IFDEF POSIX} + Posix.Base, Posix.SysSocket, Posix.NetinetIn + {$ELSE} + Winapi.Windows, Net.Winsock2, Net.Wship6 + {$ENDIF}; + +type + /// + /// 򵥵׽ֲ + /// + TRawSocket = class + private + FSocket: THandle; + FSockAddr: TRawSockAddrIn; + FPeerAddr: string; + FPeerPort: Word; + public + /// + /// ر Socket + /// + procedure Close; + + /// + /// ӵ, ֧ IPv6 + /// + function Connect(const AHost: string; APort: Word): Integer; + + /// + /// Socket ַָͶ˿, ֧ IPv6 + /// + function Bind(const Addr: string; APort: Word): Integer; + + /// + /// + /// + function Listen(backlog: Integer = SOMAXCONN): Integer; + + /// + /// һ, Socket + /// + function Accept(Addr: PSockAddr; AddrLen: PInteger): THandle; + + /// + /// + /// + function Recv(var Buf; len: Integer; flags: Integer = 0): Integer; + + /// + /// + /// + function Send(const Buf; len: Integer; flags: Integer = 0): Integer; + + /// + /// ݴַָ˿(UDP) + /// + function RecvFrom(const Addr: PSockAddr; var AddrLen: Integer; var Buf; + len: Integer; flags: Integer = 0): Integer; + + /// + /// ݵַָ˿(UDP) + /// + function SendTo(const Addr: PSockAddr; AddrLen: Integer; const Buf; + len: Integer; flags: Integer = 0): Integer; + + /// + /// ж׽ǷЧ + /// + function IsValid: Boolean; + + /// + /// ׽־ + /// + property Socket: THandle read FSocket; + + /// + /// ׽ֵַϢ + /// Connect Զ˵׽, õַԶ˵ַϢ + /// Bind ص׽, õַDZصַϢ + /// + property SockAddr: TRawSockAddrIn read FSockAddr; + property PeerAddr: string read FPeerAddr; + property PeerPort: Word read FPeerPort; + end; + +implementation + +{ TRawSocket } + +procedure TRawSocket.Close; +begin + if (FSocket = INVALID_HANDLE_VALUE) then Exit; + + TSocketAPI.CloseSocket(FSocket); + FSocket := INVALID_HANDLE_VALUE; +end; + +function TRawSocket.Connect(const AHost: string; APort: Word): Integer; +var + LHints: TRawAddrInfo; + LAddrInfo: PRawAddrInfo; +begin + FillChar(LHints, SizeOf(TRawAddrInfo), 0); + LHints.ai_family := AF_UNSPEC; + LHints.ai_socktype := SOCK_STREAM; + LHints.ai_protocol := IPPROTO_TCP; + LAddrInfo := TSocketAPI.GetAddrInfo(AHost, APort.ToString, LHints); + if (LAddrInfo = nil) then Exit(-1); + + try + FSocket := TSocketAPI.NewSocket(LAddrInfo.ai_family, LAddrInfo.ai_socktype, + LAddrInfo.ai_protocol); + if (FSocket = INVALID_HANDLE_VALUE) then Exit(-1); + + FSockAddr.AddrLen := LAddrInfo.ai_addrlen; + Move(LAddrInfo.ai_addr^, FSockAddr.Addr, LAddrInfo.ai_addrlen); + TSocketAPI.ExtractAddrInfo(@FSockAddr.Addr, FSockAddr.AddrLen, FPeerAddr, FPeerPort); + + TSocketAPI.SetKeepAlive(FSocket, 5, 3, 5); + Result := TSocketAPI.Connect(FSocket, @FSockAddr.Addr, FSockAddr.AddrLen); + finally + TSocketAPI.FreeAddrInfo(LAddrInfo); + end; +end; + +function TRawSocket.Bind(const Addr: string; APort: Word): Integer; +var + LHints: TRawAddrInfo; + LAddrInfo: PRawAddrInfo; +begin + FillChar(LHints, SizeOf(TRawAddrInfo), 0); + LHints.ai_family := AF_UNSPEC; + LHints.ai_socktype := SOCK_STREAM; + LHints.ai_protocol := IPPROTO_TCP; + LAddrInfo := TSocketAPI.GetAddrInfo(Addr, APort.ToString, LHints); + if (LAddrInfo = nil) then Exit(-1); + + FSockAddr.AddrLen := LAddrInfo.ai_addrlen; + Move(LAddrInfo.ai_addr^, FSockAddr.Addr, LAddrInfo.ai_addrlen); + TSocketAPI.FreeAddrInfo(LAddrInfo); + + TSocketAPI.ExtractAddrInfo(@FSockAddr.Addr, FSockAddr.AddrLen, FPeerAddr, FPeerPort); + + Result := TSocketAPI.Bind(FSocket, @FSockAddr.Addr, FSockAddr.AddrLen); +end; + +function TRawSocket.Listen(backlog: Integer): Integer; +begin + Result := TSocketAPI.Listen(FSocket, backlog); +end; + +function TRawSocket.Accept(Addr: PSockAddr; AddrLen: PInteger): THandle; +begin + Result := TSocketAPI.Accept(FSocket, Addr, AddrLen); +end; + +function TRawSocket.Recv(var Buf; len, flags: Integer): Integer; +begin + Result := TSocketAPI.Recv(FSocket, Buf, len, flags); +end; + +function TRawSocket.Send(const Buf; len, flags: Integer): Integer; +begin + Result := TSocketAPI.Send(FSocket, Buf, len, flags); +end; + +function TRawSocket.RecvFrom(const Addr: PSockAddr; var AddrLen: Integer; + var Buf; len, flags: Integer): Integer; +begin + Result := TSocketAPI.RecvFrom(FSocket, Addr, AddrLen, Buf, len, flags); +end; + +function TRawSocket.SendTo(const Addr: PSockAddr; AddrLen: Integer; const Buf; + len: Integer; flags: Integer): Integer; +begin + Result := TSocketAPI.SendTo(FSocket, Addr, AddrLen, Buf, len, flags); +end; + +function TRawSocket.IsValid: Boolean; +begin + Result := TSocketAPI.IsValidSocket(FSocket); +end; + +end. diff --git a/Net/Net.Winsock2.pas b/Net/Net.Winsock2.pas index 4150c82..1261e0e 100644 --- a/Net/Net.Winsock2.pas +++ b/Net/Net.Winsock2.pas @@ -65,7 +65,7 @@ Rev 1.5 4/19/2003 02:29:26 AM JPMugaas Added TransmitPackets API function call. Note that this is only supported in - Windows XP or later. + Winapi.Windows XP or later. Rev 1.4 4/19/2003 12:22:58 AM BGooijen @@ -182,7 +182,9 @@ interface {$ENDIF} uses - SysUtils, Windows; + System.SysUtils, + System.AnsiStrings, + Winapi.Windows; type EIdWinsockStubError = class(Exception) @@ -984,12 +986,12 @@ linger = record {$EXTERNALSYM FD_ALL_EVENTS} FD_ALL_EVENTS = (1 shl FD_MAX_EVENTS) - 1; -// All Windows Sockets error constants are biased by WSABASEERR from the "normal" +// All Winapi.Windows Sockets error constants are biased by WSABASEERR from the "normal" {$EXTERNALSYM WSABASEERR} WSABASEERR = 10000; -// Windows Sockets definitions of regular Microsoft C error constants +// Winapi.Windows Sockets definitions of regular Microsoft C error constants {$EXTERNALSYM WSAEINTR} WSAEINTR = WSABASEERR+ 4; @@ -1004,7 +1006,7 @@ linger = record {$EXTERNALSYM WSAEMFILE} WSAEMFILE = WSABASEERR+ 24; -// Windows Sockets definitions of regular Berkeley error constants +// Winapi.Windows Sockets definitions of regular Berkeley error constants {$EXTERNALSYM WSAEWOULDBLOCK} WSAEWOULDBLOCK = WSABASEERR+ 35; @@ -1081,7 +1083,7 @@ linger = record {$EXTERNALSYM WSAEREMOTE} WSAEREMOTE = WSABASEERR+ 71; -// Extended Windows Sockets error constant definitions +// Extended Winapi.Windows Sockets error constant definitions {$EXTERNALSYM WSASYSNOTREADY} WSASYSNOTREADY = WSABASEERR+ 91; @@ -1243,8 +1245,8 @@ linger = record {$EXTERNALSYM WSA_INFINITE} WSA_INFINITE = INFINITE; -{ Windows Sockets errors redefined as regular Berkeley error constants. - These are commented out in Windows NT to avoid conflicts with errno.h. +{ Winapi.Windows Sockets errors redefined as regular Berkeley error constants. + These are commented out in Winapi.Windows NT to avoid conflicts with errno.h. Use the WSA constants instead. } {$EXTERNALSYM EWOULDBLOCK} @@ -1851,7 +1853,7 @@ BLOB = record {$EXTERNALSYM NS_NLA} NS_NLA = 15; //* Network Location Awareness*/ - WindowsXP {$EXTERNALSYM NS_BTH} - NS_BTH = 16; //* Bluetooth SDP Namespace */ - Windows Vista + NS_BTH = 16; //* Bluetooth SDP Namespace */ - Winapi.Windows Vista {$EXTERNALSYM NS_NBP} NS_NBP = 20; @@ -1863,7 +1865,7 @@ BLOB = record {$EXTERNALSYM NS_NTDS} NS_NTDS = 32; - //Windows Vista namespaces + //Winapi.Windows Vista namespaces {$EXTERNALSYM NS_EMAIL} NS_EMAIL = 37; {$EXTERNALSYM NS_PNRPNAME} @@ -2134,7 +2136,7 @@ WSAQUERYSETW = record MSG_MCAST = $0800; {$IFNDEF WINCE} - //Windows Vista WSAPoll + //Winapi.Windows Vista WSAPoll //* Event flag definitions for WSAPoll(). */ {$EXTERNALSYM POLLRDNORM} POLLRDNORM = $0100; @@ -2878,14 +2880,14 @@ WSACOMPLETION = record var RemoteSockaddr: PSockAddr; var RemoteSockaddrLength: Integer); stdcall; {$IFNDEF WINCE} - //This is defined in the Windows Mobile 6 Standard SDK Refresh + //This is defined in the Winapi.Windows Mobile 6 Standard SDK Refresh //but I'm not sure what .DLL the function is in. I also couldn't find a WSAID //constant for it. {$EXTERNALSYM LPFN_WSARECVEX} LPFN_WSARECVEX = function(s: TSocket; var buf; len: Integer; var flags: Integer): Integer; stdcall; {$ENDIF} - //Windows Server 2003, Windows Vista + //Winapi.Windows Server 2003, Winapi.Windows Vista {$EXTERNALSYM LPFN_CONNECTEX} LPFN_CONNECTEX = function(const s : TSocket; const name: PSOCKADDR; const namelen: Integer; lpSendBuffer : Pointer; dwSendDataLength : DWORD; var lpdwBytesSent : DWORD; lpOverlapped : LPWSAOVERLAPPED) : BOOL; stdcall; {$EXTERNALSYM LPFN_DISCONNECTEX} @@ -2894,7 +2896,7 @@ WSACOMPLETION = record LPFN_WSARECVMSG = function(const s : TSocket; lpMsg : LPWSAMSG; var lpNumberOfBytesRecvd : DWORD; AOverlapped: Pointer; lpCompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE): Integer; stdcall; {$EXTERNALSYM LPFN_TRANSMITPACKETS} LPFN_TRANSMITPACKETS = function(s: TSocket; lpPacketArray: LPTRANSMIT_PACKETS_ELEMENT; nElementCount: DWORD; nSendSize: DWORD; lpOverlapped: LPWSAOVERLAPPED; dwFlags: DWORD): BOOL; stdcall; - //Windows Vista, Windows Server 2008 + //Winapi.Windows Vista, Winapi.Windows Server 2008 {$IFNDEF WINCE} {$EXTERNALSYM LPFN_WSASENDMSG} LPFN_WSASENDMSG = function(const s : TSocket; lpMsg : LPWSAMSG; const dwFlags : DWORD; var lpNumberOfBytesSent : DWORD; lpOverlapped : LPWSAOVERLAPPED; lpCompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE) : Integer; stdcall; @@ -3166,7 +3168,7 @@ WSACOMPLETION = record {$EXTERNALSYM GetAcceptExSockaddrs} GetAcceptExSockaddrs : LPFN_GETACCEPTEXSOCKADDRS = nil; {$IFNDEF WINCE} - //This is defined in the Windows Mobile 6 Standard SDK Refresh + //This is defined in the Winapi.Windows Mobile 6 Standard SDK Refresh //but I'm not sure what .DLL the function is in. I also couldn't find a WSAID //constant for it. {$EXTERNALSYM WSARecvEx} @@ -3181,7 +3183,7 @@ WSACOMPLETION = record {$EXTERNALSYM TransmitPackets} TransmitPackets : LPFN_TRANSMITPACKETS = nil; {$IFNDEF WINCE} - //Windows Vista, Windows Server 2008 + //Winapi.Windows Vista, Winapi.Windows Server 2008 {$EXTERNALSYM WSASendMsg} WSASendMsg: LPFN_WSASENDMSG = nil; {$EXTERNALSYM WSAPoll} @@ -3328,7 +3330,7 @@ ip_msfilter = record SIOCGMSFILTER = IOC_IN or ((SizeOf(u_long) and IOCPARM_MASK) shl 16) or (Ord('t') shl 8) or (127 or IOC_IN); {Do not Localize} {$IFNDEF WINCE} - //Windows 2008 and Windows Vista SP1 additions + //Winapi.Windows 2008 and Winapi.Windows Vista SP1 additions {$EXTERNALSYM SIO_IDEAL_SEND_BACKLOG_QUERY} SIO_IDEAL_SEND_BACKLOG_QUERY = IOC_OUT or ((SizeOf(u_long) and IOCPARM_MASK) shl 16) or (Ord('t') shl 8) or 123; {$EXTERNALSYM SIO_IDEAL_SEND_BACKLOG_CHANGE} @@ -3410,7 +3412,7 @@ ip_msfilter = record {$EXTERNALSYM IP_RECVTCLASS} IP_RECVTCLASS = 40; // Receive packet traffic class. {$EXTERNALSYM IP_ORIGINAL_ARRIVAL_IF} - IP_ORIGINAL_ARRIVAL_IF = 47; // Original Arrival Interface Index. (Windows 7) + IP_ORIGINAL_ARRIVAL_IF = 47; // Original Arrival Interface Index. (Winapi.Windows 7) {$IFDEF WINCE} @@ -4003,9 +4005,9 @@ ADDRINFOW = record {$EXTERNALSYM AI_RETURN_PREFERRED_NAMES} AI_RETURN_PREFERRED_NAMES = $00010000; // LUP_RETURN_PREFERRED_NAMES (Vista or later and applies only to NS_EMAIL namespace.) {$EXTERNALSYM AI_FQDN} - AI_FQDN = $00020000; // Return the FQDN in ai_canonname (Windows 7 or later) + AI_FQDN = $00020000; // Return the FQDN in ai_canonname (Winapi.Windows 7 or later) {$EXTERNALSYM AI_FILESERVER} - AI_FILESERVER = $00040000; // Resolving fileserver name resolution (Windows 7 or later) + AI_FILESERVER = $00040000; // Resolving fileserver name resolution (Winapi.Windows 7 or later) type @@ -4062,10 +4064,10 @@ ADDRINFOEXW = record { wsipx.h - Microsoft Windows + Microsoft Winapi.Windows Copyright (C) Microsoft Corporation, 1992-1999. - Windows Sockets include file for IPX/SPX. This file contains all + Winapi.Windows Sockets include file for IPX/SPX. This file contains all standardized IPX/SPX information. Include this header file after winsock.h. @@ -4123,9 +4125,9 @@ SOCKADDR_IPX = record { wsnwlink.h - Microsoft Windows + Microsoft Winapi.Windows Copyright (C) Microsoft Corporation, 1992-1999. - Microsoft-specific extensions to the Windows NT IPX/SPX Windows + Microsoft-specific extensions to the Winapi.Windows NT IPX/SPX Winapi.Windows Sockets interface. These extensions are provided for use as necessary for compatibility with existing applications. They are otherwise not recommended for use, as they are only guaranteed to @@ -4359,7 +4361,7 @@ IPX_SPXCONNSTATUS_DATA = record // wsnetbs.h // Copyright (c) 1994-1999, Microsoft Corp. All rights reserved. // -// Windows Sockets include file for NETBIOS. This file contains all +// Winapi.Windows Sockets include file for NETBIOS. This file contains all // standardized NETBIOS information. Include this header file after // winsock.h. @@ -5143,10 +5145,10 @@ procedure InitializeWinSock; if LError = 0 then begin Exit; end; - Windows.FreeLibrary(hWinSockDll); + Winapi.Windows.FreeLibrary(hWinSockDll); hWinSockDll := 0; end else begin - LError := Windows.GetLastError; + LError := Winapi.Windows.GetLastError; end; raise EIdWinsockStubError.Build(LError, RSWinsockLoadError, [WINSOCK2_DLL]); end; @@ -5159,7 +5161,7 @@ procedure LoadMSWSock; if hMSWSockDll = 0 then begin hMSWSockDll := SafeLoadLibrary(MSWSOCK_DLL); if hMSWSockDll = 0 then begin - raise EIdWinsockStubError.Build(Windows.GetLastError, RSWinsockLoadError, [MSWSOCK_DLL]); + raise EIdWinsockStubError.Build(Winapi.Windows.GetLastError, RSWinsockLoadError, [MSWSOCK_DLL]); end; end; end; @@ -5190,7 +5192,7 @@ constructor EIdWinsockStubError.Build(AWin32Error: DWORD; const ATitle: String; inherited Create(FTitle); end else begin - FWin32ErrorMessage := SysUtils.SysErrorMessage(AWin32Error); + FWin32ErrorMessage := System.SysUtils.SysErrorMessage(AWin32Error); inherited Create(FTitle + ': ' + FWin32ErrorMessage); {Do not Localize} end; end; @@ -5208,7 +5210,7 @@ function FixupStub(hDll: THandle; const AName:{$IFDEF WINCE}TIdUnicodeString{$EL if hDll = 0 then begin raise EIdWinsockStubError.Build(WSANOTINITIALISED, RSWinsockCallError, [AName]); end; - Result := Windows.GetProcAddress(hDll, {$IFDEF WINCE}PWideChar{$ELSE}PChar{$ENDIF}(AName)); + Result := Winapi.Windows.GetProcAddress(hDll, {$IFDEF WINCE}PWideChar{$ELSE}PChar{$ENDIF}(AName)); if Result = nil then begin raise EIdWinsockStubError.Build(WSAEINVAL, RSWinsockCallError, [AName]); end; @@ -6511,7 +6513,7 @@ function IN6ADDR_ISLOOPBACK(sa: PSockAddrIn6): Boolean; function IN6_ADDR_EQUAL(const a: PIn6Addr; const b: PIn6Addr): Boolean; {$IFDEF USE_INLINE}inline;{$ENDIF} begin - Result := SysUtils.CompareMem(a, b, SIZE_TIN6ADDR); + Result := System.SysUtils.CompareMem(a, b, SIZE_TIN6ADDR); end; function IN6_IS_ADDR_UNSPECIFIED(const a: PIn6Addr): Boolean; @@ -6718,7 +6720,7 @@ procedure SET_NETBIOS_SOCKADDR(snb : PSockAddrNB; const SnbType : Word; const Na with snb^ do begin snb_family := AF_NETBIOS; snb_type := SnbType; - len := StrLen(Name); + len := System.AnsiStrings.StrLen(Name); if len >= NETBIOS_NAME_LENGTH-1 then begin System.Move(Name^, snb_name, NETBIOS_NAME_LENGTH-1); end else begin diff --git a/README.md b/README.md index 8f2d9bf..8435260 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,14 @@ 作者: WiNDDRiVER(soulawing@gmail.com) -## 重要更新(2017.08.22) +## 更新记录 + +#### 2019.01.15 +- 增加 mbedtls 支持 + - mbedtls 启用方法:在工程编译选项中开启 \__CROSS_SSL\__ 和 \__MBED_TLS\__ 这两个编译开关, 并且将 MbedObj 下的目录添加到对应平台的 Library path 中 + - 目前本框架的 mbedtls 移植尚不稳定, 请勿用于生产环境 + +#### 2017.08.22 - 代码重构, 做了大量修改, 详见源码 - 增加了几个新的 interface, 用法详见 demos - ICrossSocket @@ -10,7 +17,6 @@ - ICrossServer - ICrossSslServer - ## 特性 - 针对不同平台使用不同的IO模型: diff --git a/Utils/Utils.DateTime.pas b/Utils/Utils.DateTime.pas index b50bf9d..ff3e11c 100644 --- a/Utils/Utils.DateTime.pas +++ b/Utils/Utils.DateTime.pas @@ -12,7 +12,10 @@ interface uses - System.SysUtils, System.DateUtils, System.Types, System.Math, System.TimeSpan; + System.SysUtils, + System.DateUtils, + System.Types, + System.Math; type TDateTimeHelper = record helper for TDateTime diff --git a/Utils/Utils.Utils.pas b/Utils/Utils.Utils.pas index 0a5d4f6..1cd395b 100644 --- a/Utils/Utils.Utils.pas +++ b/Utils/Utils.Utils.pas @@ -19,7 +19,8 @@ interface System.Math, System.Diagnostics, System.TimeSpan, - System.Character; + System.Character, + System.SysConst; type TUtils = class @@ -47,6 +48,7 @@ TUtils = class class function UnicodeTrim(const S: string): string; static; class function UnicodeTrimLeft(const S: string): string; static; class function UnicodeTrimRight(const S: string): string; static; + class function StrIPos(const ASubStr, AStr: string; AOffset: Integer): Integer; static; class procedure BinToHex(ABuffer: Pointer; ABufSize: Integer; AText: PChar); overload; static; class function BinToHex(ABuffer: Pointer; ABufSize: Integer): string; overload; static; inline; @@ -56,6 +58,9 @@ TUtils = class class function GetFullFileName(const AFileName: string): string; static; class function GetFileSize(const AFileName: string): Int64; static; + // 判断两段日期是否有交集 + class function IsCrossDate(const AStartDate1, AEndDate1, AStartDate2, AEndDate2: TDateTime): Boolean; + class property AppFile: string read FAppFile; class property AppPath: string read FAppPath; class property AppHome: string read FAppHome; @@ -63,6 +68,13 @@ TUtils = class class property AppName: string read FAppName; end; + TEncodingHelper = class helper for TEncoding + /// + /// 从内存块中直接解码出字符串, 省去先将内存块转换为TBytes, 从而提高效率 + /// + function GetString(ABytes: PByte; AByteCount: Integer): string; overload; + end; + implementation { TUtils } @@ -151,6 +163,12 @@ class function TUtils.GetGUID: string; // LGuid.D4[4], LGuid.D4[5], LGuid.D4[6], LGuid.D4[7]]); end; +class function TUtils.IsCrossDate(const AStartDate1, AEndDate1, AStartDate2, + AEndDate2: TDateTime): Boolean; +begin + Result := (AEndDate1 >= AStartDate2) and (AStartDate1 <= AEndDate2); +end; + class function TUtils.IsSpaceChar(const C: Char): Boolean; begin Result := (C.GetUnicodeCategory in [ @@ -212,6 +230,54 @@ class function TUtils.SimilarText(const AStr1, AStr2: string): Single; Result := 1 - (EditDistance(AStr1, AStr2) / Max(AStr1.Length, AStr2.Length)); end; +class function TUtils.StrIPos(const ASubStr, AStr: string; + AOffset: Integer): Integer; +var + I, LIterCnt, L, J: Integer; + PSubStr, PS: PChar; + LCh: Char; +begin + PSubStr := Pointer(ASubStr); + PS := Pointer(AStr); + if (PSubStr = nil) or (PS = nil) or (AOffset < 1) then + Exit(0); + L := Length(ASubStr); + { Calculate the number of possible iterations. } + LIterCnt := Length(AStr) - AOffset - L + 2; + if (L > 0) and (LIterCnt > 0) then + begin + Inc(PS, AOffset - 1); + I := 0; + LCh := UpCase(PSubStr[0]); + if L = 1 then // Special case when Substring length is 1 + repeat + if UpCase(PS[I]) = LCh then + Exit(I + AOffset); + Inc(I); + until I = LIterCnt + else + repeat + if UpCase(PS[I]) = LCh then + begin + J := 1; + repeat + if UpCase(PS[I + J]) = UpCase(PSubStr[J]) then + begin + Inc(J); + if J = L then + Exit(I + AOffset); + end + else + Break; + until False; + end; + Inc(I); + until I = LIterCnt; + end; + + Result := 0; +end; + class function TUtils.StrToDateTime(const S: string): TDateTime; begin Result := StrToDateTime(S, 'yyyy-mm-dd hh:nn:ss'); @@ -405,4 +471,22 @@ class function TUtils.EditDistance(const ASourceStr, ATargetStr: string): Intege Result := d[ASourceStr.length][ATargetStr.length]; end; +{ TEncodingHelper } + +function TEncodingHelper.GetString(ABytes: PByte; AByteCount: Integer): string; +var + LSize: Integer; +begin + if (ABytes = nil) then + raise EEncodingError.CreateRes(@SInvalidSourceArray); + if (AByteCount < 0) then + raise EEncodingError.CreateResFmt(@SInvalidCharCount, [AByteCount]); + + LSize := GetCharCount(ABytes, AByteCount); + if (AByteCount > 0) and (LSize = 0) then + raise EEncodingError.CreateRes(@SNoMappingForUnicodeCharacter); + SetLength(Result, LSize); + GetChars(ABytes, AByteCount, PChar(Result), LSize); +end; + end.