We don't need a special "WebSocket" class, as websocket itself is just an
upgrade of an existing socket / connection, and trying to come up with a
concept where a Socket class magically upgrades to a WebSocket class would be
messy.
So let's have just a WebSocketHandler, that communicates over a StreamSocket
or SslStreamSocket, and be done with that :-)
Change-Id: I449e4d662fbe2c5b1789e308053e4a71376fe481
Introduce the appropriate interface instead of the template, so that we can
de-couple the ResponseClient from the Socket itself.
Change-Id: I21892bbce5d83a18ca580a25cfc2efbb05b08705
SSL's decryption frame is 16kb, so it
makes sense to read by that multiple
for efficiency reasons.
Change-Id: Ib5d7b5bfc18fa1b27bcbc9aac93350c4e1292874
Reviewed-on: https://gerrit.libreoffice.org/34451
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
We now always read new data, because
SSL might need to process internal buffers,
and call the app message handler as long
as it keeps consuming data.
Finally, we write when we have data
to flush, even if we didn't get POLLOUT
event, because SSL might need to do
handshake, which is handled by the write
handler.
Change-Id: I909333c3a0492b0830044d51ae478ac5981b1d90
Reviewed-on: https://gerrit.libreoffice.org/34448
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
We expect to have more data if the buffer was
filled completely. Otherwise, there is no
reason to suspect there is more data, unless
we hope to have received time in that short
interval, which is not very likely.
Change-Id: I9a3dcb6378e8dcfa0d49b6c7ea92d7cec6690787
Reviewed-on: https://gerrit.libreoffice.org/34446
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
The new test sends data of of 1 byte to
N bytes and expects the exact same data
returned in response.
This tests both buffering sizes and
websocket frames.
Change-Id: Ic6232b4e899d82d90a0ee7c96e4852ffaaf8e958
Reviewed-on: https://gerrit.libreoffice.org/34441
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
SSL expects the write buffer to be the same on
retry. This requirement cannot be guaranteed
when using standard containers as the internal
memory might be re-allocated between calls.
Luckily SSL can relax this requirement when asked.
Change-Id: I26771609a8cc0f9de0e554f9fa255d998f6c7b14
Reviewed-on: https://gerrit.libreoffice.org/34440
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
Draining the buffer is the correct appraoch
to avoid accumulating data in the kernel
unnecessarily. But it also reduces the overhead
of reparsing the incoming data for message
boundaries.
The client that is to parse the data should
parse as many messages as possible and remove
them from the socket buffer.
Finally, we probably need to cap the maximum
buffer size to avoid bloating. However this
heavily depends on the application's max
message size, assuming there is no separate
buffer beyond that of the socket to accumulate
the messages in.
Change-Id: I49c4eccebd474cd07ca84f3f4eae33bc717ed1f2
Reviewed-on: https://gerrit.libreoffice.org/34411
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
Depending on the base class, which is passed as
template parameter, SimpleResponseClient can
abstract away the underlying socket type.
Change-Id: I59a403357512f329aa2565c1ef55094704e3b4ad
Reviewed-on: https://gerrit.libreoffice.org/34393
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
Now we have plain and ssl sockets based on
the BufferingSocket, each is responsible for
the socket IO only.
The SSL socket is only shell missing implementation.
Change-Id: I51d274a9335cec52c13b6a19927ddd46d98265a0
Reviewed-on: https://gerrit.libreoffice.org/34352
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
StreamSocket has nothing Client-side specific.
Indeed it could be used on the Server-side.
As such, it's data-streaming, rather than client,
hence the new name.
Change-Id: I4e048def968b3a12e11edb49760ed03e3843ae6b
Reviewed-on: https://gerrit.libreoffice.org/34351
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
The socket now buffers input, and output, updates its poll record too.
We pass a simple message from client to server and back using lamers HTTP.
Sub-classed ClientSocket to provide a simple message handler.
not very convinced by templatization here, but made it consistent.
more ideal to have some virtual socket pieces.
Avoid using 'poll' as a member function, and a local variable.
Avoid using 'fd' as a member function, and a parameter.
Add assertions around wake pipe.
Always setup sockets for polling, strobing events is expected.
Internally SocketPoll manages the sockets
and handles the polling and firing of callback.
It's thread-safe and handles asynchronous calls
to remove sockets correctly while potentially
being in poll(2).
The choice for using poll(2) compared to epoll
or select are the following:
1. For our use-case, poll(2) works great up to
a few hundred sockets, which we don't expect
to have on a single document normally.
2. select(2) has an awkward API (modifies input,
f.e) and has limit on max fds that we need to
be mindful of (even if we'll not hit it in
practice). poll(2) preserves the input and has
a no-nonsense API that's simple and readable.
3. While select(2) is the most portable, poll(2)
isn't far behind. Yet in practice we'll probably
not support other systems than Linux.
4. epoll(2) starts to scale with hundreds or
thousands of sockets. Meanwhile, it has high
overhead to adding/removing sockets (context
switch to kernel and back). Our typical case
will have a handful to a dozen sockets.
Hardly a justification for epoll's heavy guns.
Change-Id: Idf88257ea85e061a37af29eed21e38655ff43c9b
This is virtually always desirable, since
without it we may fail to bind after recycling
if the previous socket is TIME_WAIT.
However, if a socket is bound to same address
this will not prevent the failure to bind,
and we'll detect that the address/port is busy.
So the advantage is in minimizing recycling time.
Change-Id: Ib3bbbf7065f9822acfbd2d7f8ff3e8951739c0ef
The new socket class is implicitly
non-blocking, streaming, ipv4 socket.
Ipv6 to be added later, as necessary.
Change-Id: I722cc63ea97394d47a50b733c58a69cc1529d815