proces websocket data already fetched during upgrade (otherwise strange data corruption afterwards...)

This commit is contained in:
André Mussche 2014-03-14 16:27:30 +01:00
parent 57077ab1f3
commit 3e02642917
2 changed files with 60 additions and 14 deletions

View file

@ -41,6 +41,7 @@ type
FLastActivityTime: TDateTime; FLastActivityTime: TDateTime;
FLastPingTime: TDateTime; FLastPingTime: TDateTime;
class var FUseSingleWriteThread: Boolean; class var FUseSingleWriteThread: Boolean;
procedure SetIsWebsocket(const Value: Boolean);
protected protected
FMessageStream: TMemoryStream; FMessageStream: TMemoryStream;
FWriteTextToTarget: Boolean; FWriteTextToTarget: Boolean;
@ -63,7 +64,7 @@ type
function WriteData(aData: TIdBytes; aType: TWSDataCode; function WriteData(aData: TIdBytes; aType: TWSDataCode;
aFIN: boolean = true; aRSV1: boolean = false; aRSV2: boolean = false; aRSV3: boolean = false): integer; aFIN: boolean = true; aRSV1: boolean = false; aRSV2: boolean = false; aRSV3: boolean = false): integer;
property BusyUpgrading : Boolean read FBusyUpgrading write FBusyUpgrading; property BusyUpgrading : Boolean read FBusyUpgrading write FBusyUpgrading;
property IsWebsocket : Boolean read FIsWebsocket write FIsWebsocket; property IsWebsocket : Boolean read FIsWebsocket write SetIsWebsocket;
property IsServerSide : Boolean read FIsServerSide write FIsServerSide; property IsServerSide : Boolean read FIsServerSide write FIsServerSide;
property ClientExtensionBits : TWSExtensionBits read FExtensionBits write FExtensionBits; property ClientExtensionBits : TWSExtensionBits read FExtensionBits write FExtensionBits;
public public
@ -93,6 +94,8 @@ type
procedure Write(AStream: TStream; aType: TWSDataType); overload; procedure Write(AStream: TStream; aType: TWSDataType); overload;
procedure WriteBufferFlush(AByteCount: Integer); override; procedure WriteBufferFlush(AByteCount: Integer); override;
procedure ReadBytes(var VBuffer: TIdBytes; AByteCount: Integer; AAppend: Boolean = True); override;
property LastActivityTime: TDateTime read FLastActivityTime write FLastActivityTime; property LastActivityTime: TDateTime read FLastActivityTime write FLastActivityTime;
property LastPingTime: TDateTime read FLastPingTime write FLastPingTime; property LastPingTime: TDateTime read FLastPingTime write FLastPingTime;
@ -136,6 +139,7 @@ type
class procedure RemoveInstance; class procedure RemoveInstance;
end; end;
TIdBuffer_Ext = class(TIdBuffer);
//close frame codes //close frame codes
const const
@ -204,14 +208,14 @@ const
C_FrameCode_Pong = 10 {A}; C_FrameCode_Pong = 10 {A};
//B-F are reserved for further control frames //B-F are reserved for further control frames
function BytesToStringRaw(const AValue: TIdBytes): string; function BytesToStringRaw(const AValue: TIdBytes; aSize: Integer = -1): string;
var var
i: Integer; i: Integer;
begin begin
//SetLength(Result, Length(aValue)); //SetLength(Result, Length(aValue));
for i := 0 to High(AValue) do for i := 0 to High(AValue) do
begin begin
if AValue[i] = 0 then Exit; if (AValue[i] = 0) and (aSize < 0) then Exit;
if (AValue[i] < 33) or if (AValue[i] < 33) or
( (AValue[i] > 126) and ( (AValue[i] > 126) and
@ -219,7 +223,9 @@ begin
then then
Result := Result + '#' + IntToStr(AValue[i]) Result := Result + '#' + IntToStr(AValue[i])
else else
Result := Result + Char(AValue[i]) Result := Result + Char(AValue[i]);
if (aSize > 0) and (i > aSize) then Break;
end; end;
end; end;
@ -603,6 +609,24 @@ begin
end; end;
end; end;
procedure TIdIOHandlerWebsocket.ReadBytes(var VBuffer: TIdBytes;
AByteCount: Integer; AAppend: Boolean);
begin
inherited;
{$IFDEF DEBUG_WS}
if IsWebsocket then
if Debughook > 0 then
begin
OutputDebugString(PChar(Format('%d Bytes read(TID:%d): %s',
[AByteCount, getcurrentthreadid, BytesToStringRaw(VBuffer, AByteCount)])));
OutputDebugString(PChar(Format('Buffer (HeadIndex:%d): %s',
[TIdBuffer_Ext(InputBuffer).FHeadIndex,
BytesToStringRaw(TIdBuffer_Ext(InputBuffer).FBytes,
InputBuffer.Size + TIdBuffer_Ext(InputBuffer).FHeadIndex)])));
end;
{$ENDIF}
end;
function TIdIOHandlerWebsocket.ReadDataFromSource( function TIdIOHandlerWebsocket.ReadDataFromSource(
var VBuffer: TIdBytes): Integer; var VBuffer: TIdBytes): Integer;
var var
@ -625,7 +649,7 @@ begin
{$IFDEF DEBUG_WS} {$IFDEF DEBUG_WS}
if Debughook > 0 then if Debughook > 0 then
OutputDebugString(PChar(Format('Received (non ws, TID:%d, P:%d): %s', OutputDebugString(PChar(Format('Received (non ws, TID:%d, P:%d): %s',
[getcurrentthreadid, Self.Binding.PeerPort, BytesToStringRaw(VBuffer)]))); [getcurrentthreadid, Self.Binding.PeerPort, BytesToStringRaw(VBuffer, Result)])));
{$ENDIF} {$ENDIF}
end end
else else
@ -775,6 +799,20 @@ begin
end; end;
end; end;
procedure TIdIOHandlerWebsocket.SetIsWebsocket(const Value: Boolean);
var data: TIdBytes;
begin
//copy websocket data which was send/received during http upgrade
if not FIsWebsocket and Value and
(FInputBuffer.Size > 0) then
begin
FInputBuffer.ExtractToBytes(data);
FWSInputBuffer.Write(data);
end;
FIsWebsocket := Value;
end;
procedure TIdIOHandlerWebsocket.Lock; procedure TIdIOHandlerWebsocket.Lock;
begin begin
FLock.Enter; FLock.Enter;
@ -818,8 +856,10 @@ var
begin begin
FWSInputBuffer.Write(temp); FWSInputBuffer.Write(temp);
{$IFDEF DEBUG_WS} {$IFDEF DEBUG_WS}
if debughook > 0 then // if debughook > 0 then
OutputDebugString(PChar('Received: ' + BytesToStringRaw(temp))); // OutputDebugString(PChar(Format('Received (TID:%d, P:%d): %s',
// [getcurrentthreadid, Self.Binding.PeerPort, BytesToStringRaw(temp)])));
// OutputDebugString(PChar('Received: ' + BytesToStringRaw(temp)));
{$ENDIF} {$ENDIF}
end; end;
end; end;
@ -968,6 +1008,11 @@ begin
end; end;
Result := Length(aData); Result := Length(aData);
{$IFDEF DEBUG_WS}
if debughook > 0 then
OutputDebugString(PChar(Format('Received (TID:%d, P:%d, Count=%d): %s',
[getcurrentthreadid, Self.Binding.PeerPort, Result, BytesToStringRaw(aData, Result)])));
{$ENDIF}
end; end;
function TIdIOHandlerWebsocket.WriteData(aData: TIdBytes; function TIdIOHandlerWebsocket.WriteData(aData: TIdBytes;
@ -1092,7 +1137,8 @@ begin
until ioffset >= Length(bData); until ioffset >= Length(bData);
// if debughook > 0 then // if debughook > 0 then
// OutputDebugString(PChar('Written: ' + BytesToStringRaw(bData))); // OutputDebugString(PChar(Format('Written (TID:%d, P:%d): %s',
// [getcurrentthreadid, Self.Binding.PeerPort, BytesToStringRaw(bData)])));
finally finally
Unlock; Unlock;
strmData.Free; strmData.Free;

View file

@ -624,8 +624,8 @@ begin
if sdata <> '' then if sdata <> '' then
begin begin
{$WARN SYMBOL_PLATFORM OFF} {$WARN SYMBOL_PLATFORM OFF}
if DebugHook <> 0 then // if DebugHook <> 0 then
Windows.OutputDebugString(PChar('Send: ' + sdata)); // Windows.OutputDebugString(PChar('Send: ' + sdata));
bytes := TEncoding.UTF8.GetBytes(sdata); bytes := TEncoding.UTF8.GetBytes(sdata);
aStrmResponse.Write(bytes[0], Length(bytes)); aStrmResponse.Write(bytes[0], Length(bytes));
@ -694,8 +694,8 @@ begin
str := aData; str := aData;
if str = '' then Exit; if str = '' then Exit;
if DebugHook <> 0 then // if DebugHook <> 0 then
Windows.OutputDebugString(PChar('Received: ' + str)); // Windows.OutputDebugString(PChar('Received: ' + str));
while str[1] = #0 do while str[1] = #0 do
Delete(str, 1, 1); Delete(str, 1, 1);
@ -1048,8 +1048,8 @@ begin
if (ASocket.FIOHandler <> nil) then if (ASocket.FIOHandler <> nil) then
begin begin
//Assert(ASocket.FIOHandler.IsWebsocket); //Assert(ASocket.FIOHandler.IsWebsocket);
if DebugHook <> 0 then // if DebugHook <> 0 then
Windows.OutputDebugString(PChar('Send: ' + aText)); // Windows.OutputDebugString(PChar('Send: ' + aText));
ASocket.FIOHandler.Write(aText); ASocket.FIOHandler.Write(aText);
end end
else if ASocket.GUID <> '' then else if ASocket.GUID <> '' then