2017-02-11 11:13:31 -06:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2017-02-12 14:54:49 -06:00
|
|
|
#include <atomic>
|
2017-02-11 11:13:31 -06:00
|
|
|
#include <cerrno>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
|
|
|
#include <iostream>
|
|
|
|
#include <mutex>
|
|
|
|
#include <thread>
|
2017-02-14 05:10:52 -06:00
|
|
|
#include <assert.h>
|
2017-02-11 11:13:31 -06:00
|
|
|
|
2017-02-16 05:00:38 -06:00
|
|
|
#include <Poco/MemoryStream.h>
|
2017-02-11 11:13:31 -06:00
|
|
|
#include <Poco/Net/SocketAddress.h>
|
2017-02-16 05:00:38 -06:00
|
|
|
#include <Poco/Net/HTTPRequest.h>
|
|
|
|
#include <Poco/StringTokenizer.h>
|
2017-02-16 05:52:22 -06:00
|
|
|
#include <Poco/Runnable.h>
|
|
|
|
#include <Poco/Thread.h>
|
2017-02-16 05:00:38 -06:00
|
|
|
|
|
|
|
using Poco::MemoryInputStream;
|
|
|
|
using Poco::StringTokenizer;
|
2017-02-11 11:13:31 -06:00
|
|
|
|
2017-02-21 19:43:51 -06:00
|
|
|
#include "Socket.hpp"
|
2017-02-21 20:49:29 -06:00
|
|
|
#include "ServerSocket.hpp"
|
2017-02-21 19:54:13 -06:00
|
|
|
#include "SslSocket.hpp"
|
2017-02-11 11:13:31 -06:00
|
|
|
|
2017-02-17 17:13:52 -06:00
|
|
|
constexpr int HttpPortNumber = 9191;
|
|
|
|
constexpr int SslPortNumber = 9193;
|
2017-02-11 14:13:14 -06:00
|
|
|
|
2017-02-16 12:49:31 -06:00
|
|
|
static std::string computeAccept(const std::string &key);
|
|
|
|
|
2017-02-23 06:14:01 -06:00
|
|
|
class WebSocketHandler : public SocketHandlerInterface
|
2017-02-14 17:45:24 -06:00
|
|
|
{
|
2017-02-22 10:12:12 -06:00
|
|
|
std::unique_ptr<StreamSocket> _socket;
|
2017-02-16 11:49:03 -06:00
|
|
|
int _wsVersion;
|
|
|
|
std::string _wsKey;
|
|
|
|
std::string _wsProtocol;
|
2017-02-16 12:49:31 -06:00
|
|
|
std::vector<char> _wsPayload;
|
|
|
|
enum { HTTP, WEBSOCKET } _wsState;
|
2017-02-16 11:49:03 -06:00
|
|
|
|
2017-02-14 17:45:24 -06:00
|
|
|
public:
|
2017-02-23 06:14:01 -06:00
|
|
|
WebSocketHandler() :
|
2017-02-16 12:49:31 -06:00
|
|
|
_wsVersion(0),
|
|
|
|
_wsState(HTTP)
|
2017-02-14 17:45:24 -06:00
|
|
|
{
|
|
|
|
}
|
2017-02-22 10:12:12 -06:00
|
|
|
|
2017-02-23 06:14:01 -06:00
|
|
|
/// Implementation of the SocketHandlerInterface.
|
2017-02-22 10:12:12 -06:00
|
|
|
virtual void setSocket(StreamSocket* socket) override
|
|
|
|
{
|
|
|
|
_socket.reset(socket);
|
|
|
|
}
|
|
|
|
|
2017-02-23 06:14:01 -06:00
|
|
|
void handleWebsocketUpgrade()
|
2017-02-14 17:45:24 -06:00
|
|
|
{
|
2017-02-16 05:00:38 -06:00
|
|
|
int number = 0;
|
2017-02-22 10:12:12 -06:00
|
|
|
MemoryInputStream message(&_socket->_inBuffer[0], _socket->_inBuffer.size());
|
2017-02-16 05:00:38 -06:00
|
|
|
Poco::Net::HTTPRequest req;
|
|
|
|
req.read(message);
|
|
|
|
|
2017-02-16 11:49:03 -06:00
|
|
|
// if we succeeded - remove that from our input buffer
|
2017-02-20 22:13:11 -06:00
|
|
|
// FIXME: We should check if this is GET or POST. For GET, we only
|
|
|
|
// can have a single request (headers only). For POST, we can/should
|
|
|
|
// 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.
|
2017-02-22 10:12:12 -06:00
|
|
|
_socket->_inBuffer.clear();
|
2017-02-16 11:49:03 -06:00
|
|
|
|
2017-02-16 05:00:38 -06:00
|
|
|
StringTokenizer tokens(req.getURI(), "/?");
|
|
|
|
if (tokens.count() == 4)
|
2017-02-16 04:14:08 -06:00
|
|
|
{
|
2017-02-16 05:00:38 -06:00
|
|
|
std::string subpool = tokens[2];
|
|
|
|
number = std::stoi(tokens[3]);
|
2017-02-16 11:49:03 -06:00
|
|
|
|
|
|
|
// complex algorithmic core:
|
|
|
|
number = number + 1;
|
|
|
|
|
|
|
|
std::string numberString = std::to_string(number);
|
|
|
|
std::ostringstream oss;
|
|
|
|
oss << "HTTP/1.1 200 OK\r\n"
|
|
|
|
<< "Date: Once, Upon a time GMT\r\n" // Mon, 27 Jul 2009 12:28:53 GMT
|
|
|
|
<< "Server: madeup string (Linux)\r\n"
|
|
|
|
<< "Content-Length: " << numberString.size() << "\r\n"
|
|
|
|
<< "Content-Type: text/plain\r\n"
|
|
|
|
<< "Connection: Closed\r\n"
|
|
|
|
<< "\r\n"
|
|
|
|
<< numberString;
|
|
|
|
;
|
|
|
|
std::string str = oss.str();
|
2017-02-22 10:12:12 -06:00
|
|
|
_socket->_outBuffer.insert(_socket->_outBuffer.end(), str.begin(), str.end());
|
2017-02-16 11:49:03 -06:00
|
|
|
}
|
|
|
|
else if (tokens.count() == 2 && tokens[1] == "ws")
|
|
|
|
{ // create our websocket goodness ...
|
|
|
|
_wsVersion = std::stoi(req.get("Sec-WebSocket-Version", "13"));
|
|
|
|
_wsKey = req.get("Sec-WebSocket-Key", "");
|
|
|
|
_wsProtocol = req.get("Sec-WebSocket-Protocol", "chat");
|
|
|
|
std::cerr << "version " << _wsVersion << " key '" << _wsKey << "\n";
|
|
|
|
// FIXME: other sanity checks ...
|
|
|
|
|
|
|
|
std::ostringstream oss;
|
|
|
|
oss << "HTTP/1.1 101 Switching Protocols\r\n"
|
|
|
|
<< "Upgrade: websocket\r\n"
|
|
|
|
<< "Connection: Upgrade\r\n"
|
2017-02-16 12:49:31 -06:00
|
|
|
<< "Sec-Websocket-Accept: " << computeAccept(_wsKey) << "\r\n"
|
2017-02-16 11:49:03 -06:00
|
|
|
<< "\r\n";
|
|
|
|
std::string str = oss.str();
|
2017-02-22 10:12:12 -06:00
|
|
|
_socket->_outBuffer.insert(_socket->_outBuffer.end(), str.begin(), str.end());
|
2017-02-16 12:49:31 -06:00
|
|
|
_wsState = WEBSOCKET;
|
2017-02-16 04:14:08 -06:00
|
|
|
}
|
2017-02-16 05:00:38 -06:00
|
|
|
else
|
|
|
|
std::cerr << " unknown tokens " << tokens.count() << std::endl;
|
2017-02-14 17:45:24 -06:00
|
|
|
}
|
2017-02-16 12:49:31 -06:00
|
|
|
|
|
|
|
enum WSOpCode {
|
|
|
|
Continuation, // 0x0
|
|
|
|
Text, // 0x1
|
|
|
|
Binary, // 0x2
|
|
|
|
Reserved1, // 0x3
|
|
|
|
Reserved2, // 0x4
|
|
|
|
Reserved3, // 0x5
|
|
|
|
Reserved4, // 0x6
|
|
|
|
Reserved5, // 0x7
|
|
|
|
Close, // 0x8
|
|
|
|
Ping, // 0x9
|
|
|
|
Pong // 0xa
|
|
|
|
// ... reserved
|
|
|
|
};
|
|
|
|
|
2017-02-23 06:14:01 -06:00
|
|
|
/// Implementation of the SocketHandlerInterface.
|
2017-02-16 12:49:31 -06:00
|
|
|
virtual void handleIncomingMessage() override
|
|
|
|
{
|
2017-02-22 10:12:12 -06:00
|
|
|
std::cerr << "incoming message with buffer size " << _socket->_inBuffer.size() << "\n";
|
2017-02-16 12:49:31 -06:00
|
|
|
if (_wsState == HTTP)
|
|
|
|
{
|
2017-02-23 06:14:01 -06:00
|
|
|
handleWebsocketUpgrade();
|
2017-02-16 12:49:31 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// websocket fun !
|
2017-02-22 10:12:12 -06:00
|
|
|
size_t len = _socket->_inBuffer.size();
|
2017-02-16 12:49:31 -06:00
|
|
|
if (len < 2) // partial read
|
|
|
|
return;
|
|
|
|
|
2017-02-22 10:12:12 -06:00
|
|
|
unsigned char *p = reinterpret_cast<unsigned char*>(&_socket->_inBuffer[0]);
|
2017-02-17 18:58:49 -06:00
|
|
|
bool fin = p[0] & 0x80;
|
|
|
|
WSOpCode code = static_cast<WSOpCode>(p[0] & 0x0f);
|
|
|
|
bool hasMask = p[1] & 0x80;
|
|
|
|
size_t payloadLen = p[1] & 0x7f;
|
|
|
|
size_t headerLen = 2;
|
2017-02-16 12:49:31 -06:00
|
|
|
|
2017-02-17 18:58:49 -06:00
|
|
|
// normally - 7 bit length.
|
2017-02-16 12:49:31 -06:00
|
|
|
if (payloadLen == 126) // 2 byte length
|
|
|
|
{
|
|
|
|
if (len < 2 + 2)
|
|
|
|
return;
|
2017-02-19 02:01:42 -06:00
|
|
|
|
|
|
|
payloadLen = (((unsigned)p[2]) << 8) | ((unsigned)p[3]);
|
2017-02-17 18:58:49 -06:00
|
|
|
headerLen += 2;
|
2017-02-16 12:49:31 -06:00
|
|
|
}
|
|
|
|
else if (payloadLen == 127) // 8 byte length
|
|
|
|
{
|
|
|
|
if (len < 2 + 8)
|
|
|
|
return;
|
2017-02-19 19:54:50 -06:00
|
|
|
|
|
|
|
payloadLen = ((((uint64_t)(p[9])) << 0) + (((uint64_t)(p[8])) << 8) +
|
|
|
|
(((uint64_t)(p[7])) << 16) + (((uint64_t)(p[6])) << 24) +
|
|
|
|
(((uint64_t)(p[5])) << 32) + (((uint64_t)(p[4])) << 40) +
|
|
|
|
(((uint64_t)(p[3])) << 48) + (((uint64_t)(p[2])) << 56));
|
2017-02-17 18:58:49 -06:00
|
|
|
// FIXME: crop read length to remove top / sign bits.
|
|
|
|
headerLen += 8;
|
2017-02-16 12:49:31 -06:00
|
|
|
}
|
2017-02-17 18:58:49 -06:00
|
|
|
|
2017-02-19 02:01:42 -06:00
|
|
|
unsigned char *data, *mask;
|
2017-02-17 18:58:49 -06:00
|
|
|
|
|
|
|
if (hasMask)
|
2017-02-16 12:49:31 -06:00
|
|
|
{
|
2017-02-17 18:58:49 -06:00
|
|
|
mask = p + headerLen;
|
|
|
|
headerLen += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (payloadLen + headerLen > len)
|
|
|
|
{ // partial read wait for more data.
|
|
|
|
return;
|
2017-02-16 12:49:31 -06:00
|
|
|
}
|
2017-02-16 15:57:18 -06:00
|
|
|
|
2017-02-17 18:58:49 -06:00
|
|
|
data = p + headerLen;
|
|
|
|
|
2017-02-16 15:57:18 -06:00
|
|
|
if (hasMask)
|
|
|
|
{
|
2017-02-19 02:02:26 -06:00
|
|
|
for (size_t i = 0; i < payloadLen; ++i)
|
2017-02-16 15:57:18 -06:00
|
|
|
data[i] = data[i] ^ mask[i % 4];
|
|
|
|
|
|
|
|
// FIXME: copy and un-mask at the same time ...
|
2017-02-17 18:58:49 -06:00
|
|
|
_wsPayload.insert(_wsPayload.end(), data, data + payloadLen);
|
2017-02-16 15:57:18 -06:00
|
|
|
} else
|
2017-02-17 18:58:49 -06:00
|
|
|
_wsPayload.insert(_wsPayload.end(), data, data + payloadLen);
|
|
|
|
|
2017-02-22 10:12:12 -06:00
|
|
|
_socket->_inBuffer.erase(_socket->_inBuffer.begin(), _socket->_inBuffer.begin() + headerLen + payloadLen);
|
2017-02-17 18:58:49 -06:00
|
|
|
|
2017-02-16 12:49:31 -06:00
|
|
|
// FIXME: fin, aggregating payloads into _wsPayload etc.
|
2017-02-23 06:14:01 -06:00
|
|
|
handleMessage(fin, code, _wsPayload);
|
2017-02-16 12:49:31 -06:00
|
|
|
_wsPayload.clear();
|
|
|
|
}
|
|
|
|
|
2017-02-23 06:14:01 -06:00
|
|
|
void sendMessage(const std::vector<char> &data,
|
2017-02-22 10:12:12 -06:00
|
|
|
WSOpCode code = WSOpCode::Binary)
|
2017-02-16 15:57:18 -06:00
|
|
|
{
|
|
|
|
size_t len = data.size();
|
|
|
|
bool fin = false;
|
|
|
|
bool mask = false;
|
|
|
|
|
|
|
|
unsigned char header[2];
|
|
|
|
header[0] = (fin ? 0x80 : 0) | static_cast<unsigned char>(code);
|
|
|
|
header[1] = mask ? 0x80 : 0;
|
2017-02-22 10:12:12 -06:00
|
|
|
_socket->_outBuffer.push_back((char)header[0]);
|
2017-02-16 15:57:18 -06:00
|
|
|
|
|
|
|
// no out-bound masking ...
|
|
|
|
if (len < 126)
|
|
|
|
{
|
|
|
|
header[1] |= len;
|
2017-02-22 10:12:12 -06:00
|
|
|
_socket->_outBuffer.push_back((char)header[1]);
|
2017-02-16 15:57:18 -06:00
|
|
|
}
|
|
|
|
else if (len <= 0xffff)
|
|
|
|
{
|
|
|
|
header[1] |= 126;
|
2017-02-22 10:12:12 -06:00
|
|
|
_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));
|
2017-02-16 15:57:18 -06:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
header[1] |= 127;
|
2017-02-22 10:12:12 -06:00
|
|
|
_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));
|
2017-02-16 15:57:18 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: pick random number and mask in the outbuffer etc.
|
|
|
|
assert (!mask);
|
|
|
|
|
2017-02-22 10:12:12 -06:00
|
|
|
_socket->_outBuffer.insert(_socket->_outBuffer.end(), data.begin(), data.end());
|
2017-02-16 15:57:18 -06:00
|
|
|
}
|
|
|
|
|
2017-02-23 06:14:01 -06:00
|
|
|
virtual void handleMessage(bool fin, WSOpCode code, std::vector<char> &data) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
class SimpleResponseClient : public WebSocketHandler
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SimpleResponseClient() : WebSocketHandler()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void handleMessage(bool fin, WSOpCode code, std::vector<char> &data) override
|
2017-02-16 12:49:31 -06:00
|
|
|
{
|
2017-02-17 18:58:49 -06:00
|
|
|
std::cerr << "Message: fin? " << fin << " code " << code << " data size " << data.size();
|
|
|
|
if (code == WSOpCode::Text)
|
|
|
|
{
|
|
|
|
std::string text(data.begin(), data.end());
|
|
|
|
std::cerr << " text is '" << text << "'\n";
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
std::cerr << " binary\n";
|
2017-02-16 15:57:18 -06:00
|
|
|
|
|
|
|
std::vector<char> reply;
|
2017-02-19 11:06:45 -06:00
|
|
|
if (data.size() == sizeof(size_t))
|
|
|
|
{
|
|
|
|
// ping pong test
|
|
|
|
assert (data.size() >= sizeof(size_t));
|
|
|
|
size_t *countPtr = reinterpret_cast<size_t *>(&data[0]);
|
|
|
|
size_t count = *countPtr;
|
|
|
|
count++;
|
|
|
|
std::cerr << "count is " << count << "\n";
|
|
|
|
reply.insert(reply.end(), reinterpret_cast<char *>(&count),
|
|
|
|
reinterpret_cast<char *>(&count) + sizeof(count));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// echo tests
|
|
|
|
reply.insert(reply.end(), data.begin(), data.end());
|
|
|
|
}
|
|
|
|
|
2017-02-23 06:14:01 -06:00
|
|
|
sendMessage(reply);
|
2017-02-16 12:49:31 -06:00
|
|
|
}
|
2017-02-14 17:45:24 -06:00
|
|
|
};
|
|
|
|
|
2017-02-16 05:52:22 -06:00
|
|
|
// FIXME: use Poco Thread instead (?)
|
|
|
|
|
2017-02-12 14:54:49 -06:00
|
|
|
/// Generic thread class.
|
|
|
|
class Thread
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Thread(const std::function<void(std::atomic<bool>&)>& cb) :
|
|
|
|
_cb(cb),
|
|
|
|
_stop(false)
|
|
|
|
{
|
|
|
|
_thread = std::thread([this]() { _cb(_stop); });
|
|
|
|
}
|
|
|
|
|
|
|
|
Thread(Thread&& other) = delete;
|
|
|
|
const Thread& operator=(Thread&& other) = delete;
|
|
|
|
|
|
|
|
~Thread()
|
|
|
|
{
|
|
|
|
stop();
|
|
|
|
if (_thread.joinable())
|
|
|
|
{
|
|
|
|
_thread.join();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void stop()
|
|
|
|
{
|
|
|
|
_stop = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
const std::function<void(std::atomic<bool>&)> _cb;
|
|
|
|
std::atomic<bool> _stop;
|
|
|
|
std::thread _thread;
|
|
|
|
};
|
|
|
|
|
2017-02-17 17:13:52 -06:00
|
|
|
Poco::Net::SocketAddress addrHttp("127.0.0.1", HttpPortNumber);
|
|
|
|
Poco::Net::SocketAddress addrSsl("127.0.0.1", SslPortNumber);
|
2017-02-13 19:55:01 -06:00
|
|
|
|
2017-02-21 20:49:29 -06:00
|
|
|
void server(const Poco::Net::SocketAddress& addr, SocketPoll& clientPoller,
|
|
|
|
std::unique_ptr<SocketFactory> sockFactory)
|
2017-02-13 19:55:01 -06:00
|
|
|
{
|
|
|
|
// Start server.
|
2017-02-21 20:49:29 -06:00
|
|
|
auto server = std::make_shared<ServerSocket>(clientPoller, std::move(sockFactory));
|
2017-02-13 19:55:01 -06:00
|
|
|
if (!server->bind(addr))
|
|
|
|
{
|
|
|
|
const std::string msg = "Failed to bind. (errno: ";
|
|
|
|
throw std::runtime_error(msg + std::strerror(errno) + ")");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!server->listen())
|
|
|
|
{
|
|
|
|
const std::string msg = "Failed to listen. (errno: ";
|
|
|
|
throw std::runtime_error(msg + std::strerror(errno) + ")");
|
|
|
|
}
|
|
|
|
|
2017-02-15 08:48:48 -06:00
|
|
|
SocketPoll serverPoll;
|
|
|
|
|
|
|
|
serverPoll.insertNewSocket(server);
|
|
|
|
|
2017-02-13 19:55:01 -06:00
|
|
|
std::cout << "Listening." << std::endl;
|
|
|
|
for (;;)
|
|
|
|
{
|
2017-02-15 08:48:48 -06:00
|
|
|
serverPoll.poll(30000);
|
2017-02-13 19:55:01 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-20 16:14:55 -06:00
|
|
|
int main(int argc, const char**argv)
|
2017-02-13 20:25:54 -06:00
|
|
|
{
|
2017-02-16 23:30:29 -06:00
|
|
|
// TODO: These would normally come from config.
|
|
|
|
SslContext::initialize("/etc/loolwsd/cert.pem",
|
|
|
|
"/etc/loolwsd/key.pem",
|
|
|
|
"/etc/loolwsd/ca-chain.cert.pem");
|
|
|
|
|
2017-02-12 14:54:49 -06:00
|
|
|
// Used to poll client sockets.
|
2017-02-15 08:48:48 -06:00
|
|
|
SocketPoll poller;
|
2017-02-12 14:54:49 -06:00
|
|
|
|
|
|
|
// Start the client polling thread.
|
|
|
|
Thread threadPoll([&poller](std::atomic<bool>& stop)
|
|
|
|
{
|
2017-02-16 08:14:12 -06:00
|
|
|
while (!stop)
|
|
|
|
{
|
|
|
|
poller.poll(5000);
|
|
|
|
}
|
2017-02-12 14:54:49 -06:00
|
|
|
});
|
|
|
|
|
2017-02-21 20:49:29 -06:00
|
|
|
class PlainSocketFactory : public SocketFactory
|
|
|
|
{
|
|
|
|
std::shared_ptr<Socket> create(const int fd) override
|
|
|
|
{
|
2017-02-22 10:12:12 -06:00
|
|
|
return std::make_shared<StreamSocket>(fd, new SimpleResponseClient());
|
2017-02-21 20:49:29 -06:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class SslSocketFactory : public SocketFactory
|
|
|
|
{
|
|
|
|
std::shared_ptr<Socket> create(const int fd) override
|
|
|
|
{
|
2017-02-22 10:12:12 -06:00
|
|
|
return std::make_shared<SslStreamSocket>(fd, new SimpleResponseClient());
|
2017-02-21 20:49:29 -06:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-02-13 20:25:54 -06:00
|
|
|
// Start the server.
|
2017-02-20 16:14:55 -06:00
|
|
|
if (!strcmp(argv[argc-1], "ssl"))
|
2017-02-21 20:49:29 -06:00
|
|
|
server(addrSsl, poller, std::unique_ptr<SocketFactory>{new SslSocketFactory});
|
2017-02-20 16:14:55 -06:00
|
|
|
else
|
2017-02-21 20:49:29 -06:00
|
|
|
server(addrHttp, poller, std::unique_ptr<SocketFactory>{new PlainSocketFactory});
|
2017-02-11 17:21:57 -06:00
|
|
|
|
2017-02-12 14:54:49 -06:00
|
|
|
std::cout << "Shutting down server." << std::endl;
|
|
|
|
|
|
|
|
threadPoll.stop();
|
2017-02-12 13:44:14 -06:00
|
|
|
|
2017-02-16 23:30:29 -06:00
|
|
|
SslContext::uninitialize();
|
2017-02-11 11:13:31 -06:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-02-16 12:49:31 -06:00
|
|
|
// Saves writing this ourselves:
|
|
|
|
|
|
|
|
#include <Poco/Net/WebSocket.h>
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
#include <Poco/Net/WebSocket.h>
|
|
|
|
struct Puncture : private Poco::Net::WebSocket {
|
|
|
|
static std::string doComputeAccept(const std::string &key)
|
|
|
|
{
|
|
|
|
return computeAccept(key);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::string computeAccept(const std::string &key)
|
|
|
|
{
|
|
|
|
return Puncture::doComputeAccept(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-11 11:13:31 -06:00
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|