diff --git a/IdHTTPWebsocketClient.pas b/IdHTTPWebsocketClient.pas index 70e5435..83ba9ed 100644 --- a/IdHTTPWebsocketClient.pas +++ b/IdHTTPWebsocketClient.pas @@ -625,12 +625,7 @@ begin //ws://host:port/ //about resourcename, see: http://dev.w3.org/html5/websockets/ "Parsing WebSocket URLs" //sURL := Format('ws://%s:%d/%s', [Host, Port, WSResourceName]); - sURL := Format('https://%s:%d/%s', [Host, Port, WSResourceName]); -{$IFDEF WS_NO_SSL} - //TODO: depend protocol on usessl - param passing in here sURL := Format('http://%s:%d/%s', [Host, Port, WSResourceName]); -{$ENDIF} - ReadTimeout := Max(5 * 1000, ReadTimeout); { voorbeeld: diff --git a/IdIOHandlerWebsocket.pas b/IdIOHandlerWebsocket.pas index 9219ece..33b6d21 100644 --- a/IdIOHandlerWebsocket.pas +++ b/IdIOHandlerWebsocket.pas @@ -11,9 +11,6 @@ uses Classes, SysUtils, IdIOHandlerStack, IdGlobal, IdException, IdBuffer, SyncObjs, -{$IFNDEF WS_NO_SSL} - IdSSLOpenSSL, -{$ENDIF} Generics.Collections; type @@ -25,14 +22,11 @@ type TIdIOHandlerWebsocket = class; EIdWebSocketHandleError = class(EIdSocketHandleError); - {.$if CompilerVersion >= 26} //XE5 - //TIdTextEncoding = IIdTextEncoding; - {.$ifend} -{$IFDEF WS_NO_SSL} + {$if CompilerVersion >= 26} //XE5 + TIdTextEncoding = IIdTextEncoding; + {$ifend} + TIdIOHandlerWebsocket = class(TIdIOHandlerStack) -{$ELSE} - TIdIOHandlerWebsocket = class(TIdSSLIOHandlerSocketOpenSSL) -{$ENDIF} private FIsServerSide: Boolean; FBusyUpgrading: Boolean; @@ -61,15 +55,12 @@ type function ReadFrame(out aFIN, aRSV1, aRSV2, aRSV3: boolean; out aDataCode: TWSDataCode; out aData: TIdBytes): Integer; function ReadMessage(var aBuffer: TIdBytes; out aDataCode: TWSDataCode): Integer; - {.$if CompilerVersion >= 26} //XE5 - //function UTF8Encoding: IIdTextEncoding; - {.$else} + {$if CompilerVersion >= 26} //XE5 + function UTF8Encoding: IIdTextEncoding; + {$else} function UTF8Encoding: TEncoding; - {.$ifend} + {$ifend} public -{$IFNDEF WS_NO_SSL} - procedure ClearSSLOptions; -{$ENDIF} function WriteData(aData: TIdBytes; aType: TWSDataCode; aFIN: boolean = true; aRSV1: boolean = false; aRSV2: boolean = false; aRSV3: boolean = false): integer; property BusyUpgrading : Boolean read FBusyUpgrading write FBusyUpgrading; @@ -267,14 +258,6 @@ begin FPendingWriteCount := 0; end; -{$IFNDEF WS_NO_SSL} -procedure TIdIOHandlerWebsocket.ClearSSLOptions; -begin - self.fxSSLOptions.Free; - self.fxSSLOptions := nil; -end; -{$ENDIF} - procedure TIdIOHandlerWebsocket.Close; var iaWriteBuffer: TIdBytes; @@ -573,6 +556,8 @@ end; function TIdIOHandlerWebsocket.WriteDataToTarget(const ABuffer: TIdBytes; const AOffset, ALength: Integer): Integer; +var + data: TIdBytes; begin if UseSingleWriteThread and IsWebsocket and (GetCurrentThreadId <> TIdWebsocketWriteThread.Instance.ThreadID) then Assert(False, 'Write done in different thread than TIdWebsocketWriteThread!'); @@ -591,17 +576,19 @@ begin end else begin + data := ToBytes(ABuffer, ALength, AOffset); {$IFDEF DEBUG_WS} if Debughook > 0 then OutputDebugString(PChar(Format('Send (ws, TID:%d, P:%d): %s', - [getcurrentthreadid, Self.Binding.PeerPort, BytesToStringRaw(ABuffer)]))); + [getcurrentthreadid, Self.Binding.PeerPort, BytesToStringRaw(data)]))); + {$ENDIF} try if FWriteTextToTarget then - Result := WriteData(ABuffer, wdcText, True{send all at once}, + Result := WriteData(data, wdcText, True{send all at once}, webBit1 in ClientExtensionBits, webBit2 in ClientExtensionBits, webBit3 in ClientExtensionBits) else - Result := WriteData(ABuffer, wdcBinary, True{send all at once}, + Result := WriteData(data, wdcBinary, True{send all at once}, webBit1 in ClientExtensionBits, webBit2 in ClientExtensionBits, webBit3 in ClientExtensionBits); except FClosedGracefully := True; @@ -844,17 +831,17 @@ begin FLock.Leave; end; -{.$if CompilerVersion >= 26} //XE5 -//function TIdIOHandlerWebsocket.UTF8Encoding: IIdTextEncoding; -//begin -// Result := IndyTextEncoding_UTF8; -//end; -{.$else} +{$if CompilerVersion >= 26} //XE5 +function TIdIOHandlerWebsocket.UTF8Encoding: IIdTextEncoding; +begin + Result := IndyTextEncoding_UTF8; +end; +{$else} function TIdIOHandlerWebsocket.UTF8Encoding: TEncoding; begin Result := TIdTextEncoding.UTF8; end; -{.$ifend} +{$ifend} function TIdIOHandlerWebsocket.ReadFrame(out aFIN, aRSV1, aRSV2, aRSV3: boolean; out aDataCode: TWSDataCode; out aData: TIdBytes): Integer; @@ -1148,11 +1135,11 @@ begin AppendBytes(bData, aData); //important: send all at once! ioffset := 0; - iDataLength := Length(bData); repeat - result := inherited WriteDataToTarget(bdata,iOffset, (iDataLength-ioffset)); + //Result := Binding.Send(bData, ioffset); + Result := inherited WriteDataToTarget(bdata, iOffset, (Length(bData) - ioffset)); //ssl compatible? Inc(ioffset, Result); - until ioffset >= iDataLength; + until ioffset >= Length(bData); // if debughook > 0 then // OutputDebugString(PChar(Format('Written (TID:%d, P:%d): %s', diff --git a/IdServerIOHandlerWebsocket.pas b/IdServerIOHandlerWebsocket.pas index ed63e4d..80e1061 100644 --- a/IdServerIOHandlerWebsocket.pas +++ b/IdServerIOHandlerWebsocket.pas @@ -5,18 +5,10 @@ interface uses Classes, IdServerIOHandlerStack, IdIOHandlerStack, IdGlobal, IdIOHandler, IdYarn, IdThread, IdSocketHandle, -{$IFNDEF WS_NO_SSL} - IdSSLOpenSSL, - sysutils, -{$ENDIF} IdIOHandlerWebsocket; type -{$IFDEF WS_NO_SSL} TIdServerIOHandlerWebsocket = class(TIdServerIOHandlerStack) -{$ELSE} - TIdServerIOHandlerWebsocket = class(TIdServerIOHandlersslOpenSSL) -{$ENDIF} protected procedure InitComponent; override; public @@ -31,40 +23,8 @@ implementation function TIdServerIOHandlerWebsocket.Accept(ASocket: TIdSocketHandle; AListenerThread: TIdThread; AYarn: TIdYarn): TIdIOHandler; -{$IFNDEF WS_NO_SSL} -var - LIO: TIdIOHandlerWebsocket; -{$ENDIF} begin -{$IFDEF WS_NO_SSL} Result := inherited Accept(ASocket, AListenerThread, AYarn); -{$ELSE} - Assert(ASocket<>nil); - Assert(fSSLContext<>nil); - LIO := TIdIOHandlerWebsocket.Create(nil); - try - LIO.PassThrough := True; - LIO.Open; - if LIO.Binding.Accept(ASocket.Handle) then - begin - //we need to pass the SSLOptions for the socket from the server - LIO.ClearSSLOptions; - LIO.IsPeer := True; - LIO.SSLOptions := SSLOptions; - LIO.SSLSocket := TIdSSLSocket.Create(Self); - LIO.SSLContext := fSSLContext; - - end - else - begin - FreeAndNil(LIO); - end; - except - LIO.Free; - raise; - end; - Result := LIO; -{$ENDIF} if Result <> nil then begin (Result as TIdIOHandlerWebsocket).IsServerSide := True; //server must not mask, only client @@ -75,9 +35,7 @@ end; procedure TIdServerIOHandlerWebsocket.InitComponent; begin inherited InitComponent; -{$IFDEF WS_NO_SSL} IOHandlerSocketClass := TIdIOHandlerWebsocket; -{$ENDIF} end; function TIdServerIOHandlerWebsocket.MakeClientIOHandler( diff --git a/IdServerWebsocketHandling.pas b/IdServerWebsocketHandling.pas index 28ebd68..f1f6f52 100644 --- a/IdServerWebsocketHandling.pas +++ b/IdServerWebsocketHandling.pas @@ -137,9 +137,7 @@ begin aSocketIOHandler.WritePing(context); end else - begin context.IOHandler.WriteData(nil, wdcPing); - end; end; end; @@ -327,22 +325,13 @@ begin hash.Free; end; AResponseInfo.CustomHeaders.Values['Sec-WebSocket-Accept'] := sValue; -{$IFNDEF WS_NO_SSL} - //keep alive the ssl connection - AResponseInfo.CustomHeaders.Values['Keep-alive'] := 'true'; -{$ENDIF} - + //send same protocol back? AResponseInfo.CustomHeaders.Values['Sec-WebSocket-Protocol'] := context.WebSocketProtocol; //we do not support extensions yet (gzip deflate compression etc) //AResponseInfo.CustomHeaders.Values['Sec-WebSocket-Extensions'] := context.WebSocketExtensions; //http://www.lenholgate.com/blog/2011/07/websockets---the-deflate-stream-extension-is-broken-and-badly-designed.html //but is could be done using idZlib.pas and DecompressGZipStream etc -{$IFNDEF WS_NO_SSL} - //YD: TODO: Check if this is really necessary - AResponseInfo.CustomHeaders.Values['sec-websocket-extensions'] := ''; - context.WebSocketExtensions := ''; -{$ENDIF} //send response back context.IOHandler.InputBuffer.Clear; diff --git a/IdWebsocketServer.pas b/IdWebsocketServer.pas index 980d0ab..4062c8c 100644 --- a/IdWebsocketServer.pas +++ b/IdWebsocketServer.pas @@ -4,7 +4,7 @@ interface uses IdServerWebsocketHandling, IdServerSocketIOHandling, IdServerWebsocketContext, - IdHTTPServer, IdContext, IdCustomHTTPServer, Classes, IdIOHandlerWebsocket, IdServerIOHandler; + IdHTTPServer, IdContext, IdCustomHTTPServer, Classes, IdIOHandlerWebsocket; type TWebsocketMessageText = procedure(const AContext: TIdServerWSContext; const aText: string) of object; @@ -43,12 +43,7 @@ type implementation uses - IdServerIOHandlerWebsocket, IdStreamVCL, IdGlobal, Windows, -{$IFNDEF WS_NO_SSL} - idIOHandler, - idssl, -{$ENDIF} - IdWinsock2; + IdServerIOHandlerWebsocket, IdStreamVCL, IdGlobal, Windows, IdWinsock2; { TIdWebsocketServer }