You are not logged in.
I use the event EchoCustom to log server behavior. However, I would like that every REST service had its own, separate log (separate event EchoCustom). How to do it correctly? Do I have to create an instance TSynLogFamily in each REST service?
btw it's interesting...
In Delphi XE2 message is:
E2251 Ambiguous overloaded call to 'HexToBin'"
in Delphi Berlin:
E2012 Type of expression must be BOOLEAN
Why Berlin message is inaccurate?
Probably conflict in function name with unit System.Classes:
function HexToBin(Text: PWideChar; Buffer: PAnsiChar; BufSize: Integer): Integer; overload;
In SyslogMessage():
if trimmsgfromlog and (len>27) then
if (P[0]='2') and (P[8]=' ') then begin
inc(P,27); // trim e.g. '20160607 06442255 ! trace '
dec(len,27);
end else
if HexToBin(P,nil,8) then begin <------------------------------ line with error message
inc(P,25); // trim e.g. '00000000089E5A13 " info '
dec(len,25);
end;Delphi Berlin
Thanks for clarification. One more question:
why JSON is different (name quoted) between transfer as object or as record?
See on fields eg. VATID (and others):
send as record (with quotes):
{"VATID":"","PersonKind":76,"PKD":"","PlaceId":"","CommuneId":"","ProductId":268484512,"ProductVersion":0,"ProductReleaseDate":10000,"DemoVersionMode":76,"LastReceivedUUID":"","SystemId":42678,"SystemCodePage":-702306117,"ScreenResolution":-2,"DateOfCommencement":10000}
send as object (without quotes):
{VATID:"87654332",CommuneId:"0",DateOfCommencement:1485632481,LastReceivedUUID:"{3C71F148-5F70-4177-AF94-544E51FDC5D6}",PKD:"pkd",PlaceId:"09",ProductId:1234,ProductReleaseDate:100000,ProductVersion:87675675,ScreenResolution:700,SystemCodePage:987,SystemId:150}When I pass object via interfaced service method (with {$M+} and published) then before mORMot deserialize JSON with data of object I must create this object?
example:
service method:
function GetObject(const ObjectId : Integer; out Object : TMyObject);use of this method:
var
lObject : TMyObject;
//lObject := TMyObject.Create; <-- without create object I get error on next line
GetObject(x, lObject); //<-- error if lObject = nilmORMot can't autocreate this object?
I knew that these points was blind ;-P
Thanks! But why do you paste three point list for me? ;-)
If you change the type RawJSON to RawUTF8?
It helped (escaping string in response), thx.
But I don't understand what is the type of RawJSON?
Problem is no with record, but with field of type RawJSON that is coded with additional quotes and on client side decoding of server response raise error. Without this field call is sucessful.
{"UUID":"16551D01-CA15-4B32-BDFB-F5D0BDDA42E7",
"ReleaseTimestamp":1484210095,
"DeadTimestamp":1486767600,
"Topic":"Msg from: 2017-01-12 09:34:54",
"ContentsType":66,
"TagList":"{"Tag":["11","22","33","44"]}", <---- see this, JSON parser not decoding this strange item
"DemoVersionMode":76,
"PersonKind":78}}It seems to me that the type of RawJSON should be wrapped (be escaped).
I have server based on interfaced services.
In service I have method:
function GetAnnouncementList(out aAnnouncementList: TAnnouncementDataList): Integer;where:
TAnnouncementDataList = TArray<RAnnouncementData>;
RAnnouncementData = record
UUID : TAnnouncementUUID;
ReleaseTimestamp: TUnixTimestampUTC;
DeadTimestamp : TUnixTimestampUTC;
Topic: RawUTF8;
ContentsType: SmallInt;
TagList : RawJSON; <------------------------------------------ this is problematic
DemoVersionMode : AnsiChar;
PersonKind : AnsiChar;
end;On client side I get this array like:
{"result":[[{"UUID":"16551D01-CA15-4B32-BDFB-F5D0BDDA42E7","ReleaseTimestamp":1484210095,"DeadTimestamp":1486767600,"Topic":"Msg from: 2017-01-12 09:34:54","ContentsType":66,
"TagList":"{"Tag":["11","22","33","44"]}","DemoVersionMode":76,"PersonKind":78},{"UUID":"FB5A930F-3D3C-4395-B4AC-81CA639E490C","ReleaseTimestamp":1484210097,"DeadTimestamp":1486767600,"Topic":"Msg from: 2017-01-12 09:34:57","ContentsType":66,
"TagList":"{"Tag":["11","22","33","44"]}","DemoVersionMode":76,"PersonKind":78}],2]}Pay attention that TagList has quotes around:
--->"{"Tag":["11","22","33","44"]}"<---and client raise exception EInterfaceFactoryException on decoding this:
''Invalid returned JSON content: expects {result:...}, got {"result~~[[{"UUID":"16551D01-CA15-4B32-BDFB-F5D0BDDA42E7","ReleaseTimestamp":1484210095,"DeadTimestamp":1486767600,"Topic":"Wiadomość z chwili: 2017-01-12 09:34:54","ContentsType":66,"TagList":"{"Tag":["11","22","33","44"]}","DemoVersionMode":76,"PersonKind":78},{"UUID":"FB5A930F-3D3C-4395-B4AC-81CA639E490C","ReleaseTimestamp":1484210097,"DeadTimestamp":1486767600,"Topic":"Wiadomość z chwili: 2017-01-12 09:34:57","ContentsType":66,"TagList":"{"Tag":["11","22","33","44"]}","DemoVersionMode":76,"PersonKind":78}],2]}''I generate the JSON in business code on the server side and I want to send it to the client.
What am I doing wrong? How can I do this right?
I confirm this bug.
[dcc32 Error] SynEcc.pas(3251): E2382 Cannot call constructors using instance variables
Maybe paranoid, but useful when tracing mem leaks :-)
Thx for info about SSE 42.
I search for except reason and.. I found. MadExcept cause this when option "Instantly crash on buffer overrun" is checked.

Delphi version from MadExcept report: Delphi 10.1 Berlin
Framework up to date.
How can I help?
Screenshot before raised exception:
I use SynCrypto unit, it works ok. But when I enabled MadExcept to trace some memory leaks then Application raise AV on start, see callstack:
date/time : 2016-09-18, 13:30:43, 480ms
operating system : Windows 10 x64 build 14393
system language : Polish
system up time : 3 hours 15 minutes
program up time : 575 milliseconds
processors : 8x Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz
physical memory : 8647/16323 MB (free/total)
free disk space : (C:) 315,53 GB (D:) 222,00 GB
display mode : 1920x1200, 32 bit
process id : $2a48
allocated memory : 240,97 MB
largest free block : 769,83 MB
executable : JPKSender.exe
exec. date/time : 2016-09-18 13:30
version : 1.0.0.0
compiled with : Delphi 10.1 Berlin
madExcept version : 4.0.15
callstack crc : $3a9974cc, $a6b50739, $a6b50739
exception number : 1
exception class : EAccessViolation
exception message : Access violation at address 00864ABC in module 'JPKSender.exe'. Read of address 0A1C3000.
main thread ($33a8):
00864abc +008 JPKSender.exe SynCommons 23250 +5 StrCompSSE42
00868899 +031 JPKSender.exe SynCommons 32958 +5 FastFindPUTF8CharSorted
0086bdb0 +02c JPKSender.exe SynCommons 36327 +3 TJSONCustomParserRTTI.TypeNameToSimpleRTTIType
0086de39 +045 JPKSender.exe SynCommons 37008 +2 GetNextFieldType
0086dfe1 +145 JPKSender.exe SynCommons 37047 +29 TJSONRecordTextDefinition.Parse
0086dca0 +090 JPKSender.exe SynCommons 36991 +7 TJSONRecordTextDefinition.Create
0086dbec +070 JPKSender.exe SynCommons 36976 +8 TJSONRecordTextDefinition.FromCache
0086aff2 +06e JPKSender.exe SynCommons 35937 +6 TJSONCustomParsers.RegisterFromText
0087e37a +01a JPKSender.exe SynCommons 45053 +1 TTextWriter.RegisterCustomJSONSerializerFromText
00bdc438 +08c JPKSender.exe SynCommons 59135 +25 initialization
0040a186 +042 JPKSender.exe System 22279 +18 InitUnits
0040a1ef +03f JPKSender.exe System 22351 +14 @StartExe
004119a2 +042 JPKSender.exe SysInit 1419 +11 @InitExe
00bddf73 +00b JPKSender.exe JPKSender 58 +0 initialization
740862c2 +022 KERNEL32.DLL BaseThreadInitThunk
thread $2530:
740862c2 +22 KERNEL32.DLL BaseThreadInitThunk
thread $18f0:
740862c2 +22 KERNEL32.DLL BaseThreadInitThunk
cpu registers:
eax = f66a8cc0
ebx = 00000000
ecx = 0a1c2ff8
edx = 0a1c2ff8
esi = 00bdc3ac
edi = 000001f6
eip = 00864abc
esp = 0019fd54
ebp = 0019fd70
stack dump:
0019fd54 9f 88 86 00 59 57 86 00 - 00 00 00 00 0f 00 00 00 ....YW..........
0019fd64 f8 2f 1c 0a 1f 00 00 00 - 70 b9 be 00 8c fd 19 00 ./......p.......
0019fd74 b5 bd 86 00 e9 fd 00 00 - 06 70 88 00 06 00 00 00 .........p......
0019fd84 f8 2f 1c 0a 98 68 85 00 - b0 fd 19 00 3e de 86 00 ./...h......>...
0019fd94 0c fe 19 00 1e 29 86 00 - e9 fd 00 00 06 00 00 00 .....)..........
0019fda4 e8 c4 bd 00 0c fe 19 00 - 80 fe 19 00 34 fe 19 00 ............4...
0019fdb4 e6 df 86 00 34 fe 19 00 - 40 fe 19 00 24 9d 40 00 ....4...@...$.@.
0019fdc4 34 fe 19 00 bc b9 85 00 - 0c fe 19 00 cd 6f 40 00 4............o@.
0019fdd4 e8 fd 19 00 43 d1 40 00 - dc cf 1c 0a 04 00 00 00 ....C.@.........
0019fde4 e8 0f 1d 0a e8 8f 1c 0a - f0 8f 1c 0a 00 00 00 00 ................
0019fdf4 1c fe 19 00 00 00 00 00 - 28 a7 40 00 01 00 00 00 ........(.@.....
0019fe04 20 d3 4f 00 00 00 00 00 - 00 00 00 00 e6 d1 0c 00 .O.............
0019fe14 1c fe 19 00 e7 31 52 00 - be eb 58 00 00 00 00 00 .....1R...X.....
0019fe24 00 00 00 00 80 fe 19 00 - dc cf 1c 0a e8 2f 1d 0a ............./..
0019fe34 90 fe 19 00 a5 dc 86 00 - 00 00 00 00 c0 fe 19 00 ................
0019fe44 03 9f 40 00 90 fe 19 00 - e8 2f 1d 0a 90 fe 19 00 ..@....../......
0019fe54 e6 d1 40 00 60 fe 19 00 - ed 6b 88 00 40 00 00 00 ..@.`....k..@...
0019fe64 40 00 00 00 00 8f 1d 0a - 40 00 00 00 00 00 00 00 @.......@.......
0019fe74 dc cf 1c 0a e8 0f 1d 0a - f6 01 00 01 f4 c4 bd 00 ................
0019fe84 f0 50 85 00 e8 c4 bd 01 - e8 2f 1d 0a b8 fe 19 00 .P......./......I found error!!! Of course in my code... :-(
And again, I refactored and simplified example code, please look...
program Project2;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Classes,
SynCrypto;
const
//string to encrypting
CInputString : string = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque hendrerit augue quis lacus efficitur,' +
' sollicitudin tempor sapien dapibus. Vivamus quis neque congue, imperdiet nisi nec, hendrerit nulla.' +
' Ut quis dolor eget sapien sodales faucibus vel at turpis. Aenean sed varius arcu.';
//password
CPassword : TBytes = [0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1];
//AES initialization vector
CIV: TAESBlock = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
//function to encrypt aInStream used aPassword and aAESClass, result is saved to aOutStream
procedure AESstreamCrypt(aAESClass: TAESAbstractClass; const aInStream, aOutStream: TStream; const aPassword: TBytes);
var
aKeySize: Integer;
lAES : TAESAbstract;
lIn : RawByteString;
lOut : RawByteString;
begin
//get AES key size
aKeySize := Length(aPassword) shl 3;
//create an AES class object to encrypt stream
lAES := aAESClass.Create(aPassword, aKeySize);
try
//copy aInStream to RawByteString local variable
SetLength(lIn, aInStream.Size);
aInStream.Position := 0;
aInStream.ReadBuffer(lIn[1], aInStream.Size);
//assign const vector
lAES.IV := CIV;
//encrypt TBytes
lOut := lAES.EncryptPKCS7(lIn, False);
//copy encrypted RawByteString to aOutStream
aOutStream.Write(lOut[1], Length(lOut));
finally
lAES.Free;
end;
end;
//function to decrypt aInStream used aPassword and aEASClass, result is saved to aOutStream
procedure AESstreamDecrypt(aAESClass: TAESAbstractClass; aInStream, aOutStream: TStream; const aPassword: TBytes);
var
aKeySize: Integer;
lAES : TAESAbstract;
lIn : RawByteString;
lOut: RawByteString;
begin
//get AES key size
aKeySize := Length(aPassword) shl 3;
//create AES class object to decrypt stream
lAES := aAESClass.Create(aPassword, aKeySize);
try
//copy aInStream to RawByteString local variable
SetLength(lIn, aInStream.Size);
aInStream.Position := 0;
aInStream.ReadBuffer(lIn[1], aInStream.Size);
//assign const vector
lAES.IV := CIV;
//decrypt TBytes
lOut := lAES.DecryptPKCS7(lIn, False);
//copy decrypted RawByteString to aOutStream
aOutStream.Write(lOut[1], Length(lOut));
finally
lAES.Free;
end;
end;
//simple wrapper on crypt method which only passes arguments to crypt method
procedure streamCryptWrapper(const aInStream, aOutStream: TStream; const aPassword: TBytes);
begin
AESstreamCrypt(TAESCBC, aInStream, aOutStream, aPassword);
end;
//simple wrapper on decrypt method which only passes arguments to decrypt method
procedure streamDecryptWrapper(const aInStream, aOutStream: TStream; const aPassword: TBytes);
begin
AESstreamDecrypt(TAESCBC, aInStream, aOutStream, aPassword);
end;
procedure SelfTest;
var
decodedString: String;
InStr, OutStr : TStringStream;
begin
InStr := TStringStream.Create;
OutStr := TStringStream.Create;
try
// TEST 1 ------------------------------------------------------------------
InStr.Clear;
OutStr.Clear;
//put string into stream
InStr.WriteString(CInputString);
// crypt stream InStr -> OutStr
AESstreamCrypt(TAESCBC, InStr, OutStr, CPassword);
//decrypt stream OutStr -> InStr
InStr.Clear;
AESstreamDecrypt(TAESCBC, OutStr, InStr, CPassword);
//check decoded string
decodedString := InStr.DataString;
Assert(decodedString = CInputString);
// TEST 1 PASSED
// end of TEST 1 -----------------------------------------------------------
// -------------------------------------------------------------------------
// TEST 2 with simple wrapper - cause exception!
InStr.Clear;
OutStr.Clear;
//put string into stream
InStr.WriteString(CInputString);
// crypt stream InStr -> OutStr
streamCryptWrapper(InStr, OutStr, CPassword);
// decrypt stream OutStr -> InStr
InStr.Clear;
streamDecryptWrapper(OutStr, InStr, CPassword); // <--- ESynCrypto exception: TAESCBC.DecryptPKCS7: Invalid content, why??
//check decoded string
decodedString := InStr.DataString;
Assert(decodedString = CInputString);
// end of TEST 2 -----------------------------------------------------------
finally
InStr.Free;
OutStr.Free;
end;
end;
begin
try
SelfTest;
except
on E: ESynCrypto do
Writeln('ESynCrypto: ', E.Message); //TAESCBC.DecryptPKCS7: Invalid content !!!
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end....and thanks for time.
The main problem is a bug when I use wrappers, I don't know why :-(
FixInsight show warnings on SynCrypto, maybe unimportant, but...
[FixInsight Warning] SynCrypto.pas(6734): W517 Variable 'iv' hides a class field, method or property
[FixInsight Warning] SynCrypto.pas(6770): W517 Variable 'iv' hides a class field, method or property
[FixInsight Warning] SynCrypto.pas(6784): W517 Variable 'iv' hides a class field, method or property
[FixInsight Warning] SynCrypto.pas(5062): W521 Return value of function 'TAESFull.EncodeDecode' might be undefined
I add some comments:
program Project2;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Classes,
SynCrypto;
//helper function to convert ansi string to TBytes
function convertSB (const arg: AnsiString): TBytes;
var
i: integer;
begin
Setlength(Result, Length(arg));
for i := 0 to length(arg) - 1 do
begin
result[i] := ord (arg [i + 1]);
end;
end;
//function to encrypt aInStream used aPassword and aAESClass, result is saved to aOutStream
function AESstreamCrypt(aAESClass: TAESAbstractClass; const aInStream, aOutStream: TStream; const aPassword: TBytes): Integer;
var
aKeySize: Integer;
lAES : TAESAbstract;
lBytesIn : TBytes;
lBytesOut : TBytes;
begin
//get AES key size
aKeySize := Length(aPassword) shl 3;
//create an AES class object to encrypt stream
lAES := aAESClass.Create(aPassword, aKeySize);
try
//copy aInStream to TBytes local variable
SetLength(lBytesIn, aInStream.Size);
aInStream.Position := 0;
aInStream.ReadBuffer(lBytesIn[0], aInStream.Size);
//encrypt TBytes
lBytesOut := lAES.EncryptPKCS7(lBytesIn, True);
Result := Length(lBytesOut);
//copy encrypted TBytes to aOutStream
aOutStream.Write(lBytesOut[0], Length(lBytesOut));
finally
lAES.Free;
end;
end;
//function to decrypt aInStream used aPassword and aEASClass, result is saved to aOutStream
function AESstreamDecrypt(aAESClass: TAESAbstractClass; aInStream, aOutStream: TStream; const aPassword: TBytes):
Integer;
var
aKeySize: Integer;
lAES : TAESAbstract;
lBytesIn : TBytes;
lBytesOut : TBytes;
begin
//get AES key size
aKeySize := Length(aPassword) shl 3;
//create AES class object to decrypt stream
lAES := aAESClass.Create(aPassword, aKeySize);
try
//copy aInStream to TBytes local variable
SetLength(lBytesIn, aInStream.Size);
aInStream.Position := 0;
aInStream.ReadBuffer(lBytesIn[0], aInStream.Size);
//decrypt TBytes
lBytesOut := lAES.DecryptPKCS7(lBytesIn, True);
Result := Length(lBytesOut);
//copy decrypted TBytes to aOutStream
aOutStream.Write(lBytesOut[0], Length(lBytesOut));
finally
lAES.Free;
end;
end;
//simple wrapper for AESstreamCrypt function
procedure streamCryptWrapper(const aInStream, aOutStream: TStream; const aPassword: TBytes);
begin
AESstreamCrypt(TAESCBC, aInStream, aOutStream, aPassword);
end;
//simple wrapper for AESstreamDecrypt function
procedure streamDecryptWrapper(const aInStream, aOutStream: TStream; const aPassword: TBytes);
begin
AESstreamDecrypt(TAESCBC, aInStream, aOutStream, aPassword);
end;
//test direct crypt and wrapped crypt
procedure SelfTest;
var
decodedString: String;
inputString: string;
InStr, OutStr : TMemoryStream;
InputStringStream : TStringStream;
lInStrStream, lOutStrStream : TStringStream;
lPasswordBytes: TBytes;
begin
inputString := 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque hendrerit augue quis lacus efficitur,' +
' sollicitudin tempor sapien dapibus. Vivamus quis neque congue, imperdiet nisi nec, hendrerit nulla.' +
' Ut quis dolor eget sapien sodales faucibus vel at turpis. Aenean sed varius arcu.';
lPasswordBytes := convertSB('01234567890123456789012345678901');
InStr := TMemoryStream.Create;
OutStr := TMemoryStream.Create;
InputStringStream := TStringStream.Create(inputString, TEncoding.Unicode);
try
// -------------------------------------------------------------------------
// TEST 1 - use direct AESstreamCrypt and AESstreamDecrypt functions
InStr.Clear;
OutStr.Clear;
InStr.CopyFrom(InputStringStream, 0);
InStr.Position := 0;
// crypt
AESstreamCrypt(TAESCBC, InStr, OutStr, lPasswordBytes);
//decrypt
InStr.Clear;
AESstreamDecrypt(TAESCBC, OutStr, InStr, lPasswordBytes);
decodedString := 'empty';
decodedString := Copy(PChar(InStr.Memory), 1, Length(inputString));
Assert(decodedString = inputString);
// TEST 1 PASSED
// -------------------------------------------------------------------------
// TEST 2 with wrappers streamCryptWrapper and streamDecryptWrapper
InStr.Clear;
OutStr.Clear;
InStr.CopyFrom(InputStringStream, 0);
InStr.Position := 0;
// crypt
streamCryptWrapper(InStr, OutStr, lPasswordBytes);
InStr.Clear;
// decrypt
streamDecryptWrapper(OutStr, InStr, lPasswordBytes); // <--- ESynCrypto exception: TAESCBC.DecryptPKCS7: Invalid content
decodedString := 'pustka';
InStr.Position := 0;
decodedString := Copy(PChar(InStr.Memory), 1, Length(inputString));
Assert(decodedString = inputString);
finally
InStr.Free;
OutStr.Free;
InputStringStream.Free;
end;
end;
begin
try
SelfTest;
except
on E: ESynCrypto do
Writeln('ESynCrypto: ', E.Message);
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.And nothing? Nobody helps me out? Please check my code :-(
Please see example code (simple console project, please copy and save as Project2.dpr and run):
program Project2;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Classes,
SynCrypto;
function convertSB (const arg: AnsiString): TBytes;
var
i: integer;
begin
Setlength(Result, Length(arg));
for i := 0 to length(arg) - 1 do
begin
result[i] := ord (arg [i + 1]);
end;
end;
function EASstreamCrypt(aEASClass: TAESAbstractClass; const aInStream, aOutStream: TStream; const aPassword: TBytes): Integer;
var
aKeySize: Integer;
lAES : TAESAbstract;
lBytesIn : TBytes;
lBytesOut : TBytes;
begin
aKeySize := Length(aPassword) shl 3;
Assert((aKeySize = 128) or (aKeySize = 192) or (aKeySize = 256));
lAES := aEASClass.Create(aPassword, aKeySize);
try
SetLength(lBytesIn, aInStream.Size);
aInStream.Position := 0;
aInStream.ReadBuffer(lBytesIn[0], aInStream.Size);
lBytesOut := lAES.EncryptPKCS7(lBytesIn, True);
Result := Length(lBytesOut);
aOutStream.Write(lBytesOut[0], Length(lBytesOut));
finally
lAES.Free;
end;
end;
function EASstreamDecrypt(aEASClass: TAESAbstractClass; aInStream, aOutStream: TStream; const aPassword: TBytes):
Integer;
var
aKeySize: Integer;
lAES : TAESAbstract;
lBytesIn : TBytes;
lBytesOut : TBytes;
begin
aKeySize := Length(aPassword) shl 3;
Assert((aKeySize = 128) or (aKeySize = 192) or (aKeySize = 256));
lAES := aEASClass.Create(aPassword, aKeySize);
try
SetLength(lBytesIn, aInStream.Size);
aInStream.Position := 0;
aInStream.ReadBuffer(lBytesIn[0], aInStream.Size);
lBytesOut := lAES.DecryptPKCS7(lBytesIn, True);
Result := Length(lBytesOut);
aOutStream.Write(lBytesOut[0], Length(lBytesOut));
finally
lAES.Free;
end;
end;
procedure streamCryptWrapper(const aInStream, aOutStream: TStream; const aPassword: TBytes);
begin
EASstreamCrypt(TAESCBC, aInStream, aOutStream, aPassword);
end;
procedure streamDecryptWrapper(const aInStream, aOutStream: TStream; const aPassword: TBytes);
begin
EASstreamDecrypt(TAESCBC, aInStream, aOutStream, aPassword);
end;
procedure SelfTest;
var
decodedString: String;
inputString: string;
InStr, OutStr : TMemoryStream;
InputStringStream : TStringStream;
lInStrStream, lOutStrStream : TStringStream;
lPasswordBytes: TBytes;
begin
inputString := 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque hendrerit augue quis lacus efficitur,' +
' sollicitudin tempor sapien dapibus. Vivamus quis neque congue, imperdiet nisi nec, hendrerit nulla.' +
' Ut quis dolor eget sapien sodales faucibus vel at turpis. Aenean sed varius arcu.';
lPasswordBytes := convertSB('01234567890123456789012345678901');
InStr := TMemoryStream.Create;
OutStr := TMemoryStream.Create;
InputStringStream := TStringStream.Create(inputString, TEncoding.Unicode);
try
// -------------------------------------------------------------------------
// TEST 1
InStr.Clear;
OutStr.Clear;
InStr.CopyFrom(InputStringStream, 0);
InStr.Position := 0;
// crypt
EASstreamCrypt(TAESCBC, InStr, OutStr, lPasswordBytes);
//decrypt
InStr.Clear;
EASstreamDecrypt(TAESCBC, OutStr, InStr, lPasswordBytes);
decodedString := 'empty';
decodedString := Copy(PChar(InStr.Memory), 1, Length(inputString));
Assert(decodedString = inputString);
// TEST 1 PASSED
// -------------------------------------------------------------------------
// TEST 2 with simple wrapper
InStr.Clear;
OutStr.Clear;
InStr.CopyFrom(InputStringStream, 0);
InStr.Position := 0;
// crypt
streamCryptWrapper(InStr, OutStr, lPasswordBytes);
InStr.Clear;
// decrypt
streamDecryptWrapper(OutStr, InStr, lPasswordBytes); // <--- ESynCrypto exception: TAESCBC.DecryptPKCS7: Invalid content
decodedString := 'pustka';
InStr.Position := 0;
decodedString := Copy(PChar(InStr.Memory), 1, Length(inputString));
Assert(decodedString = inputString);
finally
InStr.Free;
OutStr.Free;
InputStringStream.Free;
end;
end;
begin
try
SelfTest;
except
on E: ESynCrypto do
Writeln('ESynCrypto: ', E.Message);
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.This line raise exception:
streamDecryptWrapper(OutStr, InStr, lPasswordBytes); // <--- ESynCrypto exception: TAESCBC.DecryptPKCS7: Invalid contentThe code performs two tests, the first test is done by directly calling functions:
EASstreamCrypt / EASstreamDecrypt
a second test calls a very simple wrappers:
streamCryptWrapper / streamDecryptWrapper
procedure streamCryptWrapper(const aInStream, aOutStream: TStream; const aPassword: TBytes);
begin
EASstreamCrypt(TAESCBC, aInStream, aOutStream, aPassword);
end;...and I get exception, but I don't understand why ![]()
I was looking for a problem a few hours, please help me. Thanks.
How check that port is already in use when creating a server TSQLHttpServer (http.sys)?
Thanks again :-)
But... I well understand?
You're suggesting that I should use method AddInterceptor() RATHER than events OnBeforeURI and OnAfterURI? Because it looks that these solutions are interchangeable. That you mean?
I ask, because variety of solutions now surprised me :-)
best regards
Thx for information.
I don't want to use hardcoded magic value, because it is dangerous (length SERVICE_PSEUDO_METHOD can change).
Can you add public function or class method:
function ServicePseudoMethodCount : Integer;
begin
result := Length(SERVICE_PSEUDO_METHOD);
end;And I refresh my previous question:
How to get the value of any parameter?
I tried various tricks, but without effect ![]()
Oh my god ... this is deeply buried :-)
It's OK? :
sm := Ctxt.Service.InterfaceFactory.Methods[Ctxt.ServiceMethodIndex];And how to get the value of any parameter?
I don't understand :-(
ServiceMethodIndex points to some array/list of methods? Where is this array/list?
Why ServiceParameters is nil in OnBeforeURI()?

Invoked method has 3 parameters.
Thanks for fast fix.
But, I still have one small problem. You wrote in the documentation:
/// event trigerred when URI() starts to process a request
// - the supplied Ctxt parameter would give access to the command about to
// be executed, e.g. Ctxt.Command=execSOAByInterface would identify a SOA
// service execution, with the corresponding Service and ServiceMethodIndex
// parameters as set by TSQLRestServerURIContext.URIDecodeSOAByInterface <--- this method not exist in class
// - should return TRUE if the method can be executed
// - should return FALSE if the method should not be executed, and set the
// corresponding error to the supplied context e.g.
// ! Ctxt.Error('Unauthorized method',HTML_NOTALLOWED);
// - since this callback would be executed during all TSQLRestServer.URI,
// it should better not make any slow process (like writing to a remote DB)
OnBeforeURI: TNotifyBeforeURI;but I can't find this method. But nevermind, my question:
How can I find out what method and what parameters is called by client?
How get it from Ctxt: TSQLRestServerURIContext?
Hello,
I'm starting to use these events and came across a minor oversight ;-)
TNotifyBeforeURI = function(Ctxt: TSQLRestServerURIContext): boolean;
TNotifyAfterURI = procedure(Ctxt: TSQLRestServerURIContext);
TNotifyErrorURI = function(Ctxt: TSQLRestServerURIContext; E: Exception): boolean;
Can you add at the end "of object"? :-)
Thx and regards
I know, but these solutions are ... unsightly, dangerous, introduce depending on the source code order - this is not good.
I did alias on type PTypeInfo and I use that alias. Tough luck, let it be :-)
PTypeInfo is defined in System.TypInfo.pas - and we return to the starting point :-)
Ok, that was a bad example, I think about something like this:
var p : PTypeInfo;
...
g := GetTypeData(p).Guid;But using mORMot RTTI creates a new problems. In other place of my code I use a System.Rtti.pas. Using it forces me to use native type PTypeInfo.
I must unfortunately abandon the use of incompatible PTypeInfo from mORMot and do some workaround ![]()
For example, how to replace this code?
g := GetTypeData(TypeInfo(IMyInterface)).Guid;This unfortunately does not solve the problem, because mORMot.pas does not have the PTypeData type (and additional functions like GetTypeData()), which forces me to use TypInfo - so the problem returns ![]()
SynCommons.PTypeInfo is in implementation section of unit, private.
Hi,
Unit mORMot.pas has a defined type PTypeInfo. It is incompatible with the Delphi native type PTypeInfo. For this reason I have often errors when compiling my own code where I use both mORMot.pas and TypInfo.pas units.
Is it possible to change the name of this type in mORMot, for example to PMTypeInfo?
kind regards
Big thanks Arnaud! :-)
Yes, I check OnMethodExecute, but it's not enough.
I need:
- perform the measurement of the execution time of my methods and monitor the load of threads
- at the end of execute each service method I need to call a procedure notifying about who called the method (this procedure creates a data packet and puts it into the processing queue - it is kind of billing)
The service method interceptor would be ideal solution. And I know that you could do it quite easily ;-)
I do not use mORMot tables, an entire layer of DB I'm doing in my own code.
I would just access to BeforeExecute and AfterExecute events for the called service method.
Hi,
I wanted to use Spring4D to use "virtual methods interceptor" (Nick Hodges presents it here https://www.youtube.com/watch?v=bjVKtac6bAY).
However, it failed, mORMot rejected my interface as incompatible with class (TInterfaceProxy from Spring4D, he is right).
Question:
Is there a way to intercept each method invocation (in interface based service) before and after the execution (on server side)?
But in my test environment with ScaleMM I get 3200 req/s and with FastMM only 2700 req/s. Difference is large.
RAM occupancy does not bother me, I care about performance.
Are there any other good memory managers?
Hi all,
What memory manager do you use in production servers that are to be heavily loaded on multiple threads?
FastMM is the bottleneck, ScaleMM is unstable (AV) SapMM is also unstable.
Are there other options worth considering?
However, the problem was in my code. But it was not a memory leak, but the uncontrolled growth of data structures.
Now all is good.
Sorry for confusion.
best regards
I access to Firebird by FireDAC. I use Delphi 10 Seattle.
I made simple app that have only REST layer (like in my app) and ...memory allocations not grow.
Now I search for reason in my code... but this is very uphill job.
I do not use any SynDB unit. Operations on DB are performed outside mORMot (in my code).
But for testing purpose I gave Exit instruction in first line of REST service method. Now the server receive only "empty" requests and do nothing. But memory allocation still slow grows. What could be causing this?
Hi,
I have the same problem, the server eats more and more memory. But I do not use ORM, only alone REST module. I connect several clients who perform ca 20 request per second ...and memory grows a few kilobytes on a few seconds. Without end.
It does not look good :-(
best regards
I found in sources "IgnoreException" string only once in SynBidirSock.pas:
/// low level WebSockets framing protocol
function GetFrame(out Frame: TWebSocketFrame; TimeOut: cardinal; IgnoreExceptions: boolean): boolean;
Hi,
When I configure the logger with sllException level:
with TSQLLog.Family to
begin
Level: = [sllInfo, sllWarning, sllError, sllLastError, sllExceptionOS, sllException];
end;then mORMot will capture any exceptions that appear in applications (and in threads, this is very good!) and store them in the log. Even these that are caught in a try ... except. However, sometimes very useful it would be the ability to bypass the known and expected exception types.
Did you could add to logger opportunity to register exception classes, which will skipped in the log?
with TSQLLog.Family to
begin
Level: = [sllInfo, sllWarning, sllError, sllLastError, sllExceptionOS, sllException];
RegisterExpectedException(EMyException);
RegisterExpectedException(EMyOtherException);
end;Thanks :-)
When I register the service with a method that contains a parameter of type UInt16 (Word):
procedure RemoveValue(const aAPIKey: RawUTF8; aIdValue: UInt16);I get the error:
"TInterfaceFactoryRTTI.Create:
IAdministrationService.RemoveValue "aIdValue" parameter has unexpected type Word - use integer / cardinal instead "Why I can not use a type of 16-bit?
--
kind regards