LCOV - code coverage report
Current view: top level - extra/webserver/webserver/websocket - SPWebWebsocket.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2 2 100.0 %
Date: 2024-05-12 00:16:13 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /**
       2             :  Copyright (c) 2024 Stappler LLC <admin@stappler.dev>
       3             : 
       4             :  Permission is hereby granted, free of charge, to any person obtaining a copy
       5             :  of this software and associated documentation files (the "Software"), to deal
       6             :  in the Software without restriction, including without limitation the rights
       7             :  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       8             :  copies of the Software, and to permit persons to whom the Software is
       9             :  furnished to do so, subject to the following conditions:
      10             : 
      11             :  The above copyright notice and this permission notice shall be included in
      12             :  all copies or substantial portions of the Software.
      13             : 
      14             :  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      17             :  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18             :  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      19             :  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      20             :  THE SOFTWARE.
      21             :  **/
      22             : 
      23             : #ifndef EXTRA_WEBSERVER_WEBSERVER_WEBSOCKET_SPWEBWEBSOCKET_H_
      24             : #define EXTRA_WEBSERVER_WEBSERVER_WEBSOCKET_SPWEBWEBSOCKET_H_
      25             : 
      26             : #include "SPWeb.h"
      27             : #include "SPWebRequest.h"
      28             : #include "SPWebHost.h"
      29             : #include "SPBuffer.h"
      30             : 
      31             : namespace STAPPLER_VERSIONIZED stappler::web {
      32             : 
      33             : class WebsocketManager;
      34             : class WebsocketHandler;
      35             : 
      36             : enum class WebsocketFrameType : uint8_t {
      37             :         None,
      38             : 
      39             :         // User
      40             :         Text,
      41             :         Binary,
      42             : 
      43             :         // System
      44             :         Continue,
      45             :         Close,
      46             :         Ping,
      47             :         Pong,
      48             : };
      49             : 
      50             : enum class WebsocketStatusCode : uint16_t {
      51             :         None = 0,
      52             :         Auto = 1,
      53             :         Ok = 1000,
      54             :         Away = 1001,
      55             :         ProtocolError = 1002,
      56             :         NotAcceptable = 1003,
      57             :         ExpectStatus = 1005,
      58             :         AbnormalClose = 1006,
      59             :         NotConsistent = 1007,
      60             :         PolicyViolated = 1008,
      61             :         TooLarge = 1009,
      62             :         NotNegotiated = 1010,
      63             :         UnexceptedCondition = 1011,
      64             :         SSLError = 1015,
      65             : };
      66             : 
      67             : 
      68             : struct WebsocketFrameReader : AllocBase {
      69             :         enum class Status : uint8_t {
      70             :                 Head,
      71             :                 Size16,
      72             :                 Size64,
      73             :                 Mask,
      74             :                 Body,
      75             :                 Control
      76             :         };
      77             : 
      78             :         enum class Error : uint8_t {
      79             :                 None,
      80             :                 NotInitialized, // error in reader initialization
      81             :                 ExtraIsNotEmpty,// rsv 1-3 is not empty
      82             :                 NotMasked,// input frame is not masked
      83             :                 UnknownOpcode,// unknown opcode in frame
      84             :                 InvalidSegment,// invalid FIN or OPCODE sequence in segmented frames
      85             :                 InvalidSize,// frame (or sequence) is larger then max size
      86             :                 InvalidAction,// Handler tries to perform invalid reading action
      87             :         };
      88             : 
      89             :         struct Frame {
      90             :                 bool fin; // fin value inside current frame
      91             :                 WebsocketFrameType type; // opcode from first frame
      92             :                 Bytes buffer; // common data buffer
      93             :                 size_t block; // size of completely written block when segmented
      94             :                 size_t offset; // offset inside current frame
      95             :         };
      96             : 
      97             :         static WebsocketFrameType getTypeFromOpcode(uint8_t opcode);
      98             :         static bool isControlFrameType(WebsocketFrameType t);
      99             : 
     100             :         static void unmask(uint32_t mask, size_t offset, uint8_t *data, size_t nbytes);
     101             : 
     102             :         template <typename B>
     103        5525 :         static size_t getBufferRequiredBytes(const B &buf, size_t maxSize) {
     104        5525 :                 return (buf.size() < maxSize) ? (maxSize - buf.size()) : 0;
     105             :         }
     106             : 
     107             :         bool fin = false;
     108             :         bool masked = false;
     109             : 
     110             :         Status status = Status::Head;
     111             :         Error error = Error::None;
     112             :         WebsocketFrameType type = WebsocketFrameType::None;
     113             :         uint8_t extra = 0;
     114             :         uint32_t mask = 0;
     115             :         size_t size = 0;
     116             :         size_t max = config::WEBSOCKET_DEFAULT_MAX_FRAME_SIZE; // absolute maximum (even for segmented frames)
     117             : 
     118             :         Frame frame;
     119             :         pool_t *pool = nullptr;
     120             :         Root * root = nullptr;
     121             :         StackBuffer<128> buffer;
     122             : 
     123             :         WebsocketFrameReader(Root *r, pool_t *p);
     124             : 
     125             :         explicit operator bool() const {  return error == Error::None; }
     126             : 
     127             :         size_t getRequiredBytes() const;
     128             :         uint8_t * prepare(size_t &len);
     129             :         bool save(uint8_t *, size_t nbytes);
     130             : 
     131             :         bool isFrameReady() const;
     132             :         bool isControlReady() const;
     133             :         void popFrame();
     134             :         void clear();
     135             : 
     136             :         bool updateState();
     137             : };
     138             : 
     139             : struct WebsocketFrameWriter : AllocBase {
     140             :         static uint8_t getOpcodeFromType(WebsocketFrameType opcode);
     141             : 
     142             :         static size_t getFrameSize(size_t dataSize, bool masked = false);
     143             :         static size_t makeHeader(uint8_t *buf, size_t dataSize, WebsocketFrameType t, bool masked = false, uint32_t mask = 0);
     144             :         static void makeHeader(StackBuffer<32> &buf, size_t dataSize, WebsocketFrameType t, bool masked = false, uint32_t mask = 0);
     145             : 
     146             :         struct Slice {
     147             :                 uint8_t *data;
     148             :                 size_t size;
     149             :                 Slice *next;
     150             :         };
     151             : 
     152             :         struct WriteSlot : AllocBase {
     153             :                 pool_t *pool;
     154             :                 size_t alloc = 0;
     155             :                 size_t offset = 0;
     156             :                 Slice *firstData = nullptr;
     157             :                 Slice *lastData = nullptr;
     158             : 
     159             :                 WriteSlot *next = nullptr;
     160             : 
     161             :                 WriteSlot(pool_t *p);
     162             : 
     163             :                 bool empty() const;
     164             : 
     165             :                 void emplace(const uint8_t *data, size_t size);
     166             : 
     167             :                 void pop(size_t size);
     168             : 
     169             :                 uint8_t * getNextBytes() const;
     170             :                 size_t getNextLength() const;
     171             :         };
     172             : 
     173             :         pool_t *pool = nullptr;
     174             :         WriteSlot *firstSlot = nullptr;
     175             :         WriteSlot *lastSlot = nullptr;
     176             : 
     177             :         WebsocketFrameWriter(pool_t *p);
     178             : 
     179             :         bool empty() const;
     180             : 
     181             :         WriteSlot *nextReadSlot() const;
     182             : 
     183             :         void popReadSlot();
     184             : 
     185             :         WriteSlot *nextEmplaceSlot(size_t sizeOfData);
     186             : };
     187             : 
     188             : 
     189             : }
     190             : 
     191             : #endif /* EXTRA_WEBSERVER_WEBSERVER_WEBSOCKET_SPWEBWEBSOCKET_H_ */

Generated by: LCOV version 1.14