Browse Source

* Patch from Andrew Haines to actually pass OutgoingFrameMask to frames. Add woSendErrClosesConn flag

Michaël Van Canneyt 2 years ago
parent
commit
23d61350bd
1 changed files with 22 additions and 5 deletions
  1. 22 5
      packages/fcl-web/src/websocket/fpwebsocket.pp

+ 22 - 5
packages/fcl-web/src/websocket/fpwebsocket.pp

@@ -287,7 +287,8 @@ type
                woCloseExplicit,     // SeDo Close explicitly, not implicitly.
                woCloseExplicit,     // SeDo Close explicitly, not implicitly.
                woIndividualFrames,  // Send frames one by one, do not concatenate.
                woIndividualFrames,  // Send frames one by one, do not concatenate.
                woSkipUpgradeCheck,  // Skip handshake "Upgrade:" HTTP header cheack.
                woSkipUpgradeCheck,  // Skip handshake "Upgrade:" HTTP header cheack.
-               woSkipVersionCheck   // Skip handshake "Sec-WebSocket-Version' HTTP header check.
+               woSkipVersionCheck,  // Skip handshake "Sec-WebSocket-Version' HTTP header check.
+               woSendErrClosesConn  // Don't raise an exception when writing to a broken connection
               );
               );
   TWSOptions = set of TWSOption;
   TWSOptions = set of TWSOption;
 
 
@@ -482,6 +483,7 @@ Resourcestring
   SErrServerActive = 'Operation cannot be performed while the websocket connection is active';
   SErrServerActive = 'Operation cannot be performed while the websocket connection is active';
   SErrInvalidSizeFlag = 'Invalid size flag: %d';
   SErrInvalidSizeFlag = 'Invalid size flag: %d';
   SErrInvalidFrameType = 'Invalid frame type flag: %d';
   SErrInvalidFrameType = 'Invalid frame type flag: %d';
+  SErrWriteReturnedError = 'Write operation returned error: (%d) %s';
 
 
 function DecodeBytesBase64(const s: string; Strict: boolean = false) : TBytes;
 function DecodeBytesBase64(const s: string; Strict: boolean = false) : TBytes;
 function EncodeBytesBase64(const aBytes : TBytes) : String;
 function EncodeBytesBase64(const aBytes : TBytes) : String;
@@ -1175,7 +1177,7 @@ Var
 begin
 begin
   if not (aFrameType in [ftClose,ftPing,ftPong]) then
   if not (aFrameType in [ftClose,ftPing,ftPong]) then
     Raise EWebSocket.CreateFmt(SErrNotSimpleOperation,[Ord(aFrameType)]);
     Raise EWebSocket.CreateFmt(SErrNotSimpleOperation,[Ord(aFrameType)]);
-  aFrame:=FrameClass.Create(aFrameType,True,aData);
+  aFrame:=FrameClass.Create(aFrameType,True,aData, OutgoingFrameMask);
   try
   try
     Send(aFrame);
     Send(aFrame);
   finally
   finally
@@ -1532,7 +1534,7 @@ var
   aFrame: TWSFrame;
   aFrame: TWSFrame;
 
 
 begin
 begin
-  aFrame:=FrameClass.Create(aMessage);
+  aFrame:=FrameClass.Create(aMessage, OutgoingFrameMask);
   try
   try
     Send(aFrame);
     Send(aFrame);
   finally
   finally
@@ -1544,7 +1546,7 @@ procedure TWSConnection.Send(const ABytes: TBytes);
 var
 var
   aFrame: TWSFrame;
   aFrame: TWSFrame;
 begin
 begin
-  aFrame:=FrameClass.Create(ftBinary,True,ABytes);
+  aFrame:=FrameClass.Create(ftBinary,True,ABytes, OutgoingFrameMask);
   try
   try
     Send(aFrame);
     Send(aFrame);
   finally
   finally
@@ -1590,12 +1592,27 @@ procedure TWSConnection.Send(aFrame: TWSFrame);
 
 
 Var
 Var
   Data : TBytes;
   Data : TBytes;
+  Res: Integer;
+  ErrMsg: UTF8String;
 
 
 begin
 begin
   if FCloseState=csClosed then
   if FCloseState=csClosed then
     Raise EWebSocket.Create(SErrCloseAlreadySent);
     Raise EWebSocket.Create(SErrCloseAlreadySent);
   Data:=aFrame.AsBytes;
   Data:=aFrame.AsBytes;
-  Transport.WriteBytes(Data,Length(Data));
+  Res := Transport.WriteBytes(Data,Length(Data));
+  if Res < 0 then
+  begin
+    FCloseState:=csClosed;
+    ErrMsg := Format(SErrWriteReturnedError, [GetLastOSError, SysErrorMessage(GetLastOSError)]);
+    if woSendErrClosesConn in Options then
+    begin
+      SetLength(Data, 0);
+      Data.Append(TEncoding.UTF8.GetBytes(UnicodeString(ErrMsg)));
+      DispatchEvent(ftClose, nil, Data);
+    end
+    else
+      Raise EWebSocket.Create(ErrMsg);
+  end;
   if (aFrame.FrameType=ftClose) then
   if (aFrame.FrameType=ftClose) then
     begin
     begin
     if FCloseState=csNone then
     if FCloseState=csNone then