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