local sync

This commit is contained in:
André Mussche 2014-01-02 14:59:48 +01:00
parent 86dc2bfc35
commit 7a59f2b272
3 changed files with 335 additions and 318 deletions

View file

@ -246,7 +246,7 @@ begin
if ARaiseExceptionOnTimeout then if ARaiseExceptionOnTimeout then
EIdReadTimeout.Toss(RSIdNoDataToRead) //exit, no data can be received EIdReadTimeout.Toss(RSIdNoDataToRead) //exit, no data can be received
else else
Exit; Exit(0);
end; end;
SetLength(VBuffer, RecvBufferSize); SetLength(VBuffer, RecvBufferSize);

View file

@ -584,6 +584,8 @@ var
errorref: TSocketIOError; errorref: TSocketIOError;
error: ISuperObject; error: ISuperObject;
begin begin
if ASocket = nil then Exit;
if not FConnections.ContainsValue(ASocket) and if not FConnections.ContainsValue(ASocket) and
not FConnectionsGUID.ContainsValue(ASocket) then not FConnectionsGUID.ContainsValue(ASocket) then
begin begin
@ -1258,8 +1260,6 @@ begin
for context in FConnections.Values do for context in FConnections.Values do
begin begin
if context.IsDisconnected then Continue; if context.IsDisconnected then Continue;
// if not context.IsSocketIO then
// raise EIdSocketIoUnhandledMessage.Create('Not a socket.io connection!');
if not Assigned(aCallback) then if not Assigned(aCallback) then
WriteSocketIOMsg(context, ''{no room}, aMessage, nil) WriteSocketIOMsg(context, ''{no room}, aMessage, nil)
@ -1274,8 +1274,6 @@ begin
for context in FConnectionsGUID.Values do for context in FConnectionsGUID.Values do
begin begin
if context.IsDisconnected then Continue; if context.IsDisconnected then Continue;
// if not context.IsSocketIO then
// raise EIdSocketIoUnhandledMessage.Create('Not a socket.io connection!');
if not Assigned(aCallback) then if not Assigned(aCallback) then
WriteSocketIOMsg(context, ''{no room}, aMessage, nil) WriteSocketIOMsg(context, ''{no room}, aMessage, nil)

View file

@ -1,314 +1,333 @@
unit uROHTTPWebsocketServer; unit uROHTTPWebsocketServer;
interface interface
uses uses
Classes, IdServerIOHandlerWebsocket, IdIOHandlerWebsocket, Classes, IdServerIOHandlerWebsocket, IdIOHandlerWebsocket,
uROIndyHTTPServer, uROClientIntf, uROServer, uROHTTPDispatch, uROIndyHTTPServer, uROClientIntf, uROServer, uROHTTPDispatch,
IdContext, IdCustomHTTPServer, IdCustomTCPServer, uROHash, uROServerIntf, IdContext, IdCustomHTTPServer, IdCustomTCPServer, uROHash, uROServerIntf,
IdServerWebsocketContext, IdServerSocketIOHandling, IdServerWebsocketContext, IdServerSocketIOHandling,
IdServerWebsocketHandling; IdServerWebsocketHandling;
type type
TROTransportContext = class; TROTransportContext = class;
TROIndyHTTPWebsocketServer = class(TROIndyHTTPServer) TROIndyHTTPWebsocketServer = class(TROIndyHTTPServer)
private private
FOnCustomChannelExecute: TWebsocketChannelRequest; FOnCustomChannelExecute: TWebsocketChannelRequest;
FSocketIO: TIdServerSocketIOHandling_Ext; FSocketIO: TIdServerSocketIOHandling_Ext;
function GetSocketIO: TIdServerSocketIOHandling; function GetSocketIO: TIdServerSocketIOHandling;
protected protected
procedure InternalServerConnect(AThread: TIdContext); override; FROTransportContexts: TInterfaceList;
procedure InternalServerCommandGet(AThread: TIdThreadClass; procedure InternalServerConnect(AThread: TIdContext); override;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); override; procedure InternalServerDisConnect(AThread: TIdContext); virtual;
procedure ProcessRemObjectsRequest(const AThread: TIdContext; const strmRequest: TMemoryStream; const strmResponse: TMemoryStream); procedure InternalServerCommandGet(AThread: TIdThreadClass;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); override;
function GetDispatchersClass: TROMessageDispatchersClass; override; procedure ProcessRemObjectsRequest(const AThread: TIdContext; const strmRequest: TMemoryStream; const strmResponse: TMemoryStream);
public
procedure AfterConstruction; override; function GetDispatchersClass: TROMessageDispatchersClass; override;
destructor Destroy; override; public
procedure Loaded; override; procedure AfterConstruction; override;
destructor Destroy; override;
property SocketIO: TIdServerSocketIOHandling read GetSocketIO; procedure Loaded; override;
property OnCustomChannelExecute: TWebsocketChannelRequest read FOnCustomChannelExecute write FOnCustomChannelExecute;
end; property SocketIO: TIdServerSocketIOHandling read GetSocketIO;
property OnCustomChannelExecute: TWebsocketChannelRequest read FOnCustomChannelExecute write FOnCustomChannelExecute;
TROHTTPDispatcher_Websocket = class(TROHTTPDispatcher) end;
public
function CanHandleMessage(const aTransport: IROTransport; aRequeststream : TStream): boolean; override; TROHTTPDispatcher_Websocket = class(TROHTTPDispatcher)
end; public
function CanHandleMessage(const aTransport: IROTransport; aRequeststream : TStream): boolean; override;
TROHTTPMessageDispatchers_WebSocket = class(TROHTTPMessageDispatchers) end;
protected
function GetDispatcherClass : TROMessageDispatcherClass; override; TROHTTPMessageDispatchers_WebSocket = class(TROHTTPMessageDispatchers)
end; protected
function GetDispatcherClass : TROMessageDispatcherClass; override;
TROTransportContext = class(TInterfacedObject, end;
IROTransport, IROTCPTransport,
IROActiveEventServer) TROTransportContext = class(TInterfacedObject,
private IROTransport, IROTCPTransport,
FROServer: TROIndyHTTPServer; IROActiveEventServer)
FIdContext: TIdServerWSContext; private
FEventCount: Integer; FROServer: TROIndyHTTPServer;
FClientId: TGUID; FIdContext: TIdServerWSContext;
private FEventCount: Integer;
class var FGlobalEventCount: Integer; FClientId: TGUID;
protected private
{IROTransport} class var FGlobalEventCount: Integer;
function GetTransportObject: TObject; protected
{IROTCPTransport} {IROTransport}
function GetClientAddress : string; function GetTransportObject: TObject;
{IROActiveEventServer} {IROTCPTransport}
procedure EventsRegistered(aSender : TObject; aClient: TGUID); function GetClientAddress : string;
procedure DispatchEvent(anEventDataItem : TROEventData; aSessionReference : TGUID; aSender: TObject); // asender is TROEventRepository {IROActiveEventServer}
public procedure EventsRegistered(aSender : TObject; aClient: TGUID);
//constructor Create(aROServer: TROIndyHTTPServer; aIOHandler: TIdIOHandlerWebsocket); procedure DispatchEvent(anEventDataItem : TROEventData; aSessionReference : TGUID; aSender: TObject); // asender is TROEventRepository
constructor Create(aROServer: TROIndyHTTPServer; aIdContext: TIdServerWSContext); public
//constructor Create(aROServer: TROIndyHTTPServer; aIOHandler: TIdIOHandlerWebsocket);
property Context: TIdServerWSContext read FIdContext; constructor Create(aROServer: TROIndyHTTPServer; aIdContext: TIdServerWSContext);
property ClientId: TGUID read FClientId write FClientId;
end; property Context: TIdServerWSContext read FIdContext;
property ClientId: TGUID read FClientId write FClientId;
procedure Register; end;
implementation procedure Register;
uses implementation
SysUtils, IdCoderMIME, Windows, uROEventRepository, uROSessions, uROClient,
uROClasses, StrUtils, uROIdServerWebsocketHandling; uses
SysUtils, IdCoderMIME, Windows, uROEventRepository, uROSessions, uROClient,
procedure Register; uROClasses, StrUtils, uROIdServerWebsocketHandling;
begin
RegisterComponents('RBK', [TROIndyHTTPWebsocketServer]); procedure Register;
end; begin
RegisterComponents('RBK', [TROIndyHTTPWebsocketServer]);
procedure TROIndyHTTPWebsocketServer.AfterConstruction;
begin
inherited;
FSocketIO := TIdServerSocketIOHandling_Ext.Create;
IndyServer.ContextClass := TROIdServerWSContext;
if Self.IndyServer.IOHandler = nil then
IndyServer.IOHandler := TIdServerIOHandlerWebsocket.Create(Self);
end;
destructor TROIndyHTTPWebsocketServer.Destroy;
begin
inherited;
FSocketIO.Free;
end;
function TROIndyHTTPWebsocketServer.GetDispatchersClass: TROMessageDispatchersClass;
begin
Result := TROHTTPMessageDispatchers_Websocket;
end;
function TROIndyHTTPWebsocketServer.GetSocketIO: TIdServerSocketIOHandling;
begin
Result := FSocketIO;
end;
procedure TROIndyHTTPWebsocketServer.InternalServerCommandGet(AThread: TIdThreadClass;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
(AThread as TIdServerWSContext).OnCustomChannelExecute := Self.OnCustomChannelExecute;
(AThread as TIdServerWSContext).SocketIO := Self.FSocketIO;
(AThread as TROIdServerWSContext).OnRemObjectsRequest := Self.ProcessRemObjectsRequest;
if not TROIdServerWebsocketHandling.ProcessServerCommandGet(AThread as TIdServerWSContext, ARequestInfo, AResponseInfo) then
inherited InternalServerCommandGet(AThread, ARequestInfo, AResponseInfo)
end; end;
procedure TROIndyHTTPWebsocketServer.InternalServerConnect(AThread: TIdContext); procedure TROIndyHTTPWebsocketServer.AfterConstruction;
begin begin
inherited; inherited;
(AThread as TIdServerWSContext).OnCustomChannelExecute := Self.OnCustomChannelExecute;
(AThread as TROIdServerWSContext).OnRemObjectsRequest := Self.ProcessRemObjectsRequest; FSocketIO := TIdServerSocketIOHandling_Ext.Create;
end; FROTransportContexts := TInterfaceList.Create;
procedure TROIndyHTTPWebsocketServer.Loaded; IndyServer.ContextClass := TROIdServerWSContext;
begin if Self.IndyServer.IOHandler = nil then
//do before inherited in case of designtime connection IndyServer.IOHandler := TIdServerIOHandlerWebsocket.Create(Self);
if Self.IndyServer.IOHandler = nil then IndyServer.OnDisconnect := InternalServerDisConnect;
IndyServer.IOHandler := TIdServerIOHandlerWebsocket.Create(Self); end;
inherited;
end; destructor TROIndyHTTPWebsocketServer.Destroy;
begin
procedure TROIndyHTTPWebsocketServer.ProcessRemObjectsRequest( inherited;
const AThread: TIdContext; const strmRequest: TMemoryStream; const strmResponse: TMemoryStream); FSocketIO.Free;
var FROTransportContexts.Free;
cWSNR: array[0..High(C_ROWSNR)] of AnsiChar; end;
msg: TROMessageDispatcher;
iMsgNr: Integer; function TROIndyHTTPWebsocketServer.GetDispatchersClass: TROMessageDispatchersClass;
imsg: IROMessage; begin
transport: TROTransportContext; Result := TROHTTPMessageDispatchers_Websocket;
begin end;
if strmRequest.Size < Length(C_ROWSNR) + SizeOf(iMsgNr) then Exit;
//read messagenr from the end function TROIndyHTTPWebsocketServer.GetSocketIO: TIdServerSocketIOHandling;
strmRequest.Position := strmRequest.Size - Length(C_ROWSNR) - SizeOf(iMsgNr); begin
strmRequest.Read(cWSNR[0], Length(C_ROWSNR)); Result := FSocketIO;
if (cWSNR <> C_ROWSNR) then Exit; end;
strmRequest.Read(iMsgNr, SizeOf(iMsgNr));
strmRequest.Position := 0; procedure TROIndyHTTPWebsocketServer.InternalServerCommandGet(AThread: TIdThreadClass;
//trunc extra data ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
strmRequest.Size := strmRequest.Size - Length(C_ROWSNR) - SizeOf(iMsgNr); begin
transport := AThread.Data as TROTransportContext; (AThread as TIdServerWSContext).OnCustomChannelExecute := Self.OnCustomChannelExecute;
//no RO transport object already made? (AThread as TIdServerWSContext).SocketIO := Self.FSocketIO;
if transport = nil then (AThread as TROIdServerWSContext).OnRemObjectsRequest := Self.ProcessRemObjectsRequest;
begin
//create IROTransport object if not TROIdServerWebsocketHandling.ProcessServerCommandGet(AThread as TIdServerWSContext, ARequestInfo, AResponseInfo) then
transport := TROTransportContext.Create(Self, AThread as TIdServerWSContext); inherited InternalServerCommandGet(AThread, ARequestInfo, AResponseInfo)
(transport as IROTransport)._AddRef; end;
//attach RO transport to indy context
AThread.Data := transport;
//todo: enveloppes procedure TROIndyHTTPWebsocketServer.InternalServerConnect(AThread: TIdContext);
//read client GUID the first time (needed to be able to send RO events) begin
msg := Self.Dispatchers.FindDispatcher(transport, strmRequest); inherited;
if msg = nil then (AThread as TIdServerWSContext).OnCustomChannelExecute := Self.OnCustomChannelExecute;
raise EROException.Create('No suiteable message dispatcher found!'); (AThread as TROIdServerWSContext).OnRemObjectsRequest := Self.ProcessRemObjectsRequest;
imsg := (msg.MessageIntf as IROMessageCloneable).Clone; end;
imsg.InitializeRead(transport);
imsg.ReadFromStream(strmRequest); procedure TROIndyHTTPWebsocketServer.InternalServerDisConnect(
transport.ClientId := imsg.ClientID; AThread: TIdContext);
imsg := nil; var
Assert(not IsEqualGUID(transport.ClientID, EmptyGUID)); transport: TROTransportContext;
end; begin
//EXECUTE FUNCTION transport := AThread.Data as TROTransportContext;
Self.DispatchMessage(transport, strmRequest, strmResponse); if transport <> nil then
//write number at end FROTransportContexts.Remove(transport);
strmResponse.Position := strmResponse.Size; //transport._Release;
strmResponse.Write(C_ROWSNR, Length(C_ROWSNR)); AThread.Data := nil;
strmResponse.Write(iMsgNr, SizeOf(iMsgNr)); end;
strmResponse.Position := 0;
end; procedure TROIndyHTTPWebsocketServer.Loaded;
begin
{ TROTransport } //do before inherited in case of designtime connection
if Self.IndyServer.IOHandler = nil then
constructor TROTransportContext.Create(aROServer: TROIndyHTTPServer; IndyServer.IOHandler := TIdServerIOHandlerWebsocket.Create(Self);
aIdContext: TIdServerWSContext); inherited;
begin end;
FROServer := aROServer;
FIdContext := aIdContext; procedure TROIndyHTTPWebsocketServer.ProcessRemObjectsRequest(
end; const AThread: TIdContext; const strmRequest: TMemoryStream; const strmResponse: TMemoryStream);
var
procedure TROTransportContext.EventsRegistered(aSender: TObject; aClient: TGUID); cWSNR: array[0..High(C_ROWSNR)] of AnsiChar;
begin msg: TROMessageDispatcher;
// iMsgNr: Integer;
end; imsg: IROMessage;
transport: TROTransportContext;
procedure TROTransportContext.DispatchEvent(anEventDataItem: TROEventData; begin
aSessionReference: TGUID; aSender: TObject); if strmRequest.Size < Length(C_ROWSNR) + SizeOf(iMsgNr) then Exit;
var //read messagenr from the end
i: Integer; strmRequest.Position := strmRequest.Size - Length(C_ROWSNR) - SizeOf(iMsgNr);
LContext: TIdContext; strmRequest.Read(cWSNR[0], Length(C_ROWSNR));
transport: TROTransportContext; if (cWSNR <> C_ROWSNR) then Exit;
l: TList; strmRequest.Read(iMsgNr, SizeOf(iMsgNr));
ws: TIdIOHandlerWebsocket; strmRequest.Position := 0;
cWSNR: array[0..High(C_ROWSNR)] of AnsiChar; //trunc extra data
begin strmRequest.Size := strmRequest.Size - Length(C_ROWSNR) - SizeOf(iMsgNr);
l := FROServer.IndyServer.Contexts.LockList; transport := AThread.Data as TROTransportContext;
try //no RO transport object already made?
if l.Count <= 0 then Exit; if transport = nil then
begin
anEventDataItem.Data.Position := anEventDataItem.Data.Size - Length(C_ROWSNR) - SizeOf(FEventCount); //create IROTransport object
anEventDataItem.Data.Read(cWSNR[0], Length(cWSNR)); transport := TROTransportContext.Create(Self, AThread as TIdServerWSContext);
//event number not written already? //(transport as IROTransport)._AddRef;
if cWSNR <> C_ROWSNR then FROTransportContexts.Add(transport);
begin //attach RO transport to indy context
//new event nr AThread.Data := transport;
FEventCount := -1 * InterlockedIncrement(FGlobalEventCount); //negative = event, positive is normal RO message //todo: enveloppes
//overflow? then start again from 0 //read client GUID the first time (needed to be able to send RO events)
if FEventCount > 0 then msg := Self.Dispatchers.FindDispatcher(transport, strmRequest);
begin if msg = nil then
InterlockedExchange(FGlobalEventCount, 0); raise EROException.Create('No suiteable message dispatcher found!');
FEventCount := -1 * InterlockedIncrement(FGlobalEventCount); //negative = event, positive is normal RO message imsg := (msg.MessageIntf as IROMessageCloneable).Clone;
end; imsg.InitializeRead(transport);
Assert(FEventCount < 0); imsg.ReadFromStream(strmRequest);
//write nr at end of message transport.ClientId := imsg.ClientID;
anEventDataItem.Data.Position := anEventDataItem.Data.Size; imsg := nil;
anEventDataItem.Data.Write(C_ROWSNR, Length(C_ROWSNR)); Assert(not IsEqualGUID(transport.ClientID, EmptyGUID));
anEventDataItem.Data.Write(FEventCount, SizeOf(FEventCount)); end;
anEventDataItem.Data.Position := 0; //EXECUTE FUNCTION
end; Self.DispatchMessage(transport, strmRequest, strmResponse);
//write number at end
//search specific client strmResponse.Position := strmResponse.Size;
for i := 0 to l.Count - 1 do strmResponse.Write(C_ROWSNR, Length(C_ROWSNR));
begin strmResponse.Write(iMsgNr, SizeOf(iMsgNr));
LContext := TIdContext(l.Items[i]); strmResponse.Position := 0;
transport := LContext.Data as TROTransportContext; end;
if transport = nil then Continue;
if not IsEqualGUID(transport.ClientId, aSessionReference) then Continue; { TROTransport }
//direct write event data constructor TROTransportContext.Create(aROServer: TROIndyHTTPServer;
ws := (LContext.Connection.IOHandler as TIdIOHandlerWebsocket); aIdContext: TIdServerWSContext);
if not ws.IsWebsocket then Exit; begin
ws.Lock; FROServer := aROServer;
try FIdContext := aIdContext;
try ws.Write(anEventDataItem.Data, wdtBinary) except {continue with other connections} end; end;
finally
ws.Unlock; procedure TROTransportContext.EventsRegistered(aSender: TObject; aClient: TGUID);
end; begin
end; //
finally end;
anEventDataItem.RemoveRef;
FROServer.IndyServer.Contexts.UnlockList; procedure TROTransportContext.DispatchEvent(anEventDataItem: TROEventData;
end; aSessionReference: TGUID; aSender: TObject);
end; var
i: Integer;
function TROTransportContext.GetClientAddress: string; LContext: TIdContext;
begin transport: TROTransportContext;
Result := FIdContext.Binding.PeerIP; l: TList;
end; ws: TIdIOHandlerWebsocket;
cWSNR: array[0..High(C_ROWSNR)] of AnsiChar;
function TROTransportContext.GetTransportObject: TObject; begin
begin l := FROServer.IndyServer.Contexts.LockList;
Result := FROServer; try
end; if l.Count <= 0 then Exit;
{ TROHTTPMessageDispatchers_WebSocket } anEventDataItem.Data.Position := anEventDataItem.Data.Size - Length(C_ROWSNR) - SizeOf(FEventCount);
anEventDataItem.Data.Read(cWSNR[0], Length(cWSNR));
function TROHTTPMessageDispatchers_WebSocket.GetDispatcherClass: TROMessageDispatcherClass; //event number not written already?
begin if cWSNR <> C_ROWSNR then
result := TROHTTPDispatcher_Websocket; begin
end; //new event nr
FEventCount := -1 * InterlockedIncrement(FGlobalEventCount); //negative = event, positive is normal RO message
{ TROHTTPDispatcher_Websocket } //overflow? then start again from 0
if FEventCount > 0 then
function TROHTTPDispatcher_Websocket.CanHandleMessage( begin
const aTransport: IROTransport; aRequeststream: TStream): boolean; InterlockedExchange(FGlobalEventCount, 0);
var FEventCount := -1 * InterlockedIncrement(FGlobalEventCount); //negative = event, positive is normal RO message
tcp: IROTCPTransport; end;
buf: array [0..5] of AnsiChar; Assert(FEventCount < 0);
begin //write nr at end of message
if aRequeststream = nil then result := FALSE else // for preventing warning in FPC anEventDataItem.Data.Position := anEventDataItem.Data.Size;
result := FALSE; anEventDataItem.Data.Write(C_ROWSNR, Length(C_ROWSNR));
anEventDataItem.Data.Write(FEventCount, SizeOf(FEventCount));
if not Enabled or anEventDataItem.Data.Position := 0;
not Supports(aTransport, IROTCPTransport, tcp) end;
then
Exit; //search specific client
if (tcp as TROTransportContext).FIdContext.IOHandler.IsWebsocket then for i := 0 to l.Count - 1 do
begin begin
//we can handle all kind of messages, independent on the path, so check which kind of message we have LContext := TIdContext(l.Items[i]);
Result := Self.Message.IsValidMessage((aRequeststream as TMemoryStream).Memory, aRequeststream.Size); transport := LContext.Data as TROTransportContext;
if transport = nil then Continue;
//goes wrong with enveloppes! if not IsEqualGUID(transport.ClientId, aSessionReference) then Continue;
//TROMessage.Envelopes_ProcessIncoming
if not Result and //direct write event data
(aRequeststream.Size > 6) then ws := (LContext.Connection.IOHandler as TIdIOHandlerWebsocket);
begin if not ws.IsWebsocket then Exit;
aRequeststream.Read(buf,6); ws.Lock;
Result := (buf[0] = EnvelopeSignature[0]) and try
(buf[1] = EnvelopeSignature[1]) and try ws.Write(anEventDataItem.Data, wdtBinary) except {continue with other connections} end;
(buf[2] = EnvelopeSignature[2]) and finally
(buf[3] = EnvelopeSignature[3]) and ws.Unlock;
(buf[4] = EnvelopeSignature[4]); end;
aRequeststream.Position := 0; end;
end; finally
end anEventDataItem.RemoveRef;
else FROServer.IndyServer.Contexts.UnlockList;
Result := inherited CanHandleMessage(aTransport, aRequeststream); end;
end; end;
end. function TROTransportContext.GetClientAddress: string;
begin
Result := FIdContext.Binding.PeerIP;
end;
function TROTransportContext.GetTransportObject: TObject;
begin
Result := FROServer;
end;
{ TROHTTPMessageDispatchers_WebSocket }
function TROHTTPMessageDispatchers_WebSocket.GetDispatcherClass: TROMessageDispatcherClass;
begin
result := TROHTTPDispatcher_Websocket;
end;
{ TROHTTPDispatcher_Websocket }
function TROHTTPDispatcher_Websocket.CanHandleMessage(
const aTransport: IROTransport; aRequeststream: TStream): boolean;
var
tcp: IROTCPTransport;
buf: array [0..5] of AnsiChar;
begin
if aRequeststream = nil then result := FALSE else // for preventing warning in FPC
result := FALSE;
if not Enabled or
not Supports(aTransport, IROTCPTransport, tcp)
then
Exit;
if (tcp as TROTransportContext).FIdContext.IOHandler.IsWebsocket then
begin
//we can handle all kind of messages, independent on the path, so check which kind of message we have
Result := Self.Message.IsValidMessage((aRequeststream as TMemoryStream).Memory, aRequeststream.Size);
//goes wrong with enveloppes!
//TROMessage.Envelopes_ProcessIncoming
if not Result and
(aRequeststream.Size > 6) then
begin
aRequeststream.Read(buf,6);
Result := (buf[0] = EnvelopeSignature[0]) and
(buf[1] = EnvelopeSignature[1]) and
(buf[2] = EnvelopeSignature[2]) and
(buf[3] = EnvelopeSignature[3]) and
(buf[4] = EnvelopeSignature[4]);
aRequeststream.Position := 0;
end;
end
else
Result := inherited CanHandleMessage(aTransport, aRequeststream);
end;
end.