- Recompilación en Delphi10 de todos los paquetes de RO para generar las DCU's en Lib\D10 - Recompilación en Delphi10 de todos los paquetes de DA para generar las DCU's en Lib\D10 git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.RemObjects@9 b6239004-a887-0f4b-9937-50029ccdca16
587 lines
18 KiB
ObjectPascal
587 lines
18 KiB
ObjectPascal
unit uROBaseSuperHttpChannel;
|
|
|
|
{----------------------------------------------------------------------------}
|
|
{ RemObjects SDK Library - Core Components }
|
|
{ }
|
|
{ compiler: Delphi 5 and up, Kylix 2 and up }
|
|
{ platform: Win32, Linux }
|
|
{ }
|
|
{ (c)opyright RemObjects Software. all rights reserved. }
|
|
{ }
|
|
{ Using this code requires a valid license of the RemObjects SDK }
|
|
{ which can be obtained at http://www.remobjects.com. }
|
|
{----------------------------------------------------------------------------}
|
|
|
|
{$I RemObjects.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF REMOBJECTS_TRIAL}uROTrial,{$ENDIF}
|
|
Classes, SysUtils, uROClient, uROClientIntf, uROAsync, uROClasses, SyncObjs,
|
|
{$IFDEF RemObjects_UseEncryption} uRoEncryption, {$ENDIF}uROThreadPool;
|
|
|
|
type
|
|
TDynByteArray = array of byte;
|
|
TROHttpWaitingRequest = class
|
|
private
|
|
fEvent: TROEvent;
|
|
fFreeEvent: Boolean;
|
|
fId: Integer;
|
|
fResultData: TDynByteArray;
|
|
fResultErrorCode: Integer;
|
|
public
|
|
property Id: Integer read fId;
|
|
property Event: TROEvent read fEvent;
|
|
property Resultdata: TDynByteArray read fResultData write fResultData;
|
|
property ResultErrorCode: Integer read fResultErrorCode write fResultErrorCode;
|
|
|
|
constructor Create(Id: Integer); overload;
|
|
constructor Create(Id: Integer; Ev: TROEvent); overload;
|
|
destructor Destroy; override;
|
|
end;
|
|
EROSuperHttpChannelException = class(EROException);
|
|
TROBaseSuperHttpChannel = class(TROTransportChannel, IROTransport,
|
|
IROActiveEventChannel, IROMultiThreadAwareChannel,
|
|
IROAsyncTransportChannel, IROActiveAsyncTransportChannel, IROTransportChannelEx)
|
|
private
|
|
fConnectWait: TROEvent;
|
|
fActive, fConnected: Boolean;
|
|
fSessionId, fConnectionId: TGuid;
|
|
fRemoteMaxPackageSize,
|
|
fMaxPackageSize: Integer;
|
|
fWaitingRequest: TThreadList;
|
|
fPackageCounter: Integer;
|
|
fOwnsThreadPool: Boolean;
|
|
fEventThreadPool: TROThreadPool;
|
|
fDispatchLock: TCriticalSection;
|
|
fWaitingThread: TThread;
|
|
fEventReceiver: IROEventReceiver;
|
|
fRequestTimeout: Integer;
|
|
fConnectTimeout: Integer;
|
|
fHttpRequestTimeout: Integer;
|
|
procedure SetActive(const Value: Boolean);
|
|
procedure ProcessEvent(aId: Integer; aData: TDynByteArray);
|
|
procedure SetEventThreadPool(const Value: TROThreadPool);
|
|
protected
|
|
procedure IntDispatch(aRequest: TStream; aResponse: TStream); override;
|
|
procedure IntSetServerLocator(aServerLocator: TROServerLocator); override;
|
|
function CheckStatus(const iMessageID: String): Boolean;
|
|
procedure RetrieveResponse(const iMessageID: String;
|
|
aResponse: TStream);
|
|
procedure BeforeDispatch(aMessage: IROMessage); override;
|
|
procedure RegisterEventReceiver(aReceiver: IROEventReceiver);
|
|
procedure UnregisterEventReceiver(aReceiver: IROEventReceiver);
|
|
function InvokeRequest(aRequest:TStream; iGetResponse:boolean=true):string; overload;
|
|
function InvokeRequest(aRequest:TStream; aGetResponse:boolean=true; aEvent: TROEvent=nil):string; overload;
|
|
|
|
procedure CancelRequest(aWaitingThread: Boolean); virtual; abstract;
|
|
procedure DispatchHttpRequest(aWaitingThread: Boolean; aRequest: TDynByteArray; out aResponse: TDynByteArray); virtual; abstract;
|
|
|
|
public
|
|
constructor Create(aOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
|
|
property EventThreadPool :TROThreadPool read fEventThreadPool write SetEventThreadPool;
|
|
property ConnectionId: TGUID read fConnectionId write fConnectionId;
|
|
property SessionId: TGuid read fSessionId write fSessionId;
|
|
property Connected: Boolean read fConnected;
|
|
property Active: Boolean read fActive write SetActive;
|
|
property MaxPackageSize: Integer read fMaxPackageSize write fMaxPackageSize default 1024 * 1024;
|
|
property RequestTimeout: Integer read fRequestTimeout write fRequestTimeout default 60000;
|
|
property ConnectTimeout: Integer read fConnectTimeout write fConnectTimeout default 10000;
|
|
property HttpRequestTimeout: Integer read fHttpRequestTimeout write fHttpRequestTimeout default 10000;
|
|
end;
|
|
const
|
|
ShHello = 0;
|
|
ShGoodbye = 1;
|
|
ShPackage = 2;
|
|
ShError = 3;
|
|
ShError_InvalidClientId = 0;
|
|
ShError_QueueFull = 1;
|
|
ShError_UnknownOption = 2;
|
|
ShOptions = 4;
|
|
ShAsyncWait = 5;
|
|
implementation
|
|
|
|
uses Math;
|
|
|
|
type
|
|
TROSuperHttpThread = class(TThread)
|
|
private
|
|
fOwner: TROBaseSuperHttpChannel;
|
|
public
|
|
constructor Create(aOwner: TROBaseSuperHttpChannel);
|
|
procedure Execute; override;
|
|
end;
|
|
|
|
{ TROHttpWaitingRequest }
|
|
|
|
constructor TROHttpWaitingRequest.Create(Id: Integer);
|
|
begin
|
|
fId := Id;
|
|
fEvent := TROEvent.Create(nil, true, false, '');
|
|
fFreeEvent := true;
|
|
end;
|
|
|
|
constructor TROHttpWaitingRequest.Create(Id: Integer; Ev: TROEvent);
|
|
begin
|
|
fEvent := Ev;
|
|
if Fevent = nil then begin
|
|
fEvent := TROEvent.Create(nil, true, false, '');
|
|
fFreeEvent := true;
|
|
end;
|
|
fId := Id;
|
|
end;
|
|
|
|
destructor TROHttpWaitingRequest.Destroy;
|
|
begin
|
|
if fFreeEvent then fEvent.Free;
|
|
inherited;
|
|
end;
|
|
|
|
{ TROBaseSuperHttpChannel }
|
|
|
|
procedure TROBaseSuperHttpChannel.BeforeDispatch(aMessage: IROMessage);
|
|
begin
|
|
if not fConnected then begin
|
|
Active := true;
|
|
if (fConnectWait.WaitFor(fConnectTimeout) <> wrSignaled) or not fConnected then
|
|
raise EROSuperHttpChannelException.Create('Timeout connecting');
|
|
end;
|
|
aMessage.ClientID := fSessionId;
|
|
inherited;
|
|
end;
|
|
|
|
constructor TROBaseSuperHttpChannel.Create(aOwner: TComponent);
|
|
begin
|
|
inherited Create(aOwner);
|
|
fMaxPackageSize := 1 * 1024 * 1024;
|
|
fRequestTimeout := 60000;
|
|
fConnectTimeout := 10000;
|
|
fHttpRequestTimeout := 10000;
|
|
fConnectWait := TROEvent.Create(nil, true, false, '');
|
|
fWaitingRequest := TThreadList.Create;
|
|
ThreadSafe := true;
|
|
fDispatchLock := TCriticalSection.Create;
|
|
end;
|
|
|
|
destructor TROBaseSuperHttpChannel.Destroy;
|
|
var
|
|
i: Integer;
|
|
lList: TList;
|
|
begin
|
|
if fOwnsThreadPool then fEventThreadPool.Free;
|
|
Active := False;
|
|
fConnectWait.Free;
|
|
lList := fWaitingRequest.LockList;
|
|
try
|
|
for i := 0 to lList.Count -1 do begin
|
|
TROHttpWaitingRequest(lList[i]).Free;
|
|
end;
|
|
finally
|
|
fWaitingRequest.UnlockList;
|
|
end;
|
|
fWaitingRequest.Free;
|
|
fDispatchLock.Free;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TROBaseSuperHttpChannel.IntDispatch(aRequest,
|
|
aResponse: TStream);
|
|
var
|
|
lRequest, lResponse: TDynByteArray;
|
|
lList:TList;
|
|
lId: Integer;
|
|
lReq: TROHttpWaitingRequest;
|
|
begin
|
|
if aRequest.Size > fRemoteMaxPackageSize then raise EROSuperHttpChannelException.Create('Package too large');
|
|
SetLength(lRequest, 16 + 1 + 4 + aRequest.Size);
|
|
aRequest.Position := 0;
|
|
|
|
Move(fConnectionId, lRequest[0], 16);
|
|
lRequest[16] := ShPackage;
|
|
aRequest.Read(lRequest[21], aRequest.Size);
|
|
lList := fWaitingRequest.LockList;
|
|
try
|
|
inc(fPackageCounter);
|
|
if fPackageCounter < 0 then fPackageCounter := 1;
|
|
lId := fPackageCounter;
|
|
lReq := TROHttpWaitingRequest.Create(lId);
|
|
lList.Add(lReq);
|
|
finally
|
|
fWaitingRequest.UnlockList;
|
|
end;
|
|
try
|
|
lRequest[17] := lId;
|
|
lRequest[18] := lId shr 8;
|
|
lRequest[19] := lId shr 16;
|
|
lRequest[20] := lId shr 24;
|
|
fDispatchLock.Enter;
|
|
try
|
|
DispatchHttpRequest(false, lRequest, lResponse);
|
|
if Length(lResponse) >= 6 then begin
|
|
if lResponse[0] = shError then begin
|
|
case lResponse[5] of
|
|
ShError_InvalidClientId: raise EROSuperHttpChannelException.Create('Invalid client id');
|
|
ShError_QueueFull: raise EROSuperHttpChannelException.Create('Queue full');
|
|
else
|
|
raise EROSuperHttpChannelException.Create('Unknown error');
|
|
end;
|
|
end;
|
|
end;
|
|
finally
|
|
fDispatchLock.Release;
|
|
end;
|
|
if lReq.Event.WaitFor(fRequestTimeout) <> wrSignaled then
|
|
raise EROSuperHttpChannelException.Create('Timeout');
|
|
|
|
if Length(lReq.fResultData) <> 0 then begin
|
|
aResponse.Write(lReq.fResultData[0], length(lReq.fResultData))
|
|
end else begin
|
|
case lReq.fResultErrorCode of
|
|
ShError_InvalidClientId: raise EROSuperHttpChannelException.Create('Invalid client id');
|
|
ShError_QueueFull: raise EROSuperHttpChannelException.Create('Queue full');
|
|
else
|
|
raise EROSuperHttpChannelException.Create('Unknown error');
|
|
end;
|
|
end;
|
|
finally
|
|
lList := fWaitingRequest.LockList;
|
|
lList.Remove(lReq);
|
|
fWaitingRequest.UnlockList;
|
|
lReq.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TROBaseSuperHttpChannel.IntSetServerLocator(
|
|
aServerLocator: TROServerLocator);
|
|
begin
|
|
|
|
end;
|
|
|
|
procedure TROBaseSuperHttpChannel.SetActive(const Value: Boolean);
|
|
begin
|
|
if fActive = Value then exit;
|
|
fActive := Value;
|
|
if fActive then begin
|
|
fConnectWait.ResetEvent;
|
|
if fWaitingThread <> nil then fWaitingThread.Free;
|
|
fWaitingThread := TROSuperHttpThread.Create(self);
|
|
end else begin
|
|
fWaitingThread.Terminate;
|
|
CancelRequest(true);
|
|
fWaitingThread.Free;
|
|
fwaitingThread := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure TROBaseSuperHttpChannel.SetEventThreadPool(
|
|
const Value: TROThreadPool);
|
|
begin
|
|
if fOwnsThreadPool and (fEventThreadPool <> nil) then fEventThreadPool.Free;
|
|
fEventThreadPool := Value;
|
|
fOwnsThreadPool := false;
|
|
end;
|
|
|
|
procedure TROBaseSuperHttpChannel.RegisterEventReceiver(
|
|
aReceiver: IROEventReceiver);
|
|
begin
|
|
fEventReceiver := aReceiver;
|
|
end;
|
|
|
|
procedure TROBaseSuperHttpChannel.UnregisterEventReceiver(
|
|
aReceiver: IROEventReceiver);
|
|
begin
|
|
if fEventReceiver = aReceiver then fEventReceiver := nil;
|
|
end;
|
|
|
|
|
|
function FindWaitingRequest(aList: TList; aId: Integer): TROHttpWaitingRequest;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := aList.count -1 downto 0 do begin
|
|
result := TROHttpWaitingRequest(aList[i]);
|
|
if result.fId = aId then exit;
|
|
end;
|
|
result := nil;
|
|
end;
|
|
|
|
function TROBaseSuperHttpChannel.CheckStatus(
|
|
const iMessageID: String): Boolean;
|
|
var
|
|
lList: TList;
|
|
wr: TROHttpWaitingRequest;
|
|
begin
|
|
lList := fWaitingRequest.LockList;
|
|
try
|
|
wr := FindWaitingRequest(lList, StrToInt(iMessageId));
|
|
if wr = nil then
|
|
result := true
|
|
else
|
|
result := (Length(wr.Resultdata) <> 0) or (wr.ResultErrorCode <> 0);
|
|
finally
|
|
fWaitingRequest.UnlockList;
|
|
end;
|
|
end;
|
|
|
|
procedure TROBaseSuperHttpChannel.RetrieveResponse(
|
|
const iMessageID: String; aResponse: TStream);
|
|
var
|
|
lList: TList;
|
|
wr: TROHttpWaitingRequest;
|
|
begin
|
|
lList := fWaitingRequest.LockList;
|
|
try
|
|
wr := FindWaitingRequest(lList, StrToInt(iMessageId));
|
|
finally
|
|
fWaitingRequest.UnlockList;
|
|
end;
|
|
if wr = nil then raise EROSuperHttpChannelException.Create('Invalid request id');
|
|
try
|
|
if wr.fEvent.WaitFor(fRequestTimeout) <> wrSignaled then raise EROSuperHttpChannelException.Create('Timeout');
|
|
if Length(wr.fResultData) > 0 then begin
|
|
aResponse.Write(wr.fresultData[0], Length(wr.fresultData));
|
|
aResponse.Position := 0;
|
|
end else begin
|
|
case wr.fResultErrorCode of
|
|
ShError_InvalidClientId: raise EROSuperHttpChannelException.Create('Invalid client id');
|
|
ShError_QueueFull: raise EROSuperHttpChannelException.Create('Queue full');
|
|
else
|
|
raise EROSuperHttpChannelException.Create('Unknown error');
|
|
end;
|
|
end;
|
|
finally
|
|
lList := fWaitingRequest.LockList;
|
|
try
|
|
lList.Remove(wr);
|
|
wr.Free;
|
|
finally
|
|
fWaitingRequest.UnlockList;
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
|
|
function TROBaseSuperHttpChannel.InvokeRequest(aRequest: TStream;
|
|
iGetResponse: boolean): string;
|
|
begin
|
|
result := InvokeRequest(aRequest, iGetResponse, nil);
|
|
end;
|
|
|
|
function TROBaseSuperHttpChannel.InvokeRequest(aRequest: TStream;
|
|
aGetResponse: boolean; aEvent: TROEvent): string;
|
|
var
|
|
lRequest, lResponse: TDynByteArray;
|
|
lList:TList;
|
|
lId: Integer;
|
|
lReq: TROHttpWaitingRequest;
|
|
begin
|
|
if aRequest.Size > fRemoteMaxPackageSize then raise EROSuperHttpChannelException.Create('Package too large');
|
|
SetLength(lRequest, 16 + 1 + 4 + aRequest.Size);
|
|
aRequest.Position := 0;
|
|
|
|
Move(fConnectionId, lRequest[0], 16);
|
|
lRequest[16] := ShPackage;
|
|
aRequest.Read(lRequest[21], aRequest.Size);
|
|
lList := fWaitingRequest.LockList;
|
|
try
|
|
inc(fPackageCounter);
|
|
if fPackageCounter < 0 then fPackageCounter := 1;
|
|
lId := fPackageCounter;
|
|
if aGetResponse then begin
|
|
lReq := TROHttpWaitingRequest.Create(lId);
|
|
lList.Add(lReq);
|
|
end else
|
|
lReq := nil;
|
|
finally
|
|
fWaitingRequest.UnlockList;
|
|
end;
|
|
try
|
|
lRequest[17] := lId;
|
|
lRequest[18] := lId shr 8;
|
|
lRequest[19] := lId shr 16;
|
|
lRequest[20] := lId shr 24;
|
|
fDispatchLock.Enter;
|
|
try
|
|
DispatchHttpRequest(false, lRequest, lResponse);
|
|
if Length(lResponse) >= 6 then begin
|
|
if lResponse[0] = shError then begin
|
|
case lResponse[5] of
|
|
ShError_InvalidClientId: raise EROSuperHttpChannelException.Create('Invalid client id');
|
|
ShError_QueueFull: raise EROSuperHttpChannelException.Create('Queue full');
|
|
else
|
|
raise EROSuperHttpChannelException.Create('Unknown error');
|
|
end;
|
|
end;
|
|
end;
|
|
finally
|
|
fDispatchLock.Release;
|
|
end;
|
|
result := inttostr(lId);
|
|
except
|
|
lList := fWaitingRequest.LockList;
|
|
lList.Remove(lReq);
|
|
fWaitingRequest.UnlockList;
|
|
lReq.Free;
|
|
raise;
|
|
end;
|
|
end;
|
|
|
|
type
|
|
TROSuperEventCallback = class(TInterfacedObject, IROThreadPoolCallback)
|
|
private
|
|
fData: TDynByteArray;
|
|
fOwner: TROBaseSuperHttpChannel;
|
|
public
|
|
procedure Callback(Caller: TROThreadPool; aThread: TThread);
|
|
end;
|
|
|
|
procedure TROBaseSuperHttpChannel.ProcessEvent(aId: Integer;
|
|
aData: TDynByteArray);
|
|
var
|
|
lCb: TROSuperEventCallback;
|
|
begin
|
|
lCb := TROSuperEventCallback.Create;
|
|
lCb.fOwner := self;
|
|
lCb.fData := aData;
|
|
fEventThreadPool.QueueItem(lCb);
|
|
end;
|
|
|
|
{ TROSuperHttpThread }
|
|
|
|
constructor TROSuperHttpThread.Create(aOwner: TROBaseSuperHttpChannel);
|
|
begin
|
|
inherited Create(true);
|
|
fOwner := aOwner;
|
|
Resume;
|
|
end;
|
|
|
|
procedure TROSuperHttpThread.Execute;
|
|
var
|
|
lRequest,
|
|
lTmpData,
|
|
lResponse: TDynByteArray;
|
|
lList: TList;
|
|
lPackageId: Integer;
|
|
wr: TROHttpWaitingRequest;
|
|
begin
|
|
try
|
|
if IsEqualGuid(fOwner.fConnectionId, Emptyguid) then fOwner.fConnectionId := NewGuid;
|
|
SetLength(lRequest, 16 + 1 +8 + 4 + 16);
|
|
Move(fOwner.fConnectionId, lRequest[0], 16);
|
|
lRequest[16] := shHello;
|
|
lRequest[17] := ord('R');
|
|
lRequest[18] := ord('O');
|
|
lRequest[19] := ord('S');
|
|
lRequest[20] := ord('H');
|
|
lRequest[21] := ord('1');
|
|
lRequest[22] := ord('0');
|
|
lRequest[23] := ord('0');
|
|
lRequest[24] := ord('0');
|
|
lRequest[25] := fOwner.fMaxPackageSize;
|
|
lRequest[26] := fOwner.fMaxPackageSize shr 8;
|
|
lRequest[27] := fOwner.fMaxPackageSize shr 16;
|
|
lRequest[28] := fOwner.fMaxPackageSize shr 16;
|
|
Move(fOwner.fSessionId, lRequest[29], 16);
|
|
fOwner.fDispatchLock.Enter;
|
|
try
|
|
fOwner.DispatchHttpRequest(false, lRequest, lResponse);
|
|
finally
|
|
fOwner.fDispatchLock.Leave;
|
|
end;
|
|
if Length(lResponse) <> (16 + 8 + 4) then
|
|
raise EROSuperHttpChannelException.Create('Invalid response from server for connection initiation command');
|
|
|
|
if (lResponse[0] <> ord('R')) or (lResponse[1] <> ord('O')) or (lResponse[2] <> ord('S')) or (lResponse[3] <> ord('H')) then
|
|
raise EROSuperHttpChannelException.Create('Invalid response from server for connection initiation command');
|
|
fOwner.fRemoteMaxPackageSize := Integer(lResponse[8]) or (Integer(lResponse[9]) shl 8)
|
|
or (Integer(lResponse[10]) shl 16) or (Integer(lResponse[11]) shl 24);
|
|
move(lResponse[12], fOwner.fSessionId, 16);
|
|
fOwner.fConnected := true;
|
|
fOwner.fConnectWait.SetEvent;
|
|
SetLength(lRequest, 17);
|
|
move(fOwner.fConnectionId, lRequest[0], 16);
|
|
lRequest[16] := ShAsyncWait;
|
|
while not Terminated do begin
|
|
try
|
|
fOwner.DispatchHttpRequest(true, lRequest, lResponse);
|
|
except
|
|
continue;
|
|
end;
|
|
if Length(lResponse) <> 0 then begin
|
|
case lResponse[0] of
|
|
ShError: begin
|
|
if Length(lResponse) < 5 then continue;
|
|
lPackageId := Integer(lResponse[1]) or (Integer(lResponse[2]) shl 8)
|
|
or (Integer(lResponse[3]) shl 16) or (Integer(lResponse[4]) shl 24);
|
|
lList := fOwner.fWaitingRequest.LockList;
|
|
try
|
|
wr := FindWaitingRequest(lList, lPackageId);
|
|
if wr <> nil then begin
|
|
wr.fResultErrorCode := lResponse[4];
|
|
wr.fEvent.SetEvent;
|
|
end;
|
|
finally
|
|
fOwner.fWaitingRequest.UnlockList;
|
|
end;
|
|
end;
|
|
shPackage: begin
|
|
if Length(lResponse) < 5 then continue;
|
|
lPackageId := Integer(lResponse[1]) or (Integer(lResponse[2]) shl 8)
|
|
or (Integer(lResponse[3]) shl 16) or (Integer(lResponse[4]) shl 24);
|
|
setLength(lTmpData, Length(lResponse) -5);
|
|
Move(lResponse[5], lTmpData[0], Length(lTmpData));
|
|
if lPackageId < 0 then
|
|
fOwner.ProcessEvent(lPackageId, lTmpData)
|
|
else begin
|
|
lList := fOwner.fWaitingRequest.LockList;
|
|
try
|
|
wr := FindWaitingRequest(lList, lPackageId);
|
|
if wr <> nil then begin
|
|
wr.fResultData := lTmpData;
|
|
wr.fEvent.SetEvent;
|
|
end;
|
|
finally
|
|
fOwner.fWaitingRequest.UnlockList;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
lRequest[16] := shGoodbye;
|
|
fOwner.fDispatchLock.Enter;
|
|
try
|
|
fOwner.DispatchHttpRequest(false, lRequest, lResponse);
|
|
finally
|
|
fOwner.fDispatchLock.Leave;
|
|
end;
|
|
except
|
|
// cannot let exceptions escape here
|
|
end;
|
|
end;
|
|
|
|
{ TROSuperEventCallback }
|
|
|
|
procedure TROSuperEventCallback.Callback(Caller: TROThreadPool;
|
|
aThread: TThread);
|
|
var
|
|
lData: TMemoryStream;
|
|
begin
|
|
if fOwner.fEventReceiver <> nil then begin
|
|
lData := TMemoryStream.Create;
|
|
try
|
|
lData.Write(fData[0], length(fData));
|
|
lData.Position := 0;
|
|
fOwner.fEventReceiver.Dispatch(lData, aThread);
|
|
finally
|
|
lData.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|