[Libreoffice-commits] online.git: Branch 'private/Ashod/nonblocking' - 2 commits - net/loolnb.cpp net/Socket.hpp net/SslSocket.hpp
Jan Holesovsky
kendy at collabora.com
Wed Feb 22 16:18:01 UTC 2017
net/Socket.hpp | 75 ++++++++++++++++++++++++++----------------------------
net/SslSocket.hpp | 66 ++++++++++++++++++++++-------------------------
net/loolnb.cpp | 71 +++++++++++++++++++++++++++------------------------
3 files changed, 106 insertions(+), 106 deletions(-)
New commits:
commit a8e3408830cf9573cf8c9ffbcc77b73ea580e9fc
Author: Jan Holesovsky <kendy at collabora.com>
Date: Wed Feb 22 17:12:12 2017 +0100
nb: SimpleResponseClient is a client, not a socket I guess.
Introduce the appropriate interface instead of the template, so that we can
de-couple the ResponseClient from the Socket itself.
Change-Id: I21892bbce5d83a18ca580a25cfc2efbb05b08705
diff --git a/net/Socket.hpp b/net/Socket.hpp
index 779b526..9c037e9 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -283,10 +283,29 @@ private:
std::vector<pollfd> _pollFds;
};
+class StreamSocket;
+
+/// Interface that handles the actual incoming message.
+class ResponseClientInterface
+{
+public:
+ /// Set the socket associated with this ResponseClient.
+ virtual void setSocket(StreamSocket* socket) = 0;
+
+ /// Called after successful socket reads.
+ virtual void handleIncomingMessage() = 0;
+};
+
/// A plain, non-blocking, data streaming socket.
class StreamSocket : public Socket
{
public:
+ StreamSocket(const int fd, ResponseClientInterface* responseClient) :
+ Socket(fd),
+ _responseClient(responseClient)
+ {
+ _responseClient->setSocket(this);
+ }
/// Called when a polling event is received.
/// @events is the mask of events that triggered the wake.
@@ -303,7 +322,8 @@ public:
while (!_inBuffer.empty() && oldSize != _inBuffer.size())
{
oldSize = _inBuffer.size();
- handleIncomingMessage();
+ if (_responseClient)
+ _responseClient->handleIncomingMessage();
}
// SSL might want to do handshake,
@@ -394,18 +414,16 @@ public:
}
protected:
- StreamSocket(const int fd) :
- Socket(fd)
- {
- }
+ /// Client handling the actual data.
+ std::unique_ptr<ResponseClientInterface> _responseClient;
std::vector< char > _inBuffer;
std::vector< char > _outBuffer;
-private:
- /// Override to handle read data.
- /// Called after successful socket reads.
- virtual void handleIncomingMessage() = 0;
+ // FIXME temporarily make this friend class; when integrating, we'll see
+ // what methods we need to introduce instead of direct access to the
+ // _inBuffer / _outBuffer.
+ friend class SimpleResponseClient;
};
#endif
diff --git a/net/SslSocket.hpp b/net/SslSocket.hpp
index 8a9b1f0..c46ffbc 100644
--- a/net/SslSocket.hpp
+++ b/net/SslSocket.hpp
@@ -21,6 +21,33 @@
class SslStreamSocket : public StreamSocket
{
public:
+ SslStreamSocket(const int fd, ResponseClientInterface* responseClient) :
+ StreamSocket(fd, responseClient),
+ _ssl(nullptr),
+ _sslWantsTo(SslWantsTo::ReadOrWrite),
+ _doHandshake(true)
+ {
+ BIO* bio = BIO_new(BIO_s_socket());
+ if (bio == nullptr)
+ {
+ throw std::runtime_error("Failed to create SSL BIO.");
+ }
+
+ BIO_set_fd(bio, fd, BIO_NOCLOSE);
+
+ _ssl = SslContext::newSsl();
+ if (!_ssl)
+ {
+ BIO_free(bio);
+ throw std::runtime_error("Failed to create SSL.");
+ }
+
+ SSL_set_bio(_ssl, bio, bio);
+
+ // We are a server-side socket.
+ SSL_set_accept_state(_ssl);
+ }
+
~SslStreamSocket()
{
shutdown();
@@ -89,37 +116,6 @@ public:
return StreamSocket::getPollEvents();
}
-protected:
- SslStreamSocket(const int fd) :
- StreamSocket(fd),
- _ssl(nullptr),
- _sslWantsTo(SslWantsTo::ReadOrWrite),
- _doHandshake(true)
- {
- BIO* bio = BIO_new(BIO_s_socket());
- if (bio == nullptr)
- {
- throw std::runtime_error("Failed to create SSL BIO.");
- }
-
- BIO_set_fd(bio, fd, BIO_NOCLOSE);
-
- _ssl = SslContext::newSsl();
- if (!_ssl)
- {
- BIO_free(bio);
- throw std::runtime_error("Failed to create SSL.");
- }
-
- SSL_set_bio(_ssl, bio, bio);
-
- // We are a server-side socket.
- SSL_set_accept_state(_ssl);
- }
-
- // Will construct us upon accept.
- friend class ServerSocket;
-
private:
/// The possible next I/O operation that SSL want to do.
diff --git a/net/loolnb.cpp b/net/loolnb.cpp
index ab60d11..4e4ac38 100644
--- a/net/loolnb.cpp
+++ b/net/loolnb.cpp
@@ -37,9 +37,9 @@ constexpr int SslPortNumber = 9193;
static std::string computeAccept(const std::string &key);
-template <class T>
-class SimpleResponseClient : public T
+class SimpleResponseClient : public ResponseClientInterface
{
+ std::unique_ptr<StreamSocket> _socket;
int _wsVersion;
std::string _wsKey;
std::string _wsProtocol;
@@ -47,16 +47,21 @@ class SimpleResponseClient : public T
enum { HTTP, WEBSOCKET } _wsState;
public:
- SimpleResponseClient(const int fd) :
- T(fd),
+ SimpleResponseClient() :
_wsVersion(0),
_wsState(HTTP)
{
}
- virtual void handleHTTP()
+
+ virtual void setSocket(StreamSocket* socket) override
+ {
+ _socket.reset(socket);
+ }
+
+ void handleHTTP()
{
int number = 0;
- MemoryInputStream message(&T::_inBuffer[0], T::_inBuffer.size());
+ MemoryInputStream message(&_socket->_inBuffer[0], _socket->_inBuffer.size());
Poco::Net::HTTPRequest req;
req.read(message);
@@ -66,7 +71,7 @@ public:
// use Poco HTMLForm to parse the post message properly.
// Otherwise, we should catch exceptions from the previous read/parse
// and assume we don't have sufficient data, so we wait some more.
- T::_inBuffer.clear();
+ _socket->_inBuffer.clear();
StringTokenizer tokens(req.getURI(), "/?");
if (tokens.count() == 4)
@@ -89,7 +94,7 @@ public:
<< numberString;
;
std::string str = oss.str();
- T::_outBuffer.insert(T::_outBuffer.end(), str.begin(), str.end());
+ _socket->_outBuffer.insert(_socket->_outBuffer.end(), str.begin(), str.end());
}
else if (tokens.count() == 2 && tokens[1] == "ws")
{ // create our websocket goodness ...
@@ -106,7 +111,7 @@ public:
<< "Sec-Websocket-Accept: " << computeAccept(_wsKey) << "\r\n"
<< "\r\n";
std::string str = oss.str();
- T::_outBuffer.insert(T::_outBuffer.end(), str.begin(), str.end());
+ _socket->_outBuffer.insert(_socket->_outBuffer.end(), str.begin(), str.end());
_wsState = WEBSOCKET;
}
else
@@ -130,7 +135,7 @@ public:
virtual void handleIncomingMessage() override
{
- std::cerr << "incoming message with buffer size " << T::_inBuffer.size() << "\n";
+ std::cerr << "incoming message with buffer size " << _socket->_inBuffer.size() << "\n";
if (_wsState == HTTP)
{
handleHTTP();
@@ -138,11 +143,11 @@ public:
}
// websocket fun !
- size_t len = T::_inBuffer.size();
+ size_t len = _socket->_inBuffer.size();
if (len < 2) // partial read
return;
- unsigned char *p = reinterpret_cast<unsigned char*>(&T::_inBuffer[0]);
+ unsigned char *p = reinterpret_cast<unsigned char*>(&_socket->_inBuffer[0]);
bool fin = p[0] & 0x80;
WSOpCode code = static_cast<WSOpCode>(p[0] & 0x0f);
bool hasMask = p[1] & 0x80;
@@ -196,15 +201,15 @@ public:
} else
_wsPayload.insert(_wsPayload.end(), data, data + payloadLen);
- T::_inBuffer.erase(T::_inBuffer.begin(), T::_inBuffer.begin() + headerLen + payloadLen);
+ _socket->_inBuffer.erase(_socket->_inBuffer.begin(), _socket->_inBuffer.begin() + headerLen + payloadLen);
// FIXME: fin, aggregating payloads into _wsPayload etc.
handleWSMessage(fin, code, _wsPayload);
_wsPayload.clear();
}
- virtual void queueWSMessage(const std::vector<char> &data,
- WSOpCode code = WSOpCode::Binary)
+ void queueWSMessage(const std::vector<char> &data,
+ WSOpCode code = WSOpCode::Binary)
{
size_t len = data.size();
bool fin = false;
@@ -213,42 +218,42 @@ public:
unsigned char header[2];
header[0] = (fin ? 0x80 : 0) | static_cast<unsigned char>(code);
header[1] = mask ? 0x80 : 0;
- T::_outBuffer.push_back((char)header[0]);
+ _socket->_outBuffer.push_back((char)header[0]);
// no out-bound masking ...
if (len < 126)
{
header[1] |= len;
- T::_outBuffer.push_back((char)header[1]);
+ _socket->_outBuffer.push_back((char)header[1]);
}
else if (len <= 0xffff)
{
header[1] |= 126;
- T::_outBuffer.push_back((char)header[1]);
- T::_outBuffer.push_back(static_cast<char>((len >> 8) & 0xff));
- T::_outBuffer.push_back(static_cast<char>((len >> 0) & 0xff));
+ _socket->_outBuffer.push_back((char)header[1]);
+ _socket->_outBuffer.push_back(static_cast<char>((len >> 8) & 0xff));
+ _socket->_outBuffer.push_back(static_cast<char>((len >> 0) & 0xff));
}
else
{
header[1] |= 127;
- T::_outBuffer.push_back((char)header[1]);
- T::_outBuffer.push_back(static_cast<char>((len >> 56) & 0xff));
- T::_outBuffer.push_back(static_cast<char>((len >> 48) & 0xff));
- T::_outBuffer.push_back(static_cast<char>((len >> 40) & 0xff));
- T::_outBuffer.push_back(static_cast<char>((len >> 32) & 0xff));
- T::_outBuffer.push_back(static_cast<char>((len >> 24) & 0xff));
- T::_outBuffer.push_back(static_cast<char>((len >> 16) & 0xff));
- T::_outBuffer.push_back(static_cast<char>((len >> 8) & 0xff));
- T::_outBuffer.push_back(static_cast<char>((len >> 0) & 0xff));
+ _socket->_outBuffer.push_back((char)header[1]);
+ _socket->_outBuffer.push_back(static_cast<char>((len >> 56) & 0xff));
+ _socket->_outBuffer.push_back(static_cast<char>((len >> 48) & 0xff));
+ _socket->_outBuffer.push_back(static_cast<char>((len >> 40) & 0xff));
+ _socket->_outBuffer.push_back(static_cast<char>((len >> 32) & 0xff));
+ _socket->_outBuffer.push_back(static_cast<char>((len >> 24) & 0xff));
+ _socket->_outBuffer.push_back(static_cast<char>((len >> 16) & 0xff));
+ _socket->_outBuffer.push_back(static_cast<char>((len >> 8) & 0xff));
+ _socket->_outBuffer.push_back(static_cast<char>((len >> 0) & 0xff));
}
// FIXME: pick random number and mask in the outbuffer etc.
assert (!mask);
- T::_outBuffer.insert(T::_outBuffer.end(), data.begin(), data.end());
+ _socket->_outBuffer.insert(_socket->_outBuffer.end(), data.begin(), data.end());
}
- virtual void handleWSMessage( bool fin, WSOpCode code, std::vector<char> &data)
+ void handleWSMessage(bool fin, WSOpCode code, std::vector<char> &data)
{
std::cerr << "Message: fin? " << fin << " code " << code << " data size " << data.size();
if (code == WSOpCode::Text)
@@ -374,7 +379,7 @@ int main(int argc, const char**argv)
{
std::shared_ptr<Socket> create(const int fd) override
{
- return std::make_shared<SimpleResponseClient<StreamSocket>>(fd);
+ return std::make_shared<StreamSocket>(fd, new SimpleResponseClient());
}
};
@@ -382,7 +387,7 @@ int main(int argc, const char**argv)
{
std::shared_ptr<Socket> create(const int fd) override
{
- return std::make_shared<SimpleResponseClient<SslStreamSocket>>(fd);
+ return std::make_shared<SslStreamSocket>(fd, new SimpleResponseClient());
}
};
commit 46ca4050c4d4abc340e354890c933f6095587ef7
Author: Jan Holesovsky <kendy at collabora.com>
Date: Wed Feb 22 15:45:41 2017 +0100
nb: Let's avoid too much abstraction.
Change-Id: If349e6273580b09386ad0a89467a99c6c2c0d4ec
diff --git a/net/Socket.hpp b/net/Socket.hpp
index 5d4d617..779b526 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -283,8 +283,8 @@ private:
std::vector<pollfd> _pollFds;
};
-/// Abstract buffering socket.
-class BufferingSocket : public Socket
+/// A plain, non-blocking, data streaming socket.
+class StreamSocket : public Socket
{
public:
@@ -376,10 +376,16 @@ public:
}
/// Override to handle reading of socket data differently.
- virtual int readData(char* buf, int len) = 0;
+ virtual int readData(char* buf, int len)
+ {
+ return ::read(getFD(), buf, len);
+ }
/// Override to handle writing data to socket differently.
- virtual int writeData(const char* buf, const int len) = 0;
+ virtual int writeData(const char* buf, const int len)
+ {
+ return ::write(getFD(), buf, len);
+ }
int getPollEvents() override
{
@@ -388,7 +394,7 @@ public:
}
protected:
- BufferingSocket(const int fd) :
+ StreamSocket(const int fd) :
Socket(fd)
{
}
@@ -402,31 +408,6 @@ private:
virtual void handleIncomingMessage() = 0;
};
-/// A plain, non-blocking, data streaming socket.
-class StreamSocket : public BufferingSocket
-{
-protected:
- StreamSocket(const int fd) :
- BufferingSocket(fd)
- {
- }
-
- /// Override to handle reading of socket data differently.
- virtual int readData(char* buf, int len)
- {
- return ::read(getFD(), buf, len);
- }
-
- /// Override to handle writing data to socket differently.
- virtual int writeData(const char* buf, const int len)
- {
- return ::write(getFD(), buf, len);
- }
-
- // Will construct us upon accept.
- friend class ServerSocket;
-};
-
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/net/SslSocket.hpp b/net/SslSocket.hpp
index 220447b..8a9b1f0 100644
--- a/net/SslSocket.hpp
+++ b/net/SslSocket.hpp
@@ -18,7 +18,7 @@
#include "Socket.hpp"
/// An SSL/TSL, non-blocking, data streaming socket.
-class SslStreamSocket : public BufferingSocket
+class SslStreamSocket : public StreamSocket
{
public:
~SslStreamSocket()
@@ -46,7 +46,7 @@ public:
}
// Default implementation.
- return BufferingSocket::readIncomingData();
+ return StreamSocket::readIncomingData();
}
void writeOutgoingData() override
@@ -58,7 +58,7 @@ public:
}
// Default implementation.
- BufferingSocket::writeOutgoingData();
+ StreamSocket::writeOutgoingData();
}
virtual int readData(char* buf, int len)
@@ -86,12 +86,12 @@ public:
}
// Do the default.
- return BufferingSocket::getPollEvents();
+ return StreamSocket::getPollEvents();
}
protected:
SslStreamSocket(const int fd) :
- BufferingSocket(fd),
+ StreamSocket(fd),
_ssl(nullptr),
_sslWantsTo(SslWantsTo::ReadOrWrite),
_doHandshake(true)
More information about the Libreoffice-commits
mailing list