blob: c1aa9968fcb882bc67a54dccf31bb79dde35b133 [file] [log] [blame]
Austin Schuh24adb6b2015-09-06 17:37:40 -07001// Copyright (c) 2013, Matt Godbolt
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// Redistributions of source code must retain the above copyright notice, this
8// list of conditions and the following disclaimer.
9//
10// Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13//
14// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24// POSSIBILITY OF SUCH DAMAGE.
25
26#pragma once
27
28#include "seasocks/ResponseCode.h"
29#include "seasocks/WebSocket.h"
30
31#include <netinet/in.h>
32
33#include <sys/socket.h>
34
35#include <inttypes.h>
36#include <list>
37#include <memory>
38#include <string>
39#include <vector>
40
41namespace seasocks {
42
43class Logger;
44class ServerImpl;
45class PageRequest;
46class Response;
47
48class Connection : public WebSocket {
49public:
50 Connection(
51 std::shared_ptr<Logger> logger,
52 ServerImpl& server,
53 int fd,
54 const sockaddr_in& address);
55 virtual ~Connection();
56
57 bool write(const void* data, size_t size, bool flush);
58 void handleDataReadyForRead();
59 void handleDataReadyForWrite();
60
61 int getFd() const { return _fd; }
62
63 // From WebSocket.
64 virtual void send(const char* webSocketResponse) override;
65 virtual void send(const uint8_t* webSocketResponse, size_t length) override;
66 virtual void close() override;
67
68 // From Request.
69 virtual std::shared_ptr<Credentials> credentials() const override;
70 virtual const sockaddr_in& getRemoteAddress() const override { return _address; }
71 virtual const std::string& getRequestUri() const override;
72 virtual Request::Verb verb() const override { return Request::WebSocket; }
73 virtual size_t contentLength() const override { return 0; }
74 virtual const uint8_t* content() const override { return NULL; }
75 virtual bool hasHeader(const std::string&) const override;
76 virtual std::string getHeader(const std::string&) const override;
77
78 void setLinger();
79
80 size_t inputBufferSize() const { return _inBuf.size(); }
81 size_t outputBufferSize() const { return _outBuf.size(); }
82
83 size_t bytesReceived() const { return _bytesReceived; }
84 size_t bytesSent() const { return _bytesSent; }
85
86 // For testing:
87 std::vector<uint8_t>& getInputBuffer() { return _inBuf; }
88 void handleHixieWebSocket();
89 void handleHybiWebSocket();
90 void setHandler(std::shared_ptr<WebSocket::Handler> handler) {
91 _webSocketHandler = handler;
92 }
93 void handleNewData();
94
95private:
96 void finalise();
97 bool closed() const;
98
99 void closeWhenEmpty();
100 void closeInternal();
101
102 void handleHeaders();
103 void handleWebSocketKey3();
104 void handleWebSocketTextMessage(const char* message);
105 void handleWebSocketBinaryMessage(const std::vector<uint8_t>& message);
106 void handleBufferingPostData();
107 bool handlePageRequest();
108
109 bool bufferLine(const char* line);
110 bool bufferLine(const std::string& line);
111 bool flush();
112
113 bool handleHybiHandshake(int webSocketVersion, const std::string& webSocketKey);
114
115 // Send an error document. Returns 'true' for convenience in handle*() routines.
116 bool sendError(ResponseCode errorCode, const std::string& document);
117
118 // Send individual errors. Again all return true for convenience.
119 bool sendUnsupportedError(const std::string& reason);
120 bool send404();
121 bool sendBadRequest(const std::string& reason);
122 bool sendISE(const std::string& error);
123
124 void sendHybi(int opcode, const uint8_t* webSocketResponse, size_t messageLength);
125
126 bool sendResponse(std::shared_ptr<Response> response);
127
128 bool processHeaders(uint8_t* first, uint8_t* last);
129 bool sendData(const std::string& type, const char* start, size_t size);
130
131 struct Range {
132 long start;
133 long end;
134 size_t length() const { return end - start + 1; }
135 };
136
137 bool parseRange(const std::string& rangeStr, Range& range) const;
138 bool parseRanges(const std::string& range, std::list<Range>& ranges) const;
139 bool sendStaticData();
140
141 int safeSend(const void* data, size_t size);
142
143 void bufferResponseAndCommonHeaders(ResponseCode code);
144
145 std::list<Range> processRangesForStaticData(const std::list<Range>& ranges, long fileSize);
146
147 std::shared_ptr<Logger> _logger;
148 ServerImpl &_server;
149 int _fd;
150 bool _shutdown;
151 bool _hadSendError;
152 bool _closeOnEmpty;
153 bool _registeredForWriteEvents;
154 sockaddr_in _address;
155 size_t _bytesSent;
156 size_t _bytesReceived;
157 std::vector<uint8_t> _inBuf;
158 std::vector<uint8_t> _outBuf;
159 std::shared_ptr<WebSocket::Handler> _webSocketHandler;
160 bool _shutdownByUser;
161 std::unique_ptr<PageRequest> _request;
162
163 enum State {
164 INVALID,
165 READING_HEADERS,
166 READING_WEBSOCKET_KEY3,
167 HANDLING_HIXIE_WEBSOCKET,
168 HANDLING_HYBI_WEBSOCKET,
169 BUFFERING_POST_DATA,
170 };
171 State _state;
172
173 Connection(Connection& other) = delete;
174 Connection& operator =(Connection& other) = delete;
175};
176
177} // namespace seasocks