WPILibC++ 2025.2.1
Loading...
Searching...
No Matches
HttpWebSocketServerConnection.h
Go to the documentation of this file.
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#ifndef WPINET_HTTPWEBSOCKETSERVERCONNECTION_H_
6#define WPINET_HTTPWEBSOCKETSERVERCONNECTION_H_
7
8#include <initializer_list>
9#include <memory>
10#include <span>
11#include <string>
12#include <string_view>
13
14#include <wpi/SmallVector.h>
15
17#include "wpinet/WebSocket.h"
19#include "wpinet/uv/Stream.h"
20
21namespace wpi {
22
23/**
24 * A server-side HTTP connection that also accepts WebSocket upgrades.
25 *
26 * @tparam Derived derived class for std::enable_shared_from_this.
27 */
28template <typename Derived>
30 : public HttpServerConnection,
31 public std::enable_shared_from_this<Derived> {
32 public:
33 /**
34 * Constructor.
35 *
36 * @param stream network stream
37 * @param protocols Acceptable subprotocols
38 */
39 HttpWebSocketServerConnection(std::shared_ptr<uv::Stream> stream,
40 std::span<const std::string_view> protocols)
41 : HttpServerConnection{stream},
42 m_helper{m_request},
43 m_protocols{protocols.begin(), protocols.end()} {
44 // Handle upgrade event
45 m_helper.upgrade.connect([this] {
46 // Negotiate sub-protocol
47 SmallVector<std::string_view, 2> protocols{m_protocols.begin(),
48 m_protocols.end()};
49 std::string_view protocol = m_helper.MatchProtocol(protocols).second;
50
51 // Check that the upgrade is valid
52 if (!IsValidWsUpgrade(protocol)) {
53 return;
54 }
55
56 // Disconnect HttpServerConnection header reader
59
60 // Accepting the stream may destroy this (as it replaces the stream user
61 // data), so grab a shared pointer first.
62 auto self = this->shared_from_this();
63
64 // Accept the upgrade
65 auto ws = m_helper.Accept(m_stream, protocol);
66
67 // Set this as the websocket user data to keep it around
68 ws->SetData(self);
69
70 // Store in member
71 m_websocket = ws.get();
72
73 // Call derived class function
75 });
76 }
77
78 /**
79 * Constructor.
80 *
81 * @param stream network stream
82 * @param protocols Acceptable subprotocols
83 */
85 std::shared_ptr<uv::Stream> stream,
86 std::initializer_list<std::string_view> protocols)
88 {protocols.begin(), protocols.end()}) {}
89
90 protected:
91 /**
92 * Check that an incoming WebSocket upgrade is okay. This is called prior
93 * to accepting the upgrade (so prior to ProcessWsUpgrade()).
94 *
95 * The implementation should check other headers and return true if the
96 * WebSocket connection should be accepted.
97 *
98 * @param protocol negotiated subprotocol
99 */
100 virtual bool IsValidWsUpgrade(std::string_view protocol) { return true; }
101
102 /**
103 * Process an incoming WebSocket upgrade. This is called after the header
104 * reader has been disconnected and the websocket has been accepted.
105 *
106 * The implementation should set up appropriate callbacks on the websocket
107 * object to continue communication.
108 *
109 * @note When a WebSocket upgrade occurs, the stream user data is replaced
110 * with the websocket, and the websocket user data points to "this".
111 * Replace the websocket user data with caution!
112 */
113 virtual void ProcessWsUpgrade() = 0;
114
115 /**
116 * WebSocket connection; not valid until ProcessWsUpgrade is called.
117 */
119
120 private:
121 WebSocketServerHelper m_helper;
122 SmallVector<std::string, 2> m_protocols;
123};
124
125} // namespace wpi
126
127#endif // WPINET_HTTPWEBSOCKETSERVERCONNECTION_H_
This file defines the SmallVector class.
Definition HttpServerConnection.h:19
sig::ScopedConnection m_dataConn
The header reader connection.
Definition HttpServerConnection.h:141
uv::Stream & m_stream
The underlying stream for the connection.
Definition HttpServerConnection.h:138
HttpParser m_request
The HTTP request.
Definition HttpServerConnection.h:129
sig::Connection m_messageCompleteConn
The message complete connection.
Definition HttpServerConnection.h:147
A server-side HTTP connection that also accepts WebSocket upgrades.
Definition HttpWebSocketServerConnection.h:31
virtual void ProcessWsUpgrade()=0
Process an incoming WebSocket upgrade.
virtual bool IsValidWsUpgrade(std::string_view protocol)
Check that an incoming WebSocket upgrade is okay.
Definition HttpWebSocketServerConnection.h:100
HttpWebSocketServerConnection(std::shared_ptr< uv::Stream > stream, std::span< const std::string_view > protocols)
Constructor.
Definition HttpWebSocketServerConnection.h:39
WebSocket * m_websocket
WebSocket connection; not valid until ProcessWsUpgrade is called.
Definition HttpWebSocketServerConnection.h:118
HttpWebSocketServerConnection(std::shared_ptr< uv::Stream > stream, std::initializer_list< std::string_view > protocols)
Constructor.
Definition HttpWebSocketServerConnection.h:84
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition SmallVector.h:1212
iterator begin()
Definition SmallVector.h:283
iterator end()
Definition SmallVector.h:285
RFC 6455 compliant WebSocket client and server implementation.
Definition WebSocket.h:34
WebSocket HTTP server helper.
Definition WebSocketServer.h:33
sig::Signal upgrade
Upgrade event.
Definition WebSocketServer.h:89
std::shared_ptr< WebSocket > Accept(uv::Stream &stream, std::string_view protocol={})
Accept the upgrade.
Definition WebSocketServer.h:79
std::pair< bool, std::string_view > MatchProtocol(std::span< const std::string_view > protocols)
Try to find a match to the list of sub-protocols provided by the client.
bool disconnect() noexcept
Definition Signal.h:217
void connect(Callable &&c)
Connect a callable of compatible arguments.
Definition Signal.h:586
Foonathan namespace.
Definition ntcore_cpp.h:26