Since Poco receiveFrame expected the buffer to be
at least as large as the frame, otherwise the socket
had to be closed, we sent a 'nextmessage' frame
before sending large frames with the payload size.
This caused many problems, not least related to threading
and lack of atomicity when sending large frames.
There is another API in Poco that doesn't have this
strict requirement, one that expects Poco::Buffer
and resizes it as necessary.
One potential issue is the possibility that a malicious
attacker might send very large frames to force the
server into allocating large buffers to read them,
thereby destibilizing the server, if not bringing it
down altogether.
Change-Id: I05014d54c3a1464f629ed82d761a7a65e4941985
Reviewed-on: https://gerrit.libreoffice.org/31184
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
sendFrame() implemented in LOOLWebSocket is thread safe, and also deals with
large messages - sends the "nextmessage: size=..." frame before the actual
large frame.
The problem this is attempting to solve was that when sending a large frame,
it was split to multiple packets. During that, another frame was sent from a
different thread; which lead to confusion, and the resulting frame was
corrupted (because it ended up composed from unrelated packets).
Change-Id: Ie85952e431b1cad2fdc6e3c64df8a444ea0ae971
Don't mention 'TerminationFlag' in the log line when that lovely
global variable isn't what we are logging there (but the local 'stop'
boolean variable). Also, output its value as "true" or "false", not
numerically.
A source file (.cpp) must include its own header first.
This insures that the header is self-contained and
doesn't depend on arbitrary (and accidental) includes
before it to compile.
Furthermore, system headers should go next, followed by
C then C++ headers, then libraries (Poco, etc) and, finally,
project headers come last.
This makes sure that headers and included in the same dependency
order to avoid side-effects. For example, Poco should never rely on
anything from our project in the same way that a C header should
never rely on anything in C++, Poco, or project headers.
Also, includes ought to be sorted where possible, to improve
readability and avoid accidental duplicates (of which there
were a few).
Change-Id: I62cc1343e4a091d69195e37ed659dba20cfcb1ef
Reviewed-on: https://gerrit.libreoffice.org/25262
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
UnitPrefork got what I assume is one of those PING frames that
ChildProcess::isAlive() sends before the actual reply when it sent the
"unit-memdump" message, and did not like it. Uncommenting the line
that outputs the "memory stats" message it expects showed:
Got memory stats 'PING'
Followed by:
Assertion `tokens.count() == 2' failed.
Fix by factoring out the handling of PING frames, PONG frames, and the
pseudo-PONG frames that we send ourselves in reply to PING frames into
a new function IoUtil::receiveFrame(). Use that in a couple of
places. (Probably should use in many more places.)
Getting past this then leads to later cppunit tests again being run,
and their failures then again showing up...
The closing handshake.
Either peer can send a control frame with data containing
a specified control sequence to begin the closing handshake.
Upon receiving such a frame, the other peer sends a
Close frame in response, if it hasn't already sent one.
SocketProcessor doesn't need to take response
instance, since by the time it is called we
are already upgraded to WebSocket and it's
too late to set a request-level status.
Change-Id: Id95087e60354a50148c88427130613356679cf82
Reviewed-on: https://gerrit.libreoffice.org/24110
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
In case of abnormal termination of session from client-side,
we might still have data being processed in the kit process, for
example, during auto-save. Trying to send such data over an
expired socket towards the client would throw exceptions which
need to be handled, otherwise the auto-save process would not be
successful. Further, the unhandled exception can bring the document
broker in an unstable state with dockey still present in the
object.
Also do not send 'editlock: 0' to a websocket session which is
going to be removed because the session might have been
forcefully terminated from the client-side, in which case sending
data would go nowhere.
Change-Id: I10eb9c818bc81d4db26d5a19dc8bd44f6fbdf32c
It is a status code, a 2-byte unsigned integer in network byte order,
potentially followed by a textual reason. But we never include any
specific status codes in the CLOSE frames anyway. (With a Poco-based
WebSocket peer it is always WS_NORMAL_CLOSE, 1000, 0x03 0xE8.)
Also, display more information about the exception.
Actually I think I should factor out the code to display as much
information as possible from an exception. Currently the amount of
information displayed varies from case to case in the code-base.
Much better than assuming that errno would be relevant at all
Log::error() calls (or alternatively, having to remember to append a
false parameter to the Log::error() call, which had not been done a
single time anyway.)
Call log::syserror() right after a system call has returned an
error. Don't call it otherwise.