Squashed 'third_party/seasocks/' content from commit 016dc60
Change-Id: I195fa5bfd0c0e3cc66fbbefcc7b5170bafcf7a36
git-subtree-dir: third_party/seasocks
git-subtree-split: 016dc60b247e0d1d563aea6d22a9075e6884ab9f
diff --git a/src/main/c/seasocks/Connection.h b/src/main/c/seasocks/Connection.h
new file mode 100644
index 0000000..c1aa996
--- /dev/null
+++ b/src/main/c/seasocks/Connection.h
@@ -0,0 +1,177 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "seasocks/ResponseCode.h"
+#include "seasocks/WebSocket.h"
+
+#include <netinet/in.h>
+
+#include <sys/socket.h>
+
+#include <inttypes.h>
+#include <list>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace seasocks {
+
+class Logger;
+class ServerImpl;
+class PageRequest;
+class Response;
+
+class Connection : public WebSocket {
+public:
+ Connection(
+ std::shared_ptr<Logger> logger,
+ ServerImpl& server,
+ int fd,
+ const sockaddr_in& address);
+ virtual ~Connection();
+
+ bool write(const void* data, size_t size, bool flush);
+ void handleDataReadyForRead();
+ void handleDataReadyForWrite();
+
+ int getFd() const { return _fd; }
+
+ // From WebSocket.
+ virtual void send(const char* webSocketResponse) override;
+ virtual void send(const uint8_t* webSocketResponse, size_t length) override;
+ virtual void close() override;
+
+ // From Request.
+ virtual std::shared_ptr<Credentials> credentials() const override;
+ virtual const sockaddr_in& getRemoteAddress() const override { return _address; }
+ virtual const std::string& getRequestUri() const override;
+ virtual Request::Verb verb() const override { return Request::WebSocket; }
+ virtual size_t contentLength() const override { return 0; }
+ virtual const uint8_t* content() const override { return NULL; }
+ virtual bool hasHeader(const std::string&) const override;
+ virtual std::string getHeader(const std::string&) const override;
+
+ void setLinger();
+
+ size_t inputBufferSize() const { return _inBuf.size(); }
+ size_t outputBufferSize() const { return _outBuf.size(); }
+
+ size_t bytesReceived() const { return _bytesReceived; }
+ size_t bytesSent() const { return _bytesSent; }
+
+ // For testing:
+ std::vector<uint8_t>& getInputBuffer() { return _inBuf; }
+ void handleHixieWebSocket();
+ void handleHybiWebSocket();
+ void setHandler(std::shared_ptr<WebSocket::Handler> handler) {
+ _webSocketHandler = handler;
+ }
+ void handleNewData();
+
+private:
+ void finalise();
+ bool closed() const;
+
+ void closeWhenEmpty();
+ void closeInternal();
+
+ void handleHeaders();
+ void handleWebSocketKey3();
+ void handleWebSocketTextMessage(const char* message);
+ void handleWebSocketBinaryMessage(const std::vector<uint8_t>& message);
+ void handleBufferingPostData();
+ bool handlePageRequest();
+
+ bool bufferLine(const char* line);
+ bool bufferLine(const std::string& line);
+ bool flush();
+
+ bool handleHybiHandshake(int webSocketVersion, const std::string& webSocketKey);
+
+ // Send an error document. Returns 'true' for convenience in handle*() routines.
+ bool sendError(ResponseCode errorCode, const std::string& document);
+
+ // Send individual errors. Again all return true for convenience.
+ bool sendUnsupportedError(const std::string& reason);
+ bool send404();
+ bool sendBadRequest(const std::string& reason);
+ bool sendISE(const std::string& error);
+
+ void sendHybi(int opcode, const uint8_t* webSocketResponse, size_t messageLength);
+
+ bool sendResponse(std::shared_ptr<Response> response);
+
+ bool processHeaders(uint8_t* first, uint8_t* last);
+ bool sendData(const std::string& type, const char* start, size_t size);
+
+ struct Range {
+ long start;
+ long end;
+ size_t length() const { return end - start + 1; }
+ };
+
+ bool parseRange(const std::string& rangeStr, Range& range) const;
+ bool parseRanges(const std::string& range, std::list<Range>& ranges) const;
+ bool sendStaticData();
+
+ int safeSend(const void* data, size_t size);
+
+ void bufferResponseAndCommonHeaders(ResponseCode code);
+
+ std::list<Range> processRangesForStaticData(const std::list<Range>& ranges, long fileSize);
+
+ std::shared_ptr<Logger> _logger;
+ ServerImpl &_server;
+ int _fd;
+ bool _shutdown;
+ bool _hadSendError;
+ bool _closeOnEmpty;
+ bool _registeredForWriteEvents;
+ sockaddr_in _address;
+ size_t _bytesSent;
+ size_t _bytesReceived;
+ std::vector<uint8_t> _inBuf;
+ std::vector<uint8_t> _outBuf;
+ std::shared_ptr<WebSocket::Handler> _webSocketHandler;
+ bool _shutdownByUser;
+ std::unique_ptr<PageRequest> _request;
+
+ enum State {
+ INVALID,
+ READING_HEADERS,
+ READING_WEBSOCKET_KEY3,
+ HANDLING_HIXIE_WEBSOCKET,
+ HANDLING_HYBI_WEBSOCKET,
+ BUFFERING_POST_DATA,
+ };
+ State _state;
+
+ Connection(Connection& other) = delete;
+ Connection& operator =(Connection& other) = delete;
+};
+
+} // namespace seasocks