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_SPWEBWEBSOCKETMANAGER_H_ 24 : #define EXTRA_WEBSERVER_WEBSERVER_WEBSOCKET_SPWEBWEBSOCKETMANAGER_H_ 25 : 26 : #include "SPWebWebsocket.h" 27 : 28 : namespace STAPPLER_VERSIONIZED stappler::web { 29 : 30 : class WebsocketConnection; 31 : 32 : class WebsocketManager : public AllocBase { 33 : public: 34 : static String makeAcceptKey(StringView key); 35 : 36 : WebsocketManager(const Host &); 37 : virtual ~WebsocketManager(); 38 : 39 : virtual WebsocketHandler * onAccept(const Request &, pool_t *); 40 : virtual bool onBroadcast(const Value &); 41 : 42 : size_t size() const; 43 : 44 : void receiveBroadcast(const Value &); 45 : Status accept(Request &); 46 : 47 : void run(WebsocketHandler *); 48 : 49 2674 : const Host &host() const { return _host; } 50 : 51 : protected: 52 : void addHandler(WebsocketHandler *); 53 : void removeHandler(WebsocketHandler *); 54 : 55 : pool_t *_pool; 56 : Mutex _mutex; 57 : std::atomic<size_t> _count; 58 : Vector<WebsocketHandler *> _handlers; 59 : Host _host; 60 : }; 61 : 62 : class WebsocketHandler : public AllocBase { 63 : public: 64 : WebsocketHandler(WebsocketManager *m, pool_t *p, StringView url, 65 : TimeInterval ttl = config::WEBSOCKET_DEFAULT_TTL, 66 : size_t max = config::WEBSOCKET_DEFAULT_MAX_FRAME_SIZE); 67 : virtual ~WebsocketHandler(); 68 : 69 : // Client just connected 70 0 : virtual void handleBegin() { } 71 : 72 : // Data frame was recieved from network 73 : virtual bool handleFrame(WebsocketFrameType, const Bytes &); 74 : 75 : // Message was recieved from broadcast 76 : virtual bool handleMessage(const Value &); 77 : 78 : // Client is about disconnected 79 : // You can not send any frames in this call, because 'close' frame was already sent 80 25 : virtual void handleEnd() { } 81 : 82 : // Send system-wide broadcast, that can be received by any other websocket with same servername and url 83 : // This socket also receive this broadcast 84 : void sendBroadcast(Value &&) const; 85 : 86 : void setEncodeFormat(const data::EncodeFormat &); 87 : 88 : bool send(StringView); 89 : bool send(BytesView); 90 : bool send(const Value &); 91 : 92 : // get default storage adapter, that binds to current call context 93 550 : WebsocketManager *manager() const { return _manager; } 94 100 : WebsocketConnection *connection() const { return _conn; } 95 : pool_t *pool() const; 96 : 97 25 : StringView getUrl() const { return _url; } 98 : TimeInterval getTtl() const { return _ttl; } 99 : size_t getMaxInputFrameSize() const { return _maxInputFrameSize; } 100 : 101 : bool isEnabled() const; 102 : 103 : void sendPendingNotifications(pool_t *); 104 : 105 : void performWithStorage(const Callback<void(const db::Transaction &)> &cb) const; 106 : 107 : bool performAsync(const Callback<void(AsyncTask &)> &cb) const; 108 : 109 : bool processBroadcasts(); 110 : 111 : protected: 112 : friend class WebsocketManager; 113 : friend class WebsocketConnection; 114 : 115 : void setConnection(WebsocketConnection *); 116 : virtual void receiveBroadcast(const Value &); 117 : 118 : pool_t *_pool = nullptr; 119 : WebsocketManager *_manager = nullptr; 120 : 121 : data::EncodeFormat _format = data::EncodeFormat::Json; 122 : StringView _url; 123 : TimeInterval _ttl = config::WEBSOCKET_DEFAULT_TTL; 124 : size_t _maxInputFrameSize = config::WEBSOCKET_DEFAULT_MAX_FRAME_SIZE; 125 : 126 : Mutex _broadcastMutex; 127 : pool_t *_broadcastsPool = nullptr; 128 : Vector<Value> *_broadcastsMessages = nullptr; 129 : 130 : WebsocketConnection *_conn = nullptr; 131 : }; 132 : 133 : } 134 : 135 : #endif /* EXTRA_WEBSERVER_WEBSERVER_WEBSOCKET_SPWEBWEBSOCKETMANAGER_H_ */