1 // 2 // Copyright (C) 2020 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 #pragma once 17 18 #include <deque> 19 #include <string> 20 #include <vector> 21 22 struct lws; 23 24 namespace cuttlefish { 25 26 class WebSocketHandler { 27 public: 28 WebSocketHandler(struct lws* wsi); 29 virtual ~WebSocketHandler() = default; 30 31 virtual void OnReceive(const uint8_t* msg, size_t len, bool binary) = 0; OnReceive(const uint8_t * msg,size_t len,bool binary,bool is_final)32 virtual void OnReceive(const uint8_t* msg, size_t len, bool binary, 33 [[maybe_unused]] bool is_final) { 34 OnReceive(msg, len, binary); 35 } 36 virtual void OnConnected() = 0; 37 virtual void OnClosed() = 0; 38 39 void EnqueueMessage(const uint8_t* data, size_t len, bool binary = false); 40 void EnqueueMessage(const char* data, size_t len, bool binary = false) { 41 EnqueueMessage(reinterpret_cast<const uint8_t*>(data), len, binary); 42 } 43 void Close(); 44 bool OnWritable(); 45 46 private: 47 struct WsBuffer { WsBufferWsBuffer48 WsBuffer(std::vector<uint8_t> data, bool binary) 49 : data(std::move(data)), binary(binary) {} 50 std::vector<uint8_t> data; 51 bool binary; 52 }; 53 54 void WriteWsBuffer(WsBuffer& ws_buffer); 55 56 struct lws* wsi_; 57 bool close_ = false; 58 std::deque<WsBuffer> buffer_queue_; 59 }; 60 61 class WebSocketHandlerFactory { 62 public: 63 virtual ~WebSocketHandlerFactory() = default; 64 virtual std::shared_ptr<WebSocketHandler> Build(struct lws* wsi) = 0; 65 }; 66 67 class WebSocketServer; 68 69 enum class HttpStatusCode : int { 70 // From https://developer.mozilla.org/en-US/docs/Web/HTTP/Status 71 Ok = 200, 72 NoContent = 204, 73 BadRequest = 400, 74 Unauthorized = 401, 75 NotFound = 404, 76 MethodNotAllowed = 405, 77 Conflict = 409, 78 }; 79 80 class DynHandler { 81 public: 82 DynHandler(struct lws* wsi); 83 84 virtual ~DynHandler() = default; 85 // TODO (jemoreira): Allow more than just JSON replies 86 // TODO (jemoreira): Receive request parameters 87 // Handle a GET request. 88 virtual HttpStatusCode DoGet() = 0; 89 // Handle a POST request. 90 virtual HttpStatusCode DoPost() = 0; 91 92 protected: 93 void AppendDataOut(const std::string& data); GetDataIn()94 const std::string& GetDataIn() const { return in_buffer_; } 95 96 private: 97 friend WebSocketServer; 98 void AppendDataIn(void* data, size_t len); 99 int OnWritable(); 100 size_t content_len() const; 101 102 struct lws* wsi_; 103 std::string in_buffer_ = {}; 104 std::string out_buffer_ = {}; 105 }; 106 107 using DynHandlerFactory = 108 std::function<std::unique_ptr<DynHandler>(struct lws*)>; 109 } // namespace cuttlefish 110