diff --git a/src/AsyncSocket.h b/src/AsyncSocket.h index 6077650..a7ac631 100644 --- a/src/AsyncSocket.h +++ b/src/AsyncSocket.h @@ -135,6 +135,11 @@ protected: getLoopData()->corkedSocket = this; } + /* Returns the corked socket or nullptr */ + void *corkedSocket() { + return getLoopData()->corkedSocket; + } + /* Returns wheter we are corked or not */ bool isCorked() { return getLoopData()->corkedSocket == this; diff --git a/src/HttpResponse.h b/src/HttpResponse.h index 8b04196..5955f6d 100644 --- a/src/HttpResponse.h +++ b/src/HttpResponse.h @@ -497,8 +497,20 @@ public: Super::cork(); handler(); + /* The only way we could possibly have changed the corked socket during handler call, would be if + * the HTTP socket was upgraded to WebSocket and caused a realloc. Because of this we cannot use "this" + * from here downwards. The corking is done with corkUnchecked() in upgrade. It steals cork. */ + auto *newCorkedSocket = Super::corkedSocket(); + /* Timeout on uncork failure, since most writes will succeed while corked */ - auto [written, failed] = Super::uncork(); + auto [written, failed] = static_cast(newCorkedSocket)->uncork(); + + /* If we are no longer an HTTP socket then early return the new "this". + * We don't want to even overwrite timeout as it is set in upgrade already. */ + if (this != newCorkedSocket) { + return static_cast(newCorkedSocket); + } + if (failed) { /* For now we only have one single timeout so let's use it */ /* This behavior should equal the behavior in HttpContext when uncorking fails */