1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
#pragma once
#include <Task.h>
#include <StacklessTask.h>
#include <BStream.h>
#include <HttpServer.h>
namespace Balau {
class WebSocketActionBase;
class WebSocketWorker : public StacklessTask {
public:
virtual bool parse(Http::Request & req) { return true; }
protected:
WebSocketWorker(IO<Handle> socket, const String & url) : m_socket(new BStream(socket)) { m_name = String("WebSocket:") + url + "/" + m_socket->getName(); }
~WebSocketWorker() { free(m_payload); }
private:
void processMessage();
const char * getName() const { return m_name.to_charp(); }
void Do();
String m_name;
IO<BStream> m_socket;
enum {
READ_H,
READ_PLB,
READ_PLL,
READ_MK,
READ_PL,
} m_status = READ_H;
enum { MAX_WEBSOCKET_LIMIT = 4 * 1024 * 1024 };
uint8_t * m_payload = NULL;
uint64_t m_payloadLen;
uint64_t m_totalLen;
uint64_t m_remainingBytes;
uint32_t m_mask;
uint8_t m_opcode;
bool m_hasMask;
bool m_fin;
bool m_firstFragment = true;
bool m_enforceServer = false;
bool m_enforceClient = false;
friend class WebSocketActionBase;
};
class WebSocketServerBase : public HttpServer::Action {
protected:
WebSocketServerBase(const Regex & regex) : Action(regex) { }
virtual WebSocketWorker * spawnWorker(IO<Handle> socket, const String & url) = 0;
private:
void sendError(IO<Handle> out, const char * serverName);
bool Do(HttpServer * server, Http::Request & req, HttpServer::Action::ActionMatch & match, IO<Handle> out) throw (GeneralException);
};
template<class T>
class WebSocketServer : public WebSocketServerBase {
protected:
WebSocketServer(const Regex & regex) : WebSocketServerBase(regex) { }
virtual WebSocketWorker * spawnWorker(IO<Handle> socket, const String & url) { return new T(socket, url); }
};
};
|