Commit 308e5cda authored by Kenton Varda's avatar Kenton Varda

Allow WebSocket to keep sending after close().

In Cloudflare Workers, we've observed applications in the wild that continue to send messages after a Close message. This is incorrect, but it happens, and we end up logging a spurious error as we attempt to proxy the message through.

By removing this restriction, we can now proxy these WebSockets despite the incorrect usage.
parent fc9a4e45
...@@ -2003,7 +2003,6 @@ public: ...@@ -2003,7 +2003,6 @@ public:
} }
kj::Promise<void> disconnect() override { kj::Promise<void> disconnect() override {
if (!sendClosed) {
KJ_REQUIRE(!currentlySending, "another message send is already in progress"); KJ_REQUIRE(!currentlySending, "another message send is already in progress");
KJ_IF_MAYBE(p, sendingPong) { KJ_IF_MAYBE(p, sendingPong) {
...@@ -2017,8 +2016,7 @@ public: ...@@ -2017,8 +2016,7 @@ public:
return promise; return promise;
} }
sendClosed = true; disconnected = true;
}
stream->shutdownWrite(); stream->shutdownWrite();
return kj::READY_NOW; return kj::READY_NOW;
...@@ -2348,7 +2346,8 @@ private: ...@@ -2348,7 +2346,8 @@ private:
kj::Own<kj::AsyncIoStream> stream; kj::Own<kj::AsyncIoStream> stream;
kj::Maybe<EntropySource&> maskKeyGenerator; kj::Maybe<EntropySource&> maskKeyGenerator;
bool sendClosed = false; bool hasSentClose = false;
bool disconnected = false;
bool currentlySending = false; bool currentlySending = false;
Header sendHeader; Header sendHeader;
kj::ArrayPtr<const byte> sendParts[2]; kj::ArrayPtr<const byte> sendParts[2];
...@@ -2375,7 +2374,7 @@ private: ...@@ -2375,7 +2374,7 @@ private:
kj::ArrayPtr<byte> recvData; kj::ArrayPtr<byte> recvData;
kj::Promise<void> sendImpl(byte opcode, kj::ArrayPtr<const byte> message) { kj::Promise<void> sendImpl(byte opcode, kj::ArrayPtr<const byte> message) {
KJ_REQUIRE(!sendClosed, "WebSocket already closed"); KJ_REQUIRE(!disconnected, "WebSocket can't send after disconnect()");
KJ_REQUIRE(!currentlySending, "another message send is already in progress"); KJ_REQUIRE(!currentlySending, "another message send is already in progress");
currentlySending = true; currentlySending = true;
...@@ -2390,7 +2389,10 @@ private: ...@@ -2390,7 +2389,10 @@ private:
return promise; return promise;
} }
sendClosed = opcode == OPCODE_CLOSE; // We don't stop the application from sending further messages after close() -- this is the
// application's error to make. But, we do want to make sure we don't send any PONGs after a
// close, since that would be our error. So we stack whether we closed for that reason.
hasSentClose = hasSentClose || opcode == OPCODE_CLOSE;
Mask mask(maskKeyGenerator); Mask mask(maskKeyGenerator);
...@@ -2441,7 +2443,7 @@ private: ...@@ -2441,7 +2443,7 @@ private:
} }
kj::Promise<void> sendPong(kj::Array<byte> payload) { kj::Promise<void> sendPong(kj::Array<byte> payload) {
if (sendClosed) { if (hasSentClose || disconnected) {
return kj::READY_NOW; return kj::READY_NOW;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment