Coverage Report

Created: 2025-12-18 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/uWebSockets/src/WebSocketContext.h
Line
Count
Source
1
/*
2
 * Authored by Alex Hultman, 2018-2020.
3
 * Intellectual property of third-party.
4
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
9
 *     http://www.apache.org/licenses/LICENSE-2.0
10
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
#ifndef UWS_WEBSOCKETCONTEXT_H
19
#define UWS_WEBSOCKETCONTEXT_H
20
21
#include "WebSocketContextData.h"
22
#include "WebSocketProtocol.h"
23
#include "WebSocketData.h"
24
#include "WebSocket.h"
25
26
namespace uWS {
27
28
template <bool SSL, bool isServer, typename USERDATA>
29
struct WebSocketContext {
30
    template <bool> friend struct TemplatedApp;
31
    template <bool, typename> friend struct WebSocketProtocol;
32
private:
33
    WebSocketContext() = delete;
34
35
218k
    us_socket_context_t *getSocketContext() {
36
218k
        return (us_socket_context_t *) this;
37
218k
    }
EpollEchoServerPubSub.cpp:uWS::WebSocketContext<true, true, test()::PerSocketData>::getSocketContext()
Line
Count
Source
35
34.4k
    us_socket_context_t *getSocketContext() {
36
34.4k
        return (us_socket_context_t *) this;
37
34.4k
    }
EpollHelloWorld.cpp:uWS::WebSocketContext<false, true, test()::PerSocketData>::getSocketContext()
Line
Count
Source
35
88.4k
    us_socket_context_t *getSocketContext() {
36
88.4k
        return (us_socket_context_t *) this;
37
88.4k
    }
EpollEchoServer.cpp:uWS::WebSocketContext<false, true, test()::PerSocketData>::getSocketContext()
Line
Count
Source
35
96.0k
    us_socket_context_t *getSocketContext() {
36
96.0k
        return (us_socket_context_t *) this;
37
96.0k
    }
38
39
532k
    WebSocketContextData<SSL, USERDATA> *getExt() {
40
532k
        return (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, (us_socket_context_t *) this);
41
532k
    }
EpollEchoServerPubSub.cpp:uWS::WebSocketContext<true, true, test()::PerSocketData>::getExt()
Line
Count
Source
39
91.9k
    WebSocketContextData<SSL, USERDATA> *getExt() {
40
91.9k
        return (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, (us_socket_context_t *) this);
41
91.9k
    }
EpollHelloWorld.cpp:uWS::WebSocketContext<false, true, test()::PerSocketData>::getExt()
Line
Count
Source
39
217k
    WebSocketContextData<SSL, USERDATA> *getExt() {
40
217k
        return (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, (us_socket_context_t *) this);
41
217k
    }
EpollEchoServer.cpp:uWS::WebSocketContext<false, true, test()::PerSocketData>::getExt()
Line
Count
Source
39
222k
    WebSocketContextData<SSL, USERDATA> *getExt() {
40
222k
        return (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, (us_socket_context_t *) this);
41
222k
    }
42
43
    /* If we have negotiated compression, set this frame compressed */
44
28.8k
    static bool setCompressed(WebSocketState<isServer> */*wState*/, void *s) {
45
28.8k
        WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) s);
46
47
28.8k
        if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::ENABLED) {
48
3.30k
            webSocketData->compressionStatus = WebSocketData::CompressionStatus::COMPRESSED_FRAME;
49
3.30k
            return true;
50
25.5k
        } else {
51
25.5k
            return false;
52
25.5k
        }
53
28.8k
    }
EpollEchoServerPubSub.cpp:uWS::WebSocketContext<true, true, test()::PerSocketData>::setCompressed(uWS::WebSocketState<true>*, void*)
Line
Count
Source
44
16.1k
    static bool setCompressed(WebSocketState<isServer> */*wState*/, void *s) {
45
16.1k
        WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) s);
46
47
16.1k
        if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::ENABLED) {
48
0
            webSocketData->compressionStatus = WebSocketData::CompressionStatus::COMPRESSED_FRAME;
49
0
            return true;
50
16.1k
        } else {
51
16.1k
            return false;
52
16.1k
        }
53
16.1k
    }
EpollHelloWorld.cpp:uWS::WebSocketContext<false, true, test()::PerSocketData>::setCompressed(uWS::WebSocketState<true>*, void*)
Line
Count
Source
44
2.27k
    static bool setCompressed(WebSocketState<isServer> */*wState*/, void *s) {
45
2.27k
        WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) s);
46
47
2.27k
        if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::ENABLED) {
48
1.45k
            webSocketData->compressionStatus = WebSocketData::CompressionStatus::COMPRESSED_FRAME;
49
1.45k
            return true;
50
1.45k
        } else {
51
820
            return false;
52
820
        }
53
2.27k
    }
EpollEchoServer.cpp:uWS::WebSocketContext<false, true, test()::PerSocketData>::setCompressed(uWS::WebSocketState<true>*, void*)
Line
Count
Source
44
10.4k
    static bool setCompressed(WebSocketState<isServer> */*wState*/, void *s) {
45
10.4k
        WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) s);
46
47
10.4k
        if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::ENABLED) {
48
1.85k
            webSocketData->compressionStatus = WebSocketData::CompressionStatus::COMPRESSED_FRAME;
49
1.85k
            return true;
50
8.61k
        } else {
51
8.61k
            return false;
52
8.61k
        }
53
10.4k
    }
54
55
93.0k
    static void forceClose(WebSocketState<isServer> */*wState*/, void *s, std::string_view reason = {}) {
56
93.0k
        us_socket_close(SSL, (us_socket_t *) s, (int) reason.length(), (void *) reason.data());
57
93.0k
    }
EpollEchoServerPubSub.cpp:uWS::WebSocketContext<true, true, test()::PerSocketData>::forceClose(uWS::WebSocketState<true>*, void*, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
55
49.1k
    static void forceClose(WebSocketState<isServer> */*wState*/, void *s, std::string_view reason = {}) {
56
49.1k
        us_socket_close(SSL, (us_socket_t *) s, (int) reason.length(), (void *) reason.data());
57
49.1k
    }
EpollHelloWorld.cpp:uWS::WebSocketContext<false, true, test()::PerSocketData>::forceClose(uWS::WebSocketState<true>*, void*, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
55
12.2k
    static void forceClose(WebSocketState<isServer> */*wState*/, void *s, std::string_view reason = {}) {
56
12.2k
        us_socket_close(SSL, (us_socket_t *) s, (int) reason.length(), (void *) reason.data());
57
12.2k
    }
EpollEchoServer.cpp:uWS::WebSocketContext<false, true, test()::PerSocketData>::forceClose(uWS::WebSocketState<true>*, void*, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
55
31.5k
    static void forceClose(WebSocketState<isServer> */*wState*/, void *s, std::string_view reason = {}) {
56
31.5k
        us_socket_close(SSL, (us_socket_t *) s, (int) reason.length(), (void *) reason.data());
57
31.5k
    }
58
59
    /* Returns true on breakage */
60
1.26M
    static bool handleFragment(char *data, size_t length, unsigned int remainingBytes, int opCode, bool fin, WebSocketState<isServer> *webSocketState, void *s) {
61
        /* WebSocketData and WebSocketContextData */
62
1.26M
        WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
63
1.26M
        WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) s);
64
65
        /* Is this a non-control frame? */
66
1.26M
        if (opCode < 3) {
67
            /* Did we get everything in one go? */
68
1.20M
            if (!remainingBytes && fin && !webSocketData->fragmentBuffer.length()) {
69
70
                /* Handle compressed frame */
71
1.11M
                if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::COMPRESSED_FRAME) {
72
1.21k
                        webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED;
73
74
1.21k
                        LoopData *loopData = (LoopData *) us_loop_ext(us_socket_context_loop(SSL, us_socket_context(SSL, (us_socket_t *) s)));
75
                        /* Decompress using shared or dedicated decompressor */
76
1.21k
                        std::optional<std::string_view> inflatedFrame;
77
1.21k
                        if (webSocketData->inflationStream) {
78
0
                            inflatedFrame = webSocketData->inflationStream->inflate(loopData->zlibContext, {data, length}, webSocketContextData->maxPayloadLength, false);
79
1.21k
                        } else {
80
1.21k
                            inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {data, length}, webSocketContextData->maxPayloadLength, true);
81
1.21k
                        }
82
83
1.21k
                        if (!inflatedFrame.has_value()) {
84
0
                            forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE_INFLATION);
85
0
                            return true;
86
1.21k
                        } else {
87
1.21k
                            data = (char *) inflatedFrame->data();
88
1.21k
                            length = inflatedFrame->length();
89
1.21k
                        }
90
1.21k
                }
91
92
                /* Check text messages for Utf-8 validity */
93
1.11M
                if (opCode == 1 && !protocol::isValidUtf8((unsigned char *) data, length)) {
94
20.2k
                    forceClose(webSocketState, s, ERR_INVALID_TEXT);
95
20.2k
                    return true;
96
20.2k
                }
97
98
                /* Emit message event & break if we are closed or shut down when returning */
99
1.09M
                if (webSocketContextData->messageHandler) {
100
1.08M
                    webSocketContextData->messageHandler((WebSocket<SSL, isServer, USERDATA> *) s, std::string_view(data, length), (OpCode) opCode);
101
1.08M
                    if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
102
923
                        return true;
103
923
                    }
104
1.08M
                }
105
1.09M
            } else {
106
                /* Allocate fragment buffer up front first time */
107
92.3k
                if (!webSocketData->fragmentBuffer.length()) {
108
31.9k
                    webSocketData->fragmentBuffer.reserve(length + remainingBytes);
109
31.9k
                }
110
                /* Fragments forming a big message are not caught until appending them */
111
92.3k
                if (refusePayloadLength(length + webSocketData->fragmentBuffer.length(), webSocketState, s)) {
112
619
                    forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE);
113
619
                    return true;
114
619
                }
115
91.7k
                webSocketData->fragmentBuffer.append(data, length);
116
117
                /* Are we done now? */
118
                // todo: what if we don't have any remaining bytes yet we are not fin? forceclose!
119
91.7k
                if (!remainingBytes && fin) {
120
121
                    /* Handle compression */
122
9.24k
                    if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::COMPRESSED_FRAME) {
123
1.84k
                            webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED;
124
125
                            /* 9 bytes of padding for libdeflate, 4 for zlib */
126
1.84k
                            webSocketData->fragmentBuffer.append("123456789");
127
128
1.84k
                            LoopData *loopData = (LoopData *) us_loop_ext(
129
1.84k
                                us_socket_context_loop(SSL,
130
1.84k
                                    us_socket_context(SSL, (us_socket_t *) s)
131
1.84k
                                )
132
1.84k
                            );
133
134
                            /* Decompress using shared or dedicated decompressor */
135
1.84k
                            std::optional<std::string_view> inflatedFrame;
136
1.84k
                            if (webSocketData->inflationStream) {
137
0
                                inflatedFrame = webSocketData->inflationStream->inflate(loopData->zlibContext, {webSocketData->fragmentBuffer.data(), webSocketData->fragmentBuffer.length() - 9}, webSocketContextData->maxPayloadLength, false);
138
1.84k
                            } else {
139
1.84k
                                inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {webSocketData->fragmentBuffer.data(), webSocketData->fragmentBuffer.length() - 9}, webSocketContextData->maxPayloadLength, true);
140
1.84k
                            }
141
142
1.84k
                            if (!inflatedFrame.has_value()) {
143
0
                                forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE_INFLATION);
144
0
                                return true;
145
1.84k
                            } else {
146
1.84k
                                data = (char *) inflatedFrame->data();
147
1.84k
                                length = inflatedFrame->length();
148
1.84k
                            }
149
150
151
7.40k
                    } else {
152
                        // reset length and data ptrs
153
7.40k
                        length = webSocketData->fragmentBuffer.length();
154
7.40k
                        data = webSocketData->fragmentBuffer.data();
155
7.40k
                    }
156
157
                    /* Check text messages for Utf-8 validity */
158
9.24k
                    if (opCode == 1 && !protocol::isValidUtf8((unsigned char *) data, length)) {
159
1.03k
                        forceClose(webSocketState, s, ERR_INVALID_TEXT);
160
1.03k
                        return true;
161
1.03k
                    }
162
163
                    /* Emit message and check for shutdown or close */
164
8.20k
                    if (webSocketContextData->messageHandler) {
165
7.81k
                        webSocketContextData->messageHandler((WebSocket<SSL, isServer, USERDATA> *) s, std::string_view(data, length), (OpCode) opCode);
166
7.81k
                        if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
167
389
                            return true;
168
389
                        }
169
7.81k
                    }
170
171
                    /* If we shutdown or closed, this will be taken care of elsewhere */
172
7.81k
                    webSocketData->fragmentBuffer.clear();
173
7.81k
                }
174
91.7k
            }
175
1.20M
        } else {
176
            /* Control frames need the websocket to send pings, pongs and close */
177
62.2k
            WebSocket<SSL, isServer, USERDATA> *webSocket = (WebSocket<SSL, isServer, USERDATA> *) s;
178
179
62.2k
            if (!remainingBytes && fin && !webSocketData->controlTipLength) {
180
39.8k
                if (opCode == CLOSE) {
181
17.3k
                    auto closeFrame = protocol::parseClosePayload(data, length);
182
17.3k
                    webSocket->end(closeFrame.code, std::string_view(closeFrame.message, closeFrame.length));
183
17.3k
                    return true;
184
22.5k
                } else {
185
22.5k
                    if (opCode == PING) {
186
20.2k
                        webSocket->send(std::string_view(data, length), (OpCode) OpCode::PONG);
187
20.2k
                        if (webSocketContextData->pingHandler) {
188
20.0k
                            webSocketContextData->pingHandler(webSocket, {data, length});
189
20.0k
                            if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
190
0
                                return true;
191
0
                            }
192
20.0k
                        }
193
20.2k
                    } else if (opCode == PONG) {
194
2.26k
                        if (webSocketContextData->pongHandler) {
195
2.05k
                            webSocketContextData->pongHandler(webSocket, {data, length});
196
2.05k
                            if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
197
0
                                return true;
198
0
                            }
199
2.05k
                        }
200
2.26k
                    }
201
22.5k
                }
202
39.8k
            } else {
203
                /* Here we never mind any size optimizations as we are in the worst possible path */
204
22.3k
                webSocketData->fragmentBuffer.append(data, length);
205
22.3k
                webSocketData->controlTipLength += (unsigned int) length;
206
207
22.3k
                if (!remainingBytes && fin) {
208
10.2k
                    char *controlBuffer = (char *) webSocketData->fragmentBuffer.data() + webSocketData->fragmentBuffer.length() - webSocketData->controlTipLength;
209
10.2k
                    if (opCode == CLOSE) {
210
5.55k
                        protocol::CloseFrame closeFrame = protocol::parseClosePayload(controlBuffer, webSocketData->controlTipLength);
211
5.55k
                        webSocket->end(closeFrame.code, std::string_view(closeFrame.message, closeFrame.length));
212
5.55k
                        return true;
213
5.55k
                    } else {
214
4.67k
                        if (opCode == PING) {
215
1.67k
                            webSocket->send(std::string_view(controlBuffer, webSocketData->controlTipLength), (OpCode) OpCode::PONG);
216
1.67k
                            if (webSocketContextData->pingHandler) {
217
1.47k
                                webSocketContextData->pingHandler(webSocket, std::string_view(controlBuffer, webSocketData->controlTipLength));
218
1.47k
                                if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
219
0
                                    return true;
220
0
                                }
221
1.47k
                            }
222
2.99k
                        } else if (opCode == PONG) {
223
2.99k
                            if (webSocketContextData->pongHandler) {
224
2.18k
                                webSocketContextData->pongHandler(webSocket, std::string_view(controlBuffer, webSocketData->controlTipLength));
225
2.18k
                                if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
226
0
                                    return true;
227
0
                                }
228
2.18k
                            }
229
2.99k
                        }
230
4.67k
                    }
231
232
                    /* Same here, we do not care for any particular smart allocation scheme */
233
4.67k
                    webSocketData->fragmentBuffer.resize((unsigned int) webSocketData->fragmentBuffer.length() - webSocketData->controlTipLength);
234
4.67k
                    webSocketData->controlTipLength = 0;
235
4.67k
                }
236
22.3k
            }
237
62.2k
        }
238
1.21M
        return false;
239
1.26M
    }
EpollEchoServerPubSub.cpp:uWS::WebSocketContext<true, true, test()::PerSocketData>::handleFragment(char*, unsigned long, unsigned int, int, bool, uWS::WebSocketState<true>*, void*)
Line
Count
Source
60
1.05M
    static bool handleFragment(char *data, size_t length, unsigned int remainingBytes, int opCode, bool fin, WebSocketState<isServer> *webSocketState, void *s) {
61
        /* WebSocketData and WebSocketContextData */
62
1.05M
        WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
63
1.05M
        WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) s);
64
65
        /* Is this a non-control frame? */
66
1.05M
        if (opCode < 3) {
67
            /* Did we get everything in one go? */
68
1.03M
            if (!remainingBytes && fin && !webSocketData->fragmentBuffer.length()) {
69
70
                /* Handle compressed frame */
71
1.00M
                if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::COMPRESSED_FRAME) {
72
0
                        webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED;
73
74
0
                        LoopData *loopData = (LoopData *) us_loop_ext(us_socket_context_loop(SSL, us_socket_context(SSL, (us_socket_t *) s)));
75
                        /* Decompress using shared or dedicated decompressor */
76
0
                        std::optional<std::string_view> inflatedFrame;
77
0
                        if (webSocketData->inflationStream) {
78
0
                            inflatedFrame = webSocketData->inflationStream->inflate(loopData->zlibContext, {data, length}, webSocketContextData->maxPayloadLength, false);
79
0
                        } else {
80
0
                            inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {data, length}, webSocketContextData->maxPayloadLength, true);
81
0
                        }
82
83
0
                        if (!inflatedFrame.has_value()) {
84
0
                            forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE_INFLATION);
85
0
                            return true;
86
0
                        } else {
87
0
                            data = (char *) inflatedFrame->data();
88
0
                            length = inflatedFrame->length();
89
0
                        }
90
0
                }
91
92
                /* Check text messages for Utf-8 validity */
93
1.00M
                if (opCode == 1 && !protocol::isValidUtf8((unsigned char *) data, length)) {
94
13.0k
                    forceClose(webSocketState, s, ERR_INVALID_TEXT);
95
13.0k
                    return true;
96
13.0k
                }
97
98
                /* Emit message event & break if we are closed or shut down when returning */
99
995k
                if (webSocketContextData->messageHandler) {
100
995k
                    webSocketContextData->messageHandler((WebSocket<SSL, isServer, USERDATA> *) s, std::string_view(data, length), (OpCode) opCode);
101
995k
                    if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
102
0
                        return true;
103
0
                    }
104
995k
                }
105
995k
            } else {
106
                /* Allocate fragment buffer up front first time */
107
23.0k
                if (!webSocketData->fragmentBuffer.length()) {
108
14.5k
                    webSocketData->fragmentBuffer.reserve(length + remainingBytes);
109
14.5k
                }
110
                /* Fragments forming a big message are not caught until appending them */
111
23.0k
                if (refusePayloadLength(length + webSocketData->fragmentBuffer.length(), webSocketState, s)) {
112
212
                    forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE);
113
212
                    return true;
114
212
                }
115
22.8k
                webSocketData->fragmentBuffer.append(data, length);
116
117
                /* Are we done now? */
118
                // todo: what if we don't have any remaining bytes yet we are not fin? forceclose!
119
22.8k
                if (!remainingBytes && fin) {
120
121
                    /* Handle compression */
122
3.74k
                    if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::COMPRESSED_FRAME) {
123
0
                            webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED;
124
125
                            /* 9 bytes of padding for libdeflate, 4 for zlib */
126
0
                            webSocketData->fragmentBuffer.append("123456789");
127
128
0
                            LoopData *loopData = (LoopData *) us_loop_ext(
129
0
                                us_socket_context_loop(SSL,
130
0
                                    us_socket_context(SSL, (us_socket_t *) s)
131
0
                                )
132
0
                            );
133
134
                            /* Decompress using shared or dedicated decompressor */
135
0
                            std::optional<std::string_view> inflatedFrame;
136
0
                            if (webSocketData->inflationStream) {
137
0
                                inflatedFrame = webSocketData->inflationStream->inflate(loopData->zlibContext, {webSocketData->fragmentBuffer.data(), webSocketData->fragmentBuffer.length() - 9}, webSocketContextData->maxPayloadLength, false);
138
0
                            } else {
139
0
                                inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {webSocketData->fragmentBuffer.data(), webSocketData->fragmentBuffer.length() - 9}, webSocketContextData->maxPayloadLength, true);
140
0
                            }
141
142
0
                            if (!inflatedFrame.has_value()) {
143
0
                                forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE_INFLATION);
144
0
                                return true;
145
0
                            } else {
146
0
                                data = (char *) inflatedFrame->data();
147
0
                                length = inflatedFrame->length();
148
0
                            }
149
150
151
3.74k
                    } else {
152
                        // reset length and data ptrs
153
3.74k
                        length = webSocketData->fragmentBuffer.length();
154
3.74k
                        data = webSocketData->fragmentBuffer.data();
155
3.74k
                    }
156
157
                    /* Check text messages for Utf-8 validity */
158
3.74k
                    if (opCode == 1 && !protocol::isValidUtf8((unsigned char *) data, length)) {
159
469
                        forceClose(webSocketState, s, ERR_INVALID_TEXT);
160
469
                        return true;
161
469
                    }
162
163
                    /* Emit message and check for shutdown or close */
164
3.27k
                    if (webSocketContextData->messageHandler) {
165
3.27k
                        webSocketContextData->messageHandler((WebSocket<SSL, isServer, USERDATA> *) s, std::string_view(data, length), (OpCode) opCode);
166
3.27k
                        if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
167
0
                            return true;
168
0
                        }
169
3.27k
                    }
170
171
                    /* If we shutdown or closed, this will be taken care of elsewhere */
172
3.27k
                    webSocketData->fragmentBuffer.clear();
173
3.27k
                }
174
22.8k
            }
175
1.03M
        } else {
176
            /* Control frames need the websocket to send pings, pongs and close */
177
18.7k
            WebSocket<SSL, isServer, USERDATA> *webSocket = (WebSocket<SSL, isServer, USERDATA> *) s;
178
179
18.7k
            if (!remainingBytes && fin && !webSocketData->controlTipLength) {
180
11.5k
                if (opCode == CLOSE) {
181
7.68k
                    auto closeFrame = protocol::parseClosePayload(data, length);
182
7.68k
                    webSocket->end(closeFrame.code, std::string_view(closeFrame.message, closeFrame.length));
183
7.68k
                    return true;
184
7.68k
                } else {
185
3.89k
                    if (opCode == PING) {
186
3.53k
                        webSocket->send(std::string_view(data, length), (OpCode) OpCode::PONG);
187
3.53k
                        if (webSocketContextData->pingHandler) {
188
3.53k
                            webSocketContextData->pingHandler(webSocket, {data, length});
189
3.53k
                            if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
190
0
                                return true;
191
0
                            }
192
3.53k
                        }
193
3.53k
                    } else if (opCode == PONG) {
194
361
                        if (webSocketContextData->pongHandler) {
195
361
                            webSocketContextData->pongHandler(webSocket, {data, length});
196
361
                            if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
197
0
                                return true;
198
0
                            }
199
361
                        }
200
361
                    }
201
3.89k
                }
202
11.5k
            } else {
203
                /* Here we never mind any size optimizations as we are in the worst possible path */
204
7.20k
                webSocketData->fragmentBuffer.append(data, length);
205
7.20k
                webSocketData->controlTipLength += (unsigned int) length;
206
207
7.20k
                if (!remainingBytes && fin) {
208
3.36k
                    char *controlBuffer = (char *) webSocketData->fragmentBuffer.data() + webSocketData->fragmentBuffer.length() - webSocketData->controlTipLength;
209
3.36k
                    if (opCode == CLOSE) {
210
2.30k
                        protocol::CloseFrame closeFrame = protocol::parseClosePayload(controlBuffer, webSocketData->controlTipLength);
211
2.30k
                        webSocket->end(closeFrame.code, std::string_view(closeFrame.message, closeFrame.length));
212
2.30k
                        return true;
213
2.30k
                    } else {
214
1.06k
                        if (opCode == PING) {
215
844
                            webSocket->send(std::string_view(controlBuffer, webSocketData->controlTipLength), (OpCode) OpCode::PONG);
216
844
                            if (webSocketContextData->pingHandler) {
217
844
                                webSocketContextData->pingHandler(webSocket, std::string_view(controlBuffer, webSocketData->controlTipLength));
218
844
                                if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
219
0
                                    return true;
220
0
                                }
221
844
                            }
222
844
                        } else if (opCode == PONG) {
223
216
                            if (webSocketContextData->pongHandler) {
224
216
                                webSocketContextData->pongHandler(webSocket, std::string_view(controlBuffer, webSocketData->controlTipLength));
225
216
                                if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
226
0
                                    return true;
227
0
                                }
228
216
                            }
229
216
                        }
230
1.06k
                    }
231
232
                    /* Same here, we do not care for any particular smart allocation scheme */
233
1.06k
                    webSocketData->fragmentBuffer.resize((unsigned int) webSocketData->fragmentBuffer.length() - webSocketData->controlTipLength);
234
1.06k
                    webSocketData->controlTipLength = 0;
235
1.06k
                }
236
7.20k
            }
237
18.7k
        }
238
1.02M
        return false;
239
1.05M
    }
EpollHelloWorld.cpp:uWS::WebSocketContext<false, true, test()::PerSocketData>::handleFragment(char*, unsigned long, unsigned int, int, bool, uWS::WebSocketState<true>*, void*)
Line
Count
Source
60
85.5k
    static bool handleFragment(char *data, size_t length, unsigned int remainingBytes, int opCode, bool fin, WebSocketState<isServer> *webSocketState, void *s) {
61
        /* WebSocketData and WebSocketContextData */
62
85.5k
        WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
63
85.5k
        WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) s);
64
65
        /* Is this a non-control frame? */
66
85.5k
        if (opCode < 3) {
67
            /* Did we get everything in one go? */
68
65.3k
            if (!remainingBytes && fin && !webSocketData->fragmentBuffer.length()) {
69
70
                /* Handle compressed frame */
71
13.6k
                if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::COMPRESSED_FRAME) {
72
651
                        webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED;
73
74
651
                        LoopData *loopData = (LoopData *) us_loop_ext(us_socket_context_loop(SSL, us_socket_context(SSL, (us_socket_t *) s)));
75
                        /* Decompress using shared or dedicated decompressor */
76
651
                        std::optional<std::string_view> inflatedFrame;
77
651
                        if (webSocketData->inflationStream) {
78
0
                            inflatedFrame = webSocketData->inflationStream->inflate(loopData->zlibContext, {data, length}, webSocketContextData->maxPayloadLength, false);
79
651
                        } else {
80
651
                            inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {data, length}, webSocketContextData->maxPayloadLength, true);
81
651
                        }
82
83
651
                        if (!inflatedFrame.has_value()) {
84
0
                            forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE_INFLATION);
85
0
                            return true;
86
651
                        } else {
87
651
                            data = (char *) inflatedFrame->data();
88
651
                            length = inflatedFrame->length();
89
651
                        }
90
651
                }
91
92
                /* Check text messages for Utf-8 validity */
93
13.6k
                if (opCode == 1 && !protocol::isValidUtf8((unsigned char *) data, length)) {
94
2.86k
                    forceClose(webSocketState, s, ERR_INVALID_TEXT);
95
2.86k
                    return true;
96
2.86k
                }
97
98
                /* Emit message event & break if we are closed or shut down when returning */
99
10.7k
                if (webSocketContextData->messageHandler) {
100
8.72k
                    webSocketContextData->messageHandler((WebSocket<SSL, isServer, USERDATA> *) s, std::string_view(data, length), (OpCode) opCode);
101
8.72k
                    if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
102
0
                        return true;
103
0
                    }
104
8.72k
                }
105
51.6k
            } else {
106
                /* Allocate fragment buffer up front first time */
107
51.6k
                if (!webSocketData->fragmentBuffer.length()) {
108
7.38k
                    webSocketData->fragmentBuffer.reserve(length + remainingBytes);
109
7.38k
                }
110
                /* Fragments forming a big message are not caught until appending them */
111
51.6k
                if (refusePayloadLength(length + webSocketData->fragmentBuffer.length(), webSocketState, s)) {
112
120
                    forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE);
113
120
                    return true;
114
120
                }
115
51.5k
                webSocketData->fragmentBuffer.append(data, length);
116
117
                /* Are we done now? */
118
                // todo: what if we don't have any remaining bytes yet we are not fin? forceclose!
119
51.5k
                if (!remainingBytes && fin) {
120
121
                    /* Handle compression */
122
2.26k
                    if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::COMPRESSED_FRAME) {
123
676
                            webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED;
124
125
                            /* 9 bytes of padding for libdeflate, 4 for zlib */
126
676
                            webSocketData->fragmentBuffer.append("123456789");
127
128
676
                            LoopData *loopData = (LoopData *) us_loop_ext(
129
676
                                us_socket_context_loop(SSL,
130
676
                                    us_socket_context(SSL, (us_socket_t *) s)
131
676
                                )
132
676
                            );
133
134
                            /* Decompress using shared or dedicated decompressor */
135
676
                            std::optional<std::string_view> inflatedFrame;
136
676
                            if (webSocketData->inflationStream) {
137
0
                                inflatedFrame = webSocketData->inflationStream->inflate(loopData->zlibContext, {webSocketData->fragmentBuffer.data(), webSocketData->fragmentBuffer.length() - 9}, webSocketContextData->maxPayloadLength, false);
138
676
                            } else {
139
676
                                inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {webSocketData->fragmentBuffer.data(), webSocketData->fragmentBuffer.length() - 9}, webSocketContextData->maxPayloadLength, true);
140
676
                            }
141
142
676
                            if (!inflatedFrame.has_value()) {
143
0
                                forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE_INFLATION);
144
0
                                return true;
145
676
                            } else {
146
676
                                data = (char *) inflatedFrame->data();
147
676
                                length = inflatedFrame->length();
148
676
                            }
149
150
151
1.58k
                    } else {
152
                        // reset length and data ptrs
153
1.58k
                        length = webSocketData->fragmentBuffer.length();
154
1.58k
                        data = webSocketData->fragmentBuffer.data();
155
1.58k
                    }
156
157
                    /* Check text messages for Utf-8 validity */
158
2.26k
                    if (opCode == 1 && !protocol::isValidUtf8((unsigned char *) data, length)) {
159
295
                        forceClose(webSocketState, s, ERR_INVALID_TEXT);
160
295
                        return true;
161
295
                    }
162
163
                    /* Emit message and check for shutdown or close */
164
1.96k
                    if (webSocketContextData->messageHandler) {
165
1.57k
                        webSocketContextData->messageHandler((WebSocket<SSL, isServer, USERDATA> *) s, std::string_view(data, length), (OpCode) opCode);
166
1.57k
                        if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
167
0
                            return true;
168
0
                        }
169
1.57k
                    }
170
171
                    /* If we shutdown or closed, this will be taken care of elsewhere */
172
1.96k
                    webSocketData->fragmentBuffer.clear();
173
1.96k
                }
174
51.5k
            }
175
65.3k
        } else {
176
            /* Control frames need the websocket to send pings, pongs and close */
177
20.2k
            WebSocket<SSL, isServer, USERDATA> *webSocket = (WebSocket<SSL, isServer, USERDATA> *) s;
178
179
20.2k
            if (!remainingBytes && fin && !webSocketData->controlTipLength) {
180
12.3k
                if (opCode == CLOSE) {
181
4.15k
                    auto closeFrame = protocol::parseClosePayload(data, length);
182
4.15k
                    webSocket->end(closeFrame.code, std::string_view(closeFrame.message, closeFrame.length));
183
4.15k
                    return true;
184
8.19k
                } else {
185
8.19k
                    if (opCode == PING) {
186
7.47k
                        webSocket->send(std::string_view(data, length), (OpCode) OpCode::PONG);
187
7.47k
                        if (webSocketContextData->pingHandler) {
188
7.22k
                            webSocketContextData->pingHandler(webSocket, {data, length});
189
7.22k
                            if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
190
0
                                return true;
191
0
                            }
192
7.22k
                        }
193
7.47k
                    } else if (opCode == PONG) {
194
720
                        if (webSocketContextData->pongHandler) {
195
509
                            webSocketContextData->pongHandler(webSocket, {data, length});
196
509
                            if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
197
0
                                return true;
198
0
                            }
199
509
                        }
200
720
                    }
201
8.19k
                }
202
12.3k
            } else {
203
                /* Here we never mind any size optimizations as we are in the worst possible path */
204
7.88k
                webSocketData->fragmentBuffer.append(data, length);
205
7.88k
                webSocketData->controlTipLength += (unsigned int) length;
206
207
7.88k
                if (!remainingBytes && fin) {
208
3.57k
                    char *controlBuffer = (char *) webSocketData->fragmentBuffer.data() + webSocketData->fragmentBuffer.length() - webSocketData->controlTipLength;
209
3.57k
                    if (opCode == CLOSE) {
210
1.59k
                        protocol::CloseFrame closeFrame = protocol::parseClosePayload(controlBuffer, webSocketData->controlTipLength);
211
1.59k
                        webSocket->end(closeFrame.code, std::string_view(closeFrame.message, closeFrame.length));
212
1.59k
                        return true;
213
1.98k
                    } else {
214
1.98k
                        if (opCode == PING) {
215
613
                            webSocket->send(std::string_view(controlBuffer, webSocketData->controlTipLength), (OpCode) OpCode::PONG);
216
613
                            if (webSocketContextData->pingHandler) {
217
410
                                webSocketContextData->pingHandler(webSocket, std::string_view(controlBuffer, webSocketData->controlTipLength));
218
410
                                if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
219
0
                                    return true;
220
0
                                }
221
410
                            }
222
1.36k
                        } else if (opCode == PONG) {
223
1.36k
                            if (webSocketContextData->pongHandler) {
224
556
                                webSocketContextData->pongHandler(webSocket, std::string_view(controlBuffer, webSocketData->controlTipLength));
225
556
                                if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
226
0
                                    return true;
227
0
                                }
228
556
                            }
229
1.36k
                        }
230
1.98k
                    }
231
232
                    /* Same here, we do not care for any particular smart allocation scheme */
233
1.98k
                    webSocketData->fragmentBuffer.resize((unsigned int) webSocketData->fragmentBuffer.length() - webSocketData->controlTipLength);
234
1.98k
                    webSocketData->controlTipLength = 0;
235
1.98k
                }
236
7.88k
            }
237
20.2k
        }
238
76.5k
        return false;
239
85.5k
    }
EpollEchoServer.cpp:uWS::WebSocketContext<false, true, test()::PerSocketData>::handleFragment(char*, unsigned long, unsigned int, int, bool, uWS::WebSocketState<true>*, void*)
Line
Count
Source
60
130k
    static bool handleFragment(char *data, size_t length, unsigned int remainingBytes, int opCode, bool fin, WebSocketState<isServer> *webSocketState, void *s) {
61
        /* WebSocketData and WebSocketContextData */
62
130k
        WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
63
130k
        WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) s);
64
65
        /* Is this a non-control frame? */
66
130k
        if (opCode < 3) {
67
            /* Did we get everything in one go? */
68
107k
            if (!remainingBytes && fin && !webSocketData->fragmentBuffer.length()) {
69
70
                /* Handle compressed frame */
71
89.6k
                if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::COMPRESSED_FRAME) {
72
566
                        webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED;
73
74
566
                        LoopData *loopData = (LoopData *) us_loop_ext(us_socket_context_loop(SSL, us_socket_context(SSL, (us_socket_t *) s)));
75
                        /* Decompress using shared or dedicated decompressor */
76
566
                        std::optional<std::string_view> inflatedFrame;
77
566
                        if (webSocketData->inflationStream) {
78
0
                            inflatedFrame = webSocketData->inflationStream->inflate(loopData->zlibContext, {data, length}, webSocketContextData->maxPayloadLength, false);
79
566
                        } else {
80
566
                            inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {data, length}, webSocketContextData->maxPayloadLength, true);
81
566
                        }
82
83
566
                        if (!inflatedFrame.has_value()) {
84
0
                            forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE_INFLATION);
85
0
                            return true;
86
566
                        } else {
87
566
                            data = (char *) inflatedFrame->data();
88
566
                            length = inflatedFrame->length();
89
566
                        }
90
566
                }
91
92
                /* Check text messages for Utf-8 validity */
93
89.6k
                if (opCode == 1 && !protocol::isValidUtf8((unsigned char *) data, length)) {
94
4.29k
                    forceClose(webSocketState, s, ERR_INVALID_TEXT);
95
4.29k
                    return true;
96
4.29k
                }
97
98
                /* Emit message event & break if we are closed or shut down when returning */
99
85.3k
                if (webSocketContextData->messageHandler) {
100
85.3k
                    webSocketContextData->messageHandler((WebSocket<SSL, isServer, USERDATA> *) s, std::string_view(data, length), (OpCode) opCode);
101
85.3k
                    if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
102
923
                        return true;
103
923
                    }
104
85.3k
                }
105
85.3k
            } else {
106
                /* Allocate fragment buffer up front first time */
107
17.5k
                if (!webSocketData->fragmentBuffer.length()) {
108
9.99k
                    webSocketData->fragmentBuffer.reserve(length + remainingBytes);
109
9.99k
                }
110
                /* Fragments forming a big message are not caught until appending them */
111
17.5k
                if (refusePayloadLength(length + webSocketData->fragmentBuffer.length(), webSocketState, s)) {
112
287
                    forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE);
113
287
                    return true;
114
287
                }
115
17.2k
                webSocketData->fragmentBuffer.append(data, length);
116
117
                /* Are we done now? */
118
                // todo: what if we don't have any remaining bytes yet we are not fin? forceclose!
119
17.2k
                if (!remainingBytes && fin) {
120
121
                    /* Handle compression */
122
3.23k
                    if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::COMPRESSED_FRAME) {
123
1.16k
                            webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED;
124
125
                            /* 9 bytes of padding for libdeflate, 4 for zlib */
126
1.16k
                            webSocketData->fragmentBuffer.append("123456789");
127
128
1.16k
                            LoopData *loopData = (LoopData *) us_loop_ext(
129
1.16k
                                us_socket_context_loop(SSL,
130
1.16k
                                    us_socket_context(SSL, (us_socket_t *) s)
131
1.16k
                                )
132
1.16k
                            );
133
134
                            /* Decompress using shared or dedicated decompressor */
135
1.16k
                            std::optional<std::string_view> inflatedFrame;
136
1.16k
                            if (webSocketData->inflationStream) {
137
0
                                inflatedFrame = webSocketData->inflationStream->inflate(loopData->zlibContext, {webSocketData->fragmentBuffer.data(), webSocketData->fragmentBuffer.length() - 9}, webSocketContextData->maxPayloadLength, false);
138
1.16k
                            } else {
139
1.16k
                                inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {webSocketData->fragmentBuffer.data(), webSocketData->fragmentBuffer.length() - 9}, webSocketContextData->maxPayloadLength, true);
140
1.16k
                            }
141
142
1.16k
                            if (!inflatedFrame.has_value()) {
143
0
                                forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE_INFLATION);
144
0
                                return true;
145
1.16k
                            } else {
146
1.16k
                                data = (char *) inflatedFrame->data();
147
1.16k
                                length = inflatedFrame->length();
148
1.16k
                            }
149
150
151
2.06k
                    } else {
152
                        // reset length and data ptrs
153
2.06k
                        length = webSocketData->fragmentBuffer.length();
154
2.06k
                        data = webSocketData->fragmentBuffer.data();
155
2.06k
                    }
156
157
                    /* Check text messages for Utf-8 validity */
158
3.23k
                    if (opCode == 1 && !protocol::isValidUtf8((unsigned char *) data, length)) {
159
275
                        forceClose(webSocketState, s, ERR_INVALID_TEXT);
160
275
                        return true;
161
275
                    }
162
163
                    /* Emit message and check for shutdown or close */
164
2.96k
                    if (webSocketContextData->messageHandler) {
165
2.96k
                        webSocketContextData->messageHandler((WebSocket<SSL, isServer, USERDATA> *) s, std::string_view(data, length), (OpCode) opCode);
166
2.96k
                        if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
167
389
                            return true;
168
389
                        }
169
2.96k
                    }
170
171
                    /* If we shutdown or closed, this will be taken care of elsewhere */
172
2.57k
                    webSocketData->fragmentBuffer.clear();
173
2.57k
                }
174
17.2k
            }
175
107k
        } else {
176
            /* Control frames need the websocket to send pings, pongs and close */
177
23.2k
            WebSocket<SSL, isServer, USERDATA> *webSocket = (WebSocket<SSL, isServer, USERDATA> *) s;
178
179
23.2k
            if (!remainingBytes && fin && !webSocketData->controlTipLength) {
180
15.9k
                if (opCode == CLOSE) {
181
5.48k
                    auto closeFrame = protocol::parseClosePayload(data, length);
182
5.48k
                    webSocket->end(closeFrame.code, std::string_view(closeFrame.message, closeFrame.length));
183
5.48k
                    return true;
184
10.4k
                } else {
185
10.4k
                    if (opCode == PING) {
186
9.27k
                        webSocket->send(std::string_view(data, length), (OpCode) OpCode::PONG);
187
9.27k
                        if (webSocketContextData->pingHandler) {
188
9.27k
                            webSocketContextData->pingHandler(webSocket, {data, length});
189
9.27k
                            if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
190
0
                                return true;
191
0
                            }
192
9.27k
                        }
193
9.27k
                    } else if (opCode == PONG) {
194
1.18k
                        if (webSocketContextData->pongHandler) {
195
1.18k
                            webSocketContextData->pongHandler(webSocket, {data, length});
196
1.18k
                            if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
197
0
                                return true;
198
0
                            }
199
1.18k
                        }
200
1.18k
                    }
201
10.4k
                }
202
15.9k
            } else {
203
                /* Here we never mind any size optimizations as we are in the worst possible path */
204
7.26k
                webSocketData->fragmentBuffer.append(data, length);
205
7.26k
                webSocketData->controlTipLength += (unsigned int) length;
206
207
7.26k
                if (!remainingBytes && fin) {
208
3.28k
                    char *controlBuffer = (char *) webSocketData->fragmentBuffer.data() + webSocketData->fragmentBuffer.length() - webSocketData->controlTipLength;
209
3.28k
                    if (opCode == CLOSE) {
210
1.65k
                        protocol::CloseFrame closeFrame = protocol::parseClosePayload(controlBuffer, webSocketData->controlTipLength);
211
1.65k
                        webSocket->end(closeFrame.code, std::string_view(closeFrame.message, closeFrame.length));
212
1.65k
                        return true;
213
1.65k
                    } else {
214
1.63k
                        if (opCode == PING) {
215
222
                            webSocket->send(std::string_view(controlBuffer, webSocketData->controlTipLength), (OpCode) OpCode::PONG);
216
222
                            if (webSocketContextData->pingHandler) {
217
222
                                webSocketContextData->pingHandler(webSocket, std::string_view(controlBuffer, webSocketData->controlTipLength));
218
222
                                if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
219
0
                                    return true;
220
0
                                }
221
222
                            }
222
1.40k
                        } else if (opCode == PONG) {
223
1.40k
                            if (webSocketContextData->pongHandler) {
224
1.40k
                                webSocketContextData->pongHandler(webSocket, std::string_view(controlBuffer, webSocketData->controlTipLength));
225
1.40k
                                if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
226
0
                                    return true;
227
0
                                }
228
1.40k
                            }
229
1.40k
                        }
230
1.63k
                    }
231
232
                    /* Same here, we do not care for any particular smart allocation scheme */
233
1.63k
                    webSocketData->fragmentBuffer.resize((unsigned int) webSocketData->fragmentBuffer.length() - webSocketData->controlTipLength);
234
1.63k
                    webSocketData->controlTipLength = 0;
235
1.63k
                }
236
7.26k
            }
237
23.2k
        }
238
117k
        return false;
239
130k
    }
240
241
1.30M
    static bool refusePayloadLength(uint64_t length, WebSocketState<isServer> */*wState*/, void *s) {
242
1.30M
        auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
243
244
        /* Return true for refuse, false for accept */
245
1.30M
        return webSocketContextData->maxPayloadLength < length;
246
1.30M
    }
EpollEchoServerPubSub.cpp:uWS::WebSocketContext<true, true, test()::PerSocketData>::refusePayloadLength(unsigned long, uWS::WebSocketState<true>*, void*)
Line
Count
Source
241
1.06M
    static bool refusePayloadLength(uint64_t length, WebSocketState<isServer> */*wState*/, void *s) {
242
1.06M
        auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
243
244
        /* Return true for refuse, false for accept */
245
1.06M
        return webSocketContextData->maxPayloadLength < length;
246
1.06M
    }
EpollHelloWorld.cpp:uWS::WebSocketContext<false, true, test()::PerSocketData>::refusePayloadLength(unsigned long, uWS::WebSocketState<true>*, void*)
Line
Count
Source
241
94.5k
    static bool refusePayloadLength(uint64_t length, WebSocketState<isServer> */*wState*/, void *s) {
242
94.5k
        auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
243
244
        /* Return true for refuse, false for accept */
245
94.5k
        return webSocketContextData->maxPayloadLength < length;
246
94.5k
    }
EpollEchoServer.cpp:uWS::WebSocketContext<false, true, test()::PerSocketData>::refusePayloadLength(unsigned long, uWS::WebSocketState<true>*, void*)
Line
Count
Source
241
140k
    static bool refusePayloadLength(uint64_t length, WebSocketState<isServer> */*wState*/, void *s) {
242
140k
        auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
243
244
        /* Return true for refuse, false for accept */
245
140k
        return webSocketContextData->maxPayloadLength < length;
246
140k
    }
247
248
33.2k
    WebSocketContext<SSL, isServer, USERDATA> *init() {
249
        /* Adopting a socket does not trigger open event.
250
         * We arreive as WebSocket with timeout set and
251
         * any backpressure from HTTP state kept. */
252
253
        /* Handle socket disconnections */
254
338k
        us_socket_context_on_close(SSL, getSocketContext(), [](auto *s, int code, void *reason) {
255
            /* For whatever reason, if we already have emitted close event, do not emit it again */
256
338k
            WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
257
338k
            if (!webSocketData->isShuttingDown) {
258
                /* Emit close event */
259
313k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
260
261
                /* At this point we iterate all currently held subscriptions and emit an event for all of them */
262
313k
                if (webSocketData->subscriber && webSocketContextData->subscriptionHandler) {
263
0
                    for (Topic *t : webSocketData->subscriber->topics) {
264
0
                        webSocketContextData->subscriptionHandler((WebSocket<SSL, isServer, USERDATA> *) s, t->name, (int) t->size() - 1, (int) t->size());
265
0
                    }
266
0
                }
267
268
                /* Make sure to unsubscribe from any pub/sub node at exit */
269
313k
                webSocketContextData->topicTree->freeSubscriber(webSocketData->subscriber);
270
313k
                webSocketData->subscriber = nullptr;
271
272
313k
                auto *ws = (WebSocket<SSL, isServer, USERDATA> *) s;
273
313k
                if (webSocketContextData->closeHandler) {
274
311k
                    webSocketContextData->closeHandler(ws, 1006, {(char *) reason, (size_t) code});
275
311k
                }
276
313k
                ((USERDATA *) ws->getUserData())->~USERDATA();
277
313k
            }
278
279
            /* Destruct in-placed data struct */
280
338k
            webSocketData->~WebSocketData();
281
282
338k
            return s;
283
338k
        });
EpollEchoServerPubSub.cpp:auto uWS::WebSocketContext<true, true, test()::PerSocketData>::init()::{lambda(auto:1*, int, void*)#1}::operator()<us_socket_t>(us_socket_t*, int, void*) const
Line
Count
Source
254
99.0k
        us_socket_context_on_close(SSL, getSocketContext(), [](auto *s, int code, void *reason) {
255
            /* For whatever reason, if we already have emitted close event, do not emit it again */
256
99.0k
            WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
257
99.0k
            if (!webSocketData->isShuttingDown) {
258
                /* Emit close event */
259
89.1k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
260
261
                /* At this point we iterate all currently held subscriptions and emit an event for all of them */
262
89.1k
                if (webSocketData->subscriber && webSocketContextData->subscriptionHandler) {
263
0
                    for (Topic *t : webSocketData->subscriber->topics) {
264
0
                        webSocketContextData->subscriptionHandler((WebSocket<SSL, isServer, USERDATA> *) s, t->name, (int) t->size() - 1, (int) t->size());
265
0
                    }
266
0
                }
267
268
                /* Make sure to unsubscribe from any pub/sub node at exit */
269
89.1k
                webSocketContextData->topicTree->freeSubscriber(webSocketData->subscriber);
270
89.1k
                webSocketData->subscriber = nullptr;
271
272
89.1k
                auto *ws = (WebSocket<SSL, isServer, USERDATA> *) s;
273
89.1k
                if (webSocketContextData->closeHandler) {
274
89.1k
                    webSocketContextData->closeHandler(ws, 1006, {(char *) reason, (size_t) code});
275
89.1k
                }
276
89.1k
                ((USERDATA *) ws->getUserData())->~USERDATA();
277
89.1k
            }
278
279
            /* Destruct in-placed data struct */
280
99.0k
            webSocketData->~WebSocketData();
281
282
99.0k
            return s;
283
99.0k
        });
EpollHelloWorld.cpp:auto uWS::WebSocketContext<false, true, test()::PerSocketData>::init()::{lambda(auto:1*, int, void*)#1}::operator()<us_socket_t>(us_socket_t*, int, void*) const
Line
Count
Source
254
34.1k
        us_socket_context_on_close(SSL, getSocketContext(), [](auto *s, int code, void *reason) {
255
            /* For whatever reason, if we already have emitted close event, do not emit it again */
256
34.1k
            WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
257
34.1k
            if (!webSocketData->isShuttingDown) {
258
                /* Emit close event */
259
28.3k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
260
261
                /* At this point we iterate all currently held subscriptions and emit an event for all of them */
262
28.3k
                if (webSocketData->subscriber && webSocketContextData->subscriptionHandler) {
263
0
                    for (Topic *t : webSocketData->subscriber->topics) {
264
0
                        webSocketContextData->subscriptionHandler((WebSocket<SSL, isServer, USERDATA> *) s, t->name, (int) t->size() - 1, (int) t->size());
265
0
                    }
266
0
                }
267
268
                /* Make sure to unsubscribe from any pub/sub node at exit */
269
28.3k
                webSocketContextData->topicTree->freeSubscriber(webSocketData->subscriber);
270
28.3k
                webSocketData->subscriber = nullptr;
271
272
28.3k
                auto *ws = (WebSocket<SSL, isServer, USERDATA> *) s;
273
28.3k
                if (webSocketContextData->closeHandler) {
274
27.0k
                    webSocketContextData->closeHandler(ws, 1006, {(char *) reason, (size_t) code});
275
27.0k
                }
276
28.3k
                ((USERDATA *) ws->getUserData())->~USERDATA();
277
28.3k
            }
278
279
            /* Destruct in-placed data struct */
280
34.1k
            webSocketData->~WebSocketData();
281
282
34.1k
            return s;
283
34.1k
        });
EpollEchoServer.cpp:auto uWS::WebSocketContext<false, true, test()::PerSocketData>::init()::{lambda(auto:1*, int, void*)#1}::operator()<us_socket_t>(us_socket_t*, int, void*) const
Line
Count
Source
254
204k
        us_socket_context_on_close(SSL, getSocketContext(), [](auto *s, int code, void *reason) {
255
            /* For whatever reason, if we already have emitted close event, do not emit it again */
256
204k
            WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
257
204k
            if (!webSocketData->isShuttingDown) {
258
                /* Emit close event */
259
195k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
260
261
                /* At this point we iterate all currently held subscriptions and emit an event for all of them */
262
195k
                if (webSocketData->subscriber && webSocketContextData->subscriptionHandler) {
263
0
                    for (Topic *t : webSocketData->subscriber->topics) {
264
0
                        webSocketContextData->subscriptionHandler((WebSocket<SSL, isServer, USERDATA> *) s, t->name, (int) t->size() - 1, (int) t->size());
265
0
                    }
266
0
                }
267
268
                /* Make sure to unsubscribe from any pub/sub node at exit */
269
195k
                webSocketContextData->topicTree->freeSubscriber(webSocketData->subscriber);
270
195k
                webSocketData->subscriber = nullptr;
271
272
195k
                auto *ws = (WebSocket<SSL, isServer, USERDATA> *) s;
273
195k
                if (webSocketContextData->closeHandler) {
274
195k
                    webSocketContextData->closeHandler(ws, 1006, {(char *) reason, (size_t) code});
275
195k
                }
276
195k
                ((USERDATA *) ws->getUserData())->~USERDATA();
277
195k
            }
278
279
            /* Destruct in-placed data struct */
280
204k
            webSocketData->~WebSocketData();
281
282
204k
            return s;
283
204k
        });
284
285
        /* Handle WebSocket data streams */
286
214k
        us_socket_context_on_data(SSL, getSocketContext(), [](auto *s, char *data, int length) {
287
288
            /* We need the websocket data */
289
214k
            WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
290
291
            /* When in websocket shutdown mode, we do not care for ANY message, whether responding close frame or not.
292
             * We only care for the TCP FIN really, not emitting any message after closing is key */
293
214k
            if (webSocketData->isShuttingDown) {
294
1.57k
                return s;
295
1.57k
            }
296
297
213k
            auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
298
213k
            auto *asyncSocket = (AsyncSocket<SSL> *) s;
299
300
            /* Every time we get data and not in shutdown state we simply reset the timeout */
301
213k
            asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
302
213k
            webSocketData->hasTimedOut = false;
303
304
            /* We always cork on data */
305
213k
            asyncSocket->cork();
306
307
            /* This parser has virtually no overhead */
308
213k
            WebSocketProtocol<isServer, WebSocketContext<SSL, isServer, USERDATA>>::consume(data, (unsigned int) length, (WebSocketState<isServer> *) webSocketData, s);
309
310
            /* Uncorking a closed socekt is fine, in fact it is needed */
311
213k
            asyncSocket->uncork();
312
313
            /* If uncorking was successful and we are in shutdown state then send TCP FIN */
314
213k
            if (asyncSocket->getBufferedAmount() == 0) {
315
                /* We can now be in shutdown state */
316
49.0k
                if (webSocketData->isShuttingDown) {
317
                    /* Shutting down a closed socket is handled by uSockets and just fine */
318
3.69k
                    asyncSocket->shutdown();
319
3.69k
                }
320
49.0k
            }
321
322
213k
            return s;
323
214k
        });
EpollEchoServerPubSub.cpp:auto uWS::WebSocketContext<true, true, test()::PerSocketData>::init()::{lambda(auto:1*, char*, int)#1}::operator()<us_socket_t>(us_socket_t*, char*, int) const
Line
Count
Source
286
83.7k
        us_socket_context_on_data(SSL, getSocketContext(), [](auto *s, char *data, int length) {
287
288
            /* We need the websocket data */
289
83.7k
            WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
290
291
            /* When in websocket shutdown mode, we do not care for ANY message, whether responding close frame or not.
292
             * We only care for the TCP FIN really, not emitting any message after closing is key */
293
83.7k
            if (webSocketData->isShuttingDown) {
294
799
                return s;
295
799
            }
296
297
82.9k
            auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
298
82.9k
            auto *asyncSocket = (AsyncSocket<SSL> *) s;
299
300
            /* Every time we get data and not in shutdown state we simply reset the timeout */
301
82.9k
            asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
302
82.9k
            webSocketData->hasTimedOut = false;
303
304
            /* We always cork on data */
305
82.9k
            asyncSocket->cork();
306
307
            /* This parser has virtually no overhead */
308
82.9k
            WebSocketProtocol<isServer, WebSocketContext<SSL, isServer, USERDATA>>::consume(data, (unsigned int) length, (WebSocketState<isServer> *) webSocketData, s);
309
310
            /* Uncorking a closed socekt is fine, in fact it is needed */
311
82.9k
            asyncSocket->uncork();
312
313
            /* If uncorking was successful and we are in shutdown state then send TCP FIN */
314
82.9k
            if (asyncSocket->getBufferedAmount() == 0) {
315
                /* We can now be in shutdown state */
316
6.34k
                if (webSocketData->isShuttingDown) {
317
                    /* Shutting down a closed socket is handled by uSockets and just fine */
318
1.45k
                    asyncSocket->shutdown();
319
1.45k
                }
320
6.34k
            }
321
322
82.9k
            return s;
323
83.7k
        });
EpollHelloWorld.cpp:auto uWS::WebSocketContext<false, true, test()::PerSocketData>::init()::{lambda(auto:1*, char*, int)#1}::operator()<us_socket_t>(us_socket_t*, char*, int) const
Line
Count
Source
286
63.7k
        us_socket_context_on_data(SSL, getSocketContext(), [](auto *s, char *data, int length) {
287
288
            /* We need the websocket data */
289
63.7k
            WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
290
291
            /* When in websocket shutdown mode, we do not care for ANY message, whether responding close frame or not.
292
             * We only care for the TCP FIN really, not emitting any message after closing is key */
293
63.7k
            if (webSocketData->isShuttingDown) {
294
388
                return s;
295
388
            }
296
297
63.3k
            auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
298
63.3k
            auto *asyncSocket = (AsyncSocket<SSL> *) s;
299
300
            /* Every time we get data and not in shutdown state we simply reset the timeout */
301
63.3k
            asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
302
63.3k
            webSocketData->hasTimedOut = false;
303
304
            /* We always cork on data */
305
63.3k
            asyncSocket->cork();
306
307
            /* This parser has virtually no overhead */
308
63.3k
            WebSocketProtocol<isServer, WebSocketContext<SSL, isServer, USERDATA>>::consume(data, (unsigned int) length, (WebSocketState<isServer> *) webSocketData, s);
309
310
            /* Uncorking a closed socekt is fine, in fact it is needed */
311
63.3k
            asyncSocket->uncork();
312
313
            /* If uncorking was successful and we are in shutdown state then send TCP FIN */
314
63.3k
            if (asyncSocket->getBufferedAmount() == 0) {
315
                /* We can now be in shutdown state */
316
31.7k
                if (webSocketData->isShuttingDown) {
317
                    /* Shutting down a closed socket is handled by uSockets and just fine */
318
1.13k
                    asyncSocket->shutdown();
319
1.13k
                }
320
31.7k
            }
321
322
63.3k
            return s;
323
63.7k
        });
EpollEchoServer.cpp:auto uWS::WebSocketContext<false, true, test()::PerSocketData>::init()::{lambda(auto:1*, char*, int)#1}::operator()<us_socket_t>(us_socket_t*, char*, int) const
Line
Count
Source
286
67.4k
        us_socket_context_on_data(SSL, getSocketContext(), [](auto *s, char *data, int length) {
287
288
            /* We need the websocket data */
289
67.4k
            WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
290
291
            /* When in websocket shutdown mode, we do not care for ANY message, whether responding close frame or not.
292
             * We only care for the TCP FIN really, not emitting any message after closing is key */
293
67.4k
            if (webSocketData->isShuttingDown) {
294
390
                return s;
295
390
            }
296
297
67.1k
            auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
298
67.1k
            auto *asyncSocket = (AsyncSocket<SSL> *) s;
299
300
            /* Every time we get data and not in shutdown state we simply reset the timeout */
301
67.1k
            asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
302
67.1k
            webSocketData->hasTimedOut = false;
303
304
            /* We always cork on data */
305
67.1k
            asyncSocket->cork();
306
307
            /* This parser has virtually no overhead */
308
67.1k
            WebSocketProtocol<isServer, WebSocketContext<SSL, isServer, USERDATA>>::consume(data, (unsigned int) length, (WebSocketState<isServer> *) webSocketData, s);
309
310
            /* Uncorking a closed socekt is fine, in fact it is needed */
311
67.1k
            asyncSocket->uncork();
312
313
            /* If uncorking was successful and we are in shutdown state then send TCP FIN */
314
67.1k
            if (asyncSocket->getBufferedAmount() == 0) {
315
                /* We can now be in shutdown state */
316
10.8k
                if (webSocketData->isShuttingDown) {
317
                    /* Shutting down a closed socket is handled by uSockets and just fine */
318
1.11k
                    asyncSocket->shutdown();
319
1.11k
                }
320
10.8k
            }
321
322
67.1k
            return s;
323
67.4k
        });
324
325
        /* Handle HTTP write out (note: SSL_read may trigger this spuriously, the app need to handle spurious calls) */
326
92.8k
        us_socket_context_on_writable(SSL, getSocketContext(), [](auto *s) {
327
328
            /* NOTE: Are we called here corked? If so, the below write code is broken, since
329
             * we will have 0 as getBufferedAmount due to writing to cork buffer, then sending TCP FIN before
330
             * we actually uncorked and sent off things */
331
332
            /* It makes sense to check for us_is_shut_down here and return if so, to avoid shutting down twice */
333
92.8k
            if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) {
334
0
                return s;
335
0
            }
336
337
92.8k
            AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
338
92.8k
            WebSocketData *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
339
340
            /* We store old backpressure since it is unclear whether write drained anything,
341
             * however, in case of coming here with 0 backpressure we still need to emit drain event */
342
92.8k
            unsigned int backpressure = asyncSocket->getBufferedAmount();
343
344
            /* Drain as much as possible */
345
92.8k
            asyncSocket->write(nullptr, 0);
346
347
            /* Behavior: if we actively drain backpressure, always reset timeout (even if we are in shutdown) */
348
            /* Also reset timeout if we came here with 0 backpressure */
349
92.8k
            if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
350
52.7k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
351
52.7k
                asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
352
52.7k
                webSocketData->hasTimedOut = false;
353
52.7k
            }
354
355
            /* Are we in (WebSocket) shutdown mode? */
356
92.8k
            if (webSocketData->isShuttingDown) {
357
                /* Check if we just now drained completely */
358
5.07k
                if (asyncSocket->getBufferedAmount() == 0) {
359
                    /* Now perform the actual TCP/TLS shutdown which was postponed due to backpressure */
360
911
                    asyncSocket->shutdown();
361
911
                }
362
87.7k
            } else if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
363
                /* Only call drain if we actually drained backpressure or if we came here with 0 backpressure */
364
50.8k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
365
50.8k
                if (webSocketContextData->drainHandler) {
366
50.5k
                    webSocketContextData->drainHandler((WebSocket<SSL, isServer, USERDATA> *) s);
367
50.5k
                }
368
                /* No need to check for closed here as we leave the handler immediately*/
369
50.8k
            }
370
371
92.8k
            return s;
372
92.8k
        });
EpollEchoServerPubSub.cpp:auto uWS::WebSocketContext<true, true, test()::PerSocketData>::init()::{lambda(auto:1*)#1}::operator()<us_socket_t>(us_socket_t*) const
Line
Count
Source
326
13.3k
        us_socket_context_on_writable(SSL, getSocketContext(), [](auto *s) {
327
328
            /* NOTE: Are we called here corked? If so, the below write code is broken, since
329
             * we will have 0 as getBufferedAmount due to writing to cork buffer, then sending TCP FIN before
330
             * we actually uncorked and sent off things */
331
332
            /* It makes sense to check for us_is_shut_down here and return if so, to avoid shutting down twice */
333
13.3k
            if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) {
334
0
                return s;
335
0
            }
336
337
13.3k
            AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
338
13.3k
            WebSocketData *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
339
340
            /* We store old backpressure since it is unclear whether write drained anything,
341
             * however, in case of coming here with 0 backpressure we still need to emit drain event */
342
13.3k
            unsigned int backpressure = asyncSocket->getBufferedAmount();
343
344
            /* Drain as much as possible */
345
13.3k
            asyncSocket->write(nullptr, 0);
346
347
            /* Behavior: if we actively drain backpressure, always reset timeout (even if we are in shutdown) */
348
            /* Also reset timeout if we came here with 0 backpressure */
349
13.3k
            if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
350
7.43k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
351
7.43k
                asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
352
7.43k
                webSocketData->hasTimedOut = false;
353
7.43k
            }
354
355
            /* Are we in (WebSocket) shutdown mode? */
356
13.3k
            if (webSocketData->isShuttingDown) {
357
                /* Check if we just now drained completely */
358
2.86k
                if (asyncSocket->getBufferedAmount() == 0) {
359
                    /* Now perform the actual TCP/TLS shutdown which was postponed due to backpressure */
360
378
                    asyncSocket->shutdown();
361
378
                }
362
10.4k
            } else if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
363
                /* Only call drain if we actually drained backpressure or if we came here with 0 backpressure */
364
6.73k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
365
6.73k
                if (webSocketContextData->drainHandler) {
366
6.73k
                    webSocketContextData->drainHandler((WebSocket<SSL, isServer, USERDATA> *) s);
367
6.73k
                }
368
                /* No need to check for closed here as we leave the handler immediately*/
369
6.73k
            }
370
371
13.3k
            return s;
372
13.3k
        });
EpollHelloWorld.cpp:auto uWS::WebSocketContext<false, true, test()::PerSocketData>::init()::{lambda(auto:1*)#1}::operator()<us_socket_t>(us_socket_t*) const
Line
Count
Source
326
7.10k
        us_socket_context_on_writable(SSL, getSocketContext(), [](auto *s) {
327
328
            /* NOTE: Are we called here corked? If so, the below write code is broken, since
329
             * we will have 0 as getBufferedAmount due to writing to cork buffer, then sending TCP FIN before
330
             * we actually uncorked and sent off things */
331
332
            /* It makes sense to check for us_is_shut_down here and return if so, to avoid shutting down twice */
333
7.10k
            if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) {
334
0
                return s;
335
0
            }
336
337
7.10k
            AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
338
7.10k
            WebSocketData *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
339
340
            /* We store old backpressure since it is unclear whether write drained anything,
341
             * however, in case of coming here with 0 backpressure we still need to emit drain event */
342
7.10k
            unsigned int backpressure = asyncSocket->getBufferedAmount();
343
344
            /* Drain as much as possible */
345
7.10k
            asyncSocket->write(nullptr, 0);
346
347
            /* Behavior: if we actively drain backpressure, always reset timeout (even if we are in shutdown) */
348
            /* Also reset timeout if we came here with 0 backpressure */
349
7.10k
            if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
350
4.53k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
351
4.53k
                asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
352
4.53k
                webSocketData->hasTimedOut = false;
353
4.53k
            }
354
355
            /* Are we in (WebSocket) shutdown mode? */
356
7.10k
            if (webSocketData->isShuttingDown) {
357
                /* Check if we just now drained completely */
358
974
                if (asyncSocket->getBufferedAmount() == 0) {
359
                    /* Now perform the actual TCP/TLS shutdown which was postponed due to backpressure */
360
202
                    asyncSocket->shutdown();
361
202
                }
362
6.12k
            } else if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
363
                /* Only call drain if we actually drained backpressure or if we came here with 0 backpressure */
364
4.05k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
365
4.05k
                if (webSocketContextData->drainHandler) {
366
3.77k
                    webSocketContextData->drainHandler((WebSocket<SSL, isServer, USERDATA> *) s);
367
3.77k
                }
368
                /* No need to check for closed here as we leave the handler immediately*/
369
4.05k
            }
370
371
7.10k
            return s;
372
7.10k
        });
EpollEchoServer.cpp:auto uWS::WebSocketContext<false, true, test()::PerSocketData>::init()::{lambda(auto:1*)#1}::operator()<us_socket_t>(us_socket_t*) const
Line
Count
Source
326
72.4k
        us_socket_context_on_writable(SSL, getSocketContext(), [](auto *s) {
327
328
            /* NOTE: Are we called here corked? If so, the below write code is broken, since
329
             * we will have 0 as getBufferedAmount due to writing to cork buffer, then sending TCP FIN before
330
             * we actually uncorked and sent off things */
331
332
            /* It makes sense to check for us_is_shut_down here and return if so, to avoid shutting down twice */
333
72.4k
            if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) {
334
0
                return s;
335
0
            }
336
337
72.4k
            AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
338
72.4k
            WebSocketData *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
339
340
            /* We store old backpressure since it is unclear whether write drained anything,
341
             * however, in case of coming here with 0 backpressure we still need to emit drain event */
342
72.4k
            unsigned int backpressure = asyncSocket->getBufferedAmount();
343
344
            /* Drain as much as possible */
345
72.4k
            asyncSocket->write(nullptr, 0);
346
347
            /* Behavior: if we actively drain backpressure, always reset timeout (even if we are in shutdown) */
348
            /* Also reset timeout if we came here with 0 backpressure */
349
72.4k
            if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
350
40.7k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
351
40.7k
                asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
352
40.7k
                webSocketData->hasTimedOut = false;
353
40.7k
            }
354
355
            /* Are we in (WebSocket) shutdown mode? */
356
72.4k
            if (webSocketData->isShuttingDown) {
357
                /* Check if we just now drained completely */
358
1.24k
                if (asyncSocket->getBufferedAmount() == 0) {
359
                    /* Now perform the actual TCP/TLS shutdown which was postponed due to backpressure */
360
331
                    asyncSocket->shutdown();
361
331
                }
362
71.1k
            } else if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
363
                /* Only call drain if we actually drained backpressure or if we came here with 0 backpressure */
364
40.0k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
365
40.0k
                if (webSocketContextData->drainHandler) {
366
40.0k
                    webSocketContextData->drainHandler((WebSocket<SSL, isServer, USERDATA> *) s);
367
40.0k
                }
368
                /* No need to check for closed here as we leave the handler immediately*/
369
40.0k
            }
370
371
72.4k
            return s;
372
72.4k
        });
373
374
        /* Handle FIN, WebSocket does not support half-closed sockets, so simply close */
375
33.2k
        us_socket_context_on_end(SSL, getSocketContext(), [](auto *s) {
376
377
            /* If we get a fin, we just close I guess */
378
7.17k
            us_socket_close(SSL, (us_socket_t *) s, (int) ERR_TCP_FIN.length(), (void *) ERR_TCP_FIN.data());
379
380
7.17k
            return s;
381
7.17k
        });
EpollEchoServerPubSub.cpp:auto uWS::WebSocketContext<true, true, test()::PerSocketData>::init()::{lambda(auto:1*)#2}::operator()<us_socket_t>(us_socket_t*) const
Line
Count
Source
375
1.36k
        us_socket_context_on_end(SSL, getSocketContext(), [](auto *s) {
376
377
            /* If we get a fin, we just close I guess */
378
1.36k
            us_socket_close(SSL, (us_socket_t *) s, (int) ERR_TCP_FIN.length(), (void *) ERR_TCP_FIN.data());
379
380
1.36k
            return s;
381
1.36k
        });
EpollHelloWorld.cpp:auto uWS::WebSocketContext<false, true, test()::PerSocketData>::init()::{lambda(auto:1*)#2}::operator()<us_socket_t>(us_socket_t*) const
Line
Count
Source
375
270
        us_socket_context_on_end(SSL, getSocketContext(), [](auto *s) {
376
377
            /* If we get a fin, we just close I guess */
378
270
            us_socket_close(SSL, (us_socket_t *) s, (int) ERR_TCP_FIN.length(), (void *) ERR_TCP_FIN.data());
379
380
270
            return s;
381
270
        });
EpollEchoServer.cpp:auto uWS::WebSocketContext<false, true, test()::PerSocketData>::init()::{lambda(auto:1*)#2}::operator()<us_socket_t>(us_socket_t*) const
Line
Count
Source
375
5.54k
        us_socket_context_on_end(SSL, getSocketContext(), [](auto *s) {
376
377
            /* If we get a fin, we just close I guess */
378
5.54k
            us_socket_close(SSL, (us_socket_t *) s, (int) ERR_TCP_FIN.length(), (void *) ERR_TCP_FIN.data());
379
380
5.54k
            return s;
381
5.54k
        });
382
383
33.2k
        us_socket_context_on_long_timeout(SSL, getSocketContext(), [](auto *s) {
384
0
            ((WebSocket<SSL, isServer, USERDATA> *) s)->end(1000, "please reconnect");
385
386
0
            return s;
387
0
        });
Unexecuted instantiation: EpollEchoServerPubSub.cpp:auto uWS::WebSocketContext<true, true, test()::PerSocketData>::init()::{lambda(auto:1*)#3}::operator()<us_socket_t>(us_socket_t*) const
Unexecuted instantiation: EpollHelloWorld.cpp:auto uWS::WebSocketContext<false, true, test()::PerSocketData>::init()::{lambda(auto:1*)#3}::operator()<us_socket_t>(us_socket_t*) const
Unexecuted instantiation: EpollEchoServer.cpp:auto uWS::WebSocketContext<false, true, test()::PerSocketData>::init()::{lambda(auto:1*)#3}::operator()<us_socket_t>(us_socket_t*) const
388
389
        /* Handle socket timeouts, simply close them so to not confuse client with FIN */
390
33.2k
        us_socket_context_on_timeout(SSL, getSocketContext(), [](auto *s) {
391
392
31.0k
            auto *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
393
31.0k
            auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
394
395
31.0k
            if (webSocketContextData->sendPingsAutomatically && !webSocketData->isShuttingDown && !webSocketData->hasTimedOut) {
396
16.8k
                webSocketData->hasTimedOut = true;
397
16.8k
                us_socket_timeout(SSL, s, webSocketContextData->idleTimeoutComponents.second);
398
                /* Send ping without being corked */
399
16.8k
                ((AsyncSocket<SSL> *) s)->write("\x89\x00", 2);
400
16.8k
                return s;
401
16.8k
            }
402
403
            /* Timeout is very simple; we just close it */
404
            /* Warning: we happen to know forceClose will not use first parameter so pass nullptr here */
405
14.2k
            forceClose(nullptr, s, ERR_WEBSOCKET_TIMEOUT);
406
407
14.2k
            return s;
408
31.0k
        });
EpollEchoServerPubSub.cpp:auto uWS::WebSocketContext<true, true, test()::PerSocketData>::init()::{lambda(auto:1*)#4}::operator()<us_socket_t>(us_socket_t*) const
Line
Count
Source
390
197
        us_socket_context_on_timeout(SSL, getSocketContext(), [](auto *s) {
391
392
197
            auto *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
393
197
            auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
394
395
197
            if (webSocketContextData->sendPingsAutomatically && !webSocketData->isShuttingDown && !webSocketData->hasTimedOut) {
396
0
                webSocketData->hasTimedOut = true;
397
0
                us_socket_timeout(SSL, s, webSocketContextData->idleTimeoutComponents.second);
398
                /* Send ping without being corked */
399
0
                ((AsyncSocket<SSL> *) s)->write("\x89\x00", 2);
400
0
                return s;
401
0
            }
402
403
            /* Timeout is very simple; we just close it */
404
            /* Warning: we happen to know forceClose will not use first parameter so pass nullptr here */
405
197
            forceClose(nullptr, s, ERR_WEBSOCKET_TIMEOUT);
406
407
197
            return s;
408
197
        });
EpollHelloWorld.cpp:auto uWS::WebSocketContext<false, true, test()::PerSocketData>::init()::{lambda(auto:1*)#4}::operator()<us_socket_t>(us_socket_t*) const
Line
Count
Source
390
6.51k
        us_socket_context_on_timeout(SSL, getSocketContext(), [](auto *s) {
391
392
6.51k
            auto *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
393
6.51k
            auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
394
395
6.51k
            if (webSocketContextData->sendPingsAutomatically && !webSocketData->isShuttingDown && !webSocketData->hasTimedOut) {
396
2.57k
                webSocketData->hasTimedOut = true;
397
2.57k
                us_socket_timeout(SSL, s, webSocketContextData->idleTimeoutComponents.second);
398
                /* Send ping without being corked */
399
2.57k
                ((AsyncSocket<SSL> *) s)->write("\x89\x00", 2);
400
2.57k
                return s;
401
2.57k
            }
402
403
            /* Timeout is very simple; we just close it */
404
            /* Warning: we happen to know forceClose will not use first parameter so pass nullptr here */
405
3.94k
            forceClose(nullptr, s, ERR_WEBSOCKET_TIMEOUT);
406
407
3.94k
            return s;
408
6.51k
        });
EpollEchoServer.cpp:auto uWS::WebSocketContext<false, true, test()::PerSocketData>::init()::{lambda(auto:1*)#4}::operator()<us_socket_t>(us_socket_t*) const
Line
Count
Source
390
24.3k
        us_socket_context_on_timeout(SSL, getSocketContext(), [](auto *s) {
391
392
24.3k
            auto *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
393
24.3k
            auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
394
395
24.3k
            if (webSocketContextData->sendPingsAutomatically && !webSocketData->isShuttingDown && !webSocketData->hasTimedOut) {
396
14.2k
                webSocketData->hasTimedOut = true;
397
14.2k
                us_socket_timeout(SSL, s, webSocketContextData->idleTimeoutComponents.second);
398
                /* Send ping without being corked */
399
14.2k
                ((AsyncSocket<SSL> *) s)->write("\x89\x00", 2);
400
14.2k
                return s;
401
14.2k
            }
402
403
            /* Timeout is very simple; we just close it */
404
            /* Warning: we happen to know forceClose will not use first parameter so pass nullptr here */
405
10.1k
            forceClose(nullptr, s, ERR_WEBSOCKET_TIMEOUT);
406
407
10.1k
            return s;
408
24.3k
        });
409
410
33.2k
        return this;
411
33.2k
    }
EpollEchoServerPubSub.cpp:uWS::WebSocketContext<true, true, test()::PerSocketData>::init()
Line
Count
Source
248
5.74k
    WebSocketContext<SSL, isServer, USERDATA> *init() {
249
        /* Adopting a socket does not trigger open event.
250
         * We arreive as WebSocket with timeout set and
251
         * any backpressure from HTTP state kept. */
252
253
        /* Handle socket disconnections */
254
5.74k
        us_socket_context_on_close(SSL, getSocketContext(), [](auto *s, int code, void *reason) {
255
            /* For whatever reason, if we already have emitted close event, do not emit it again */
256
5.74k
            WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
257
5.74k
            if (!webSocketData->isShuttingDown) {
258
                /* Emit close event */
259
5.74k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
260
261
                /* At this point we iterate all currently held subscriptions and emit an event for all of them */
262
5.74k
                if (webSocketData->subscriber && webSocketContextData->subscriptionHandler) {
263
5.74k
                    for (Topic *t : webSocketData->subscriber->topics) {
264
5.74k
                        webSocketContextData->subscriptionHandler((WebSocket<SSL, isServer, USERDATA> *) s, t->name, (int) t->size() - 1, (int) t->size());
265
5.74k
                    }
266
5.74k
                }
267
268
                /* Make sure to unsubscribe from any pub/sub node at exit */
269
5.74k
                webSocketContextData->topicTree->freeSubscriber(webSocketData->subscriber);
270
5.74k
                webSocketData->subscriber = nullptr;
271
272
5.74k
                auto *ws = (WebSocket<SSL, isServer, USERDATA> *) s;
273
5.74k
                if (webSocketContextData->closeHandler) {
274
5.74k
                    webSocketContextData->closeHandler(ws, 1006, {(char *) reason, (size_t) code});
275
5.74k
                }
276
5.74k
                ((USERDATA *) ws->getUserData())->~USERDATA();
277
5.74k
            }
278
279
            /* Destruct in-placed data struct */
280
5.74k
            webSocketData->~WebSocketData();
281
282
5.74k
            return s;
283
5.74k
        });
284
285
        /* Handle WebSocket data streams */
286
5.74k
        us_socket_context_on_data(SSL, getSocketContext(), [](auto *s, char *data, int length) {
287
288
            /* We need the websocket data */
289
5.74k
            WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
290
291
            /* When in websocket shutdown mode, we do not care for ANY message, whether responding close frame or not.
292
             * We only care for the TCP FIN really, not emitting any message after closing is key */
293
5.74k
            if (webSocketData->isShuttingDown) {
294
5.74k
                return s;
295
5.74k
            }
296
297
5.74k
            auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
298
5.74k
            auto *asyncSocket = (AsyncSocket<SSL> *) s;
299
300
            /* Every time we get data and not in shutdown state we simply reset the timeout */
301
5.74k
            asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
302
5.74k
            webSocketData->hasTimedOut = false;
303
304
            /* We always cork on data */
305
5.74k
            asyncSocket->cork();
306
307
            /* This parser has virtually no overhead */
308
5.74k
            WebSocketProtocol<isServer, WebSocketContext<SSL, isServer, USERDATA>>::consume(data, (unsigned int) length, (WebSocketState<isServer> *) webSocketData, s);
309
310
            /* Uncorking a closed socekt is fine, in fact it is needed */
311
5.74k
            asyncSocket->uncork();
312
313
            /* If uncorking was successful and we are in shutdown state then send TCP FIN */
314
5.74k
            if (asyncSocket->getBufferedAmount() == 0) {
315
                /* We can now be in shutdown state */
316
5.74k
                if (webSocketData->isShuttingDown) {
317
                    /* Shutting down a closed socket is handled by uSockets and just fine */
318
5.74k
                    asyncSocket->shutdown();
319
5.74k
                }
320
5.74k
            }
321
322
5.74k
            return s;
323
5.74k
        });
324
325
        /* Handle HTTP write out (note: SSL_read may trigger this spuriously, the app need to handle spurious calls) */
326
5.74k
        us_socket_context_on_writable(SSL, getSocketContext(), [](auto *s) {
327
328
            /* NOTE: Are we called here corked? If so, the below write code is broken, since
329
             * we will have 0 as getBufferedAmount due to writing to cork buffer, then sending TCP FIN before
330
             * we actually uncorked and sent off things */
331
332
            /* It makes sense to check for us_is_shut_down here and return if so, to avoid shutting down twice */
333
5.74k
            if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) {
334
5.74k
                return s;
335
5.74k
            }
336
337
5.74k
            AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
338
5.74k
            WebSocketData *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
339
340
            /* We store old backpressure since it is unclear whether write drained anything,
341
             * however, in case of coming here with 0 backpressure we still need to emit drain event */
342
5.74k
            unsigned int backpressure = asyncSocket->getBufferedAmount();
343
344
            /* Drain as much as possible */
345
5.74k
            asyncSocket->write(nullptr, 0);
346
347
            /* Behavior: if we actively drain backpressure, always reset timeout (even if we are in shutdown) */
348
            /* Also reset timeout if we came here with 0 backpressure */
349
5.74k
            if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
350
5.74k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
351
5.74k
                asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
352
5.74k
                webSocketData->hasTimedOut = false;
353
5.74k
            }
354
355
            /* Are we in (WebSocket) shutdown mode? */
356
5.74k
            if (webSocketData->isShuttingDown) {
357
                /* Check if we just now drained completely */
358
5.74k
                if (asyncSocket->getBufferedAmount() == 0) {
359
                    /* Now perform the actual TCP/TLS shutdown which was postponed due to backpressure */
360
5.74k
                    asyncSocket->shutdown();
361
5.74k
                }
362
5.74k
            } else if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
363
                /* Only call drain if we actually drained backpressure or if we came here with 0 backpressure */
364
5.74k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
365
5.74k
                if (webSocketContextData->drainHandler) {
366
5.74k
                    webSocketContextData->drainHandler((WebSocket<SSL, isServer, USERDATA> *) s);
367
5.74k
                }
368
                /* No need to check for closed here as we leave the handler immediately*/
369
5.74k
            }
370
371
5.74k
            return s;
372
5.74k
        });
373
374
        /* Handle FIN, WebSocket does not support half-closed sockets, so simply close */
375
5.74k
        us_socket_context_on_end(SSL, getSocketContext(), [](auto *s) {
376
377
            /* If we get a fin, we just close I guess */
378
5.74k
            us_socket_close(SSL, (us_socket_t *) s, (int) ERR_TCP_FIN.length(), (void *) ERR_TCP_FIN.data());
379
380
5.74k
            return s;
381
5.74k
        });
382
383
5.74k
        us_socket_context_on_long_timeout(SSL, getSocketContext(), [](auto *s) {
384
5.74k
            ((WebSocket<SSL, isServer, USERDATA> *) s)->end(1000, "please reconnect");
385
386
5.74k
            return s;
387
5.74k
        });
388
389
        /* Handle socket timeouts, simply close them so to not confuse client with FIN */
390
5.74k
        us_socket_context_on_timeout(SSL, getSocketContext(), [](auto *s) {
391
392
5.74k
            auto *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
393
5.74k
            auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
394
395
5.74k
            if (webSocketContextData->sendPingsAutomatically && !webSocketData->isShuttingDown && !webSocketData->hasTimedOut) {
396
5.74k
                webSocketData->hasTimedOut = true;
397
5.74k
                us_socket_timeout(SSL, s, webSocketContextData->idleTimeoutComponents.second);
398
                /* Send ping without being corked */
399
5.74k
                ((AsyncSocket<SSL> *) s)->write("\x89\x00", 2);
400
5.74k
                return s;
401
5.74k
            }
402
403
            /* Timeout is very simple; we just close it */
404
            /* Warning: we happen to know forceClose will not use first parameter so pass nullptr here */
405
5.74k
            forceClose(nullptr, s, ERR_WEBSOCKET_TIMEOUT);
406
407
5.74k
            return s;
408
5.74k
        });
409
410
5.74k
        return this;
411
5.74k
    }
EpollHelloWorld.cpp:uWS::WebSocketContext<false, true, test()::PerSocketData>::init()
Line
Count
Source
248
13.6k
    WebSocketContext<SSL, isServer, USERDATA> *init() {
249
        /* Adopting a socket does not trigger open event.
250
         * We arreive as WebSocket with timeout set and
251
         * any backpressure from HTTP state kept. */
252
253
        /* Handle socket disconnections */
254
13.6k
        us_socket_context_on_close(SSL, getSocketContext(), [](auto *s, int code, void *reason) {
255
            /* For whatever reason, if we already have emitted close event, do not emit it again */
256
13.6k
            WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
257
13.6k
            if (!webSocketData->isShuttingDown) {
258
                /* Emit close event */
259
13.6k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
260
261
                /* At this point we iterate all currently held subscriptions and emit an event for all of them */
262
13.6k
                if (webSocketData->subscriber && webSocketContextData->subscriptionHandler) {
263
13.6k
                    for (Topic *t : webSocketData->subscriber->topics) {
264
13.6k
                        webSocketContextData->subscriptionHandler((WebSocket<SSL, isServer, USERDATA> *) s, t->name, (int) t->size() - 1, (int) t->size());
265
13.6k
                    }
266
13.6k
                }
267
268
                /* Make sure to unsubscribe from any pub/sub node at exit */
269
13.6k
                webSocketContextData->topicTree->freeSubscriber(webSocketData->subscriber);
270
13.6k
                webSocketData->subscriber = nullptr;
271
272
13.6k
                auto *ws = (WebSocket<SSL, isServer, USERDATA> *) s;
273
13.6k
                if (webSocketContextData->closeHandler) {
274
13.6k
                    webSocketContextData->closeHandler(ws, 1006, {(char *) reason, (size_t) code});
275
13.6k
                }
276
13.6k
                ((USERDATA *) ws->getUserData())->~USERDATA();
277
13.6k
            }
278
279
            /* Destruct in-placed data struct */
280
13.6k
            webSocketData->~WebSocketData();
281
282
13.6k
            return s;
283
13.6k
        });
284
285
        /* Handle WebSocket data streams */
286
13.6k
        us_socket_context_on_data(SSL, getSocketContext(), [](auto *s, char *data, int length) {
287
288
            /* We need the websocket data */
289
13.6k
            WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
290
291
            /* When in websocket shutdown mode, we do not care for ANY message, whether responding close frame or not.
292
             * We only care for the TCP FIN really, not emitting any message after closing is key */
293
13.6k
            if (webSocketData->isShuttingDown) {
294
13.6k
                return s;
295
13.6k
            }
296
297
13.6k
            auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
298
13.6k
            auto *asyncSocket = (AsyncSocket<SSL> *) s;
299
300
            /* Every time we get data and not in shutdown state we simply reset the timeout */
301
13.6k
            asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
302
13.6k
            webSocketData->hasTimedOut = false;
303
304
            /* We always cork on data */
305
13.6k
            asyncSocket->cork();
306
307
            /* This parser has virtually no overhead */
308
13.6k
            WebSocketProtocol<isServer, WebSocketContext<SSL, isServer, USERDATA>>::consume(data, (unsigned int) length, (WebSocketState<isServer> *) webSocketData, s);
309
310
            /* Uncorking a closed socekt is fine, in fact it is needed */
311
13.6k
            asyncSocket->uncork();
312
313
            /* If uncorking was successful and we are in shutdown state then send TCP FIN */
314
13.6k
            if (asyncSocket->getBufferedAmount() == 0) {
315
                /* We can now be in shutdown state */
316
13.6k
                if (webSocketData->isShuttingDown) {
317
                    /* Shutting down a closed socket is handled by uSockets and just fine */
318
13.6k
                    asyncSocket->shutdown();
319
13.6k
                }
320
13.6k
            }
321
322
13.6k
            return s;
323
13.6k
        });
324
325
        /* Handle HTTP write out (note: SSL_read may trigger this spuriously, the app need to handle spurious calls) */
326
13.6k
        us_socket_context_on_writable(SSL, getSocketContext(), [](auto *s) {
327
328
            /* NOTE: Are we called here corked? If so, the below write code is broken, since
329
             * we will have 0 as getBufferedAmount due to writing to cork buffer, then sending TCP FIN before
330
             * we actually uncorked and sent off things */
331
332
            /* It makes sense to check for us_is_shut_down here and return if so, to avoid shutting down twice */
333
13.6k
            if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) {
334
13.6k
                return s;
335
13.6k
            }
336
337
13.6k
            AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
338
13.6k
            WebSocketData *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
339
340
            /* We store old backpressure since it is unclear whether write drained anything,
341
             * however, in case of coming here with 0 backpressure we still need to emit drain event */
342
13.6k
            unsigned int backpressure = asyncSocket->getBufferedAmount();
343
344
            /* Drain as much as possible */
345
13.6k
            asyncSocket->write(nullptr, 0);
346
347
            /* Behavior: if we actively drain backpressure, always reset timeout (even if we are in shutdown) */
348
            /* Also reset timeout if we came here with 0 backpressure */
349
13.6k
            if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
350
13.6k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
351
13.6k
                asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
352
13.6k
                webSocketData->hasTimedOut = false;
353
13.6k
            }
354
355
            /* Are we in (WebSocket) shutdown mode? */
356
13.6k
            if (webSocketData->isShuttingDown) {
357
                /* Check if we just now drained completely */
358
13.6k
                if (asyncSocket->getBufferedAmount() == 0) {
359
                    /* Now perform the actual TCP/TLS shutdown which was postponed due to backpressure */
360
13.6k
                    asyncSocket->shutdown();
361
13.6k
                }
362
13.6k
            } else if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
363
                /* Only call drain if we actually drained backpressure or if we came here with 0 backpressure */
364
13.6k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
365
13.6k
                if (webSocketContextData->drainHandler) {
366
13.6k
                    webSocketContextData->drainHandler((WebSocket<SSL, isServer, USERDATA> *) s);
367
13.6k
                }
368
                /* No need to check for closed here as we leave the handler immediately*/
369
13.6k
            }
370
371
13.6k
            return s;
372
13.6k
        });
373
374
        /* Handle FIN, WebSocket does not support half-closed sockets, so simply close */
375
13.6k
        us_socket_context_on_end(SSL, getSocketContext(), [](auto *s) {
376
377
            /* If we get a fin, we just close I guess */
378
13.6k
            us_socket_close(SSL, (us_socket_t *) s, (int) ERR_TCP_FIN.length(), (void *) ERR_TCP_FIN.data());
379
380
13.6k
            return s;
381
13.6k
        });
382
383
13.6k
        us_socket_context_on_long_timeout(SSL, getSocketContext(), [](auto *s) {
384
13.6k
            ((WebSocket<SSL, isServer, USERDATA> *) s)->end(1000, "please reconnect");
385
386
13.6k
            return s;
387
13.6k
        });
388
389
        /* Handle socket timeouts, simply close them so to not confuse client with FIN */
390
13.6k
        us_socket_context_on_timeout(SSL, getSocketContext(), [](auto *s) {
391
392
13.6k
            auto *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
393
13.6k
            auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
394
395
13.6k
            if (webSocketContextData->sendPingsAutomatically && !webSocketData->isShuttingDown && !webSocketData->hasTimedOut) {
396
13.6k
                webSocketData->hasTimedOut = true;
397
13.6k
                us_socket_timeout(SSL, s, webSocketContextData->idleTimeoutComponents.second);
398
                /* Send ping without being corked */
399
13.6k
                ((AsyncSocket<SSL> *) s)->write("\x89\x00", 2);
400
13.6k
                return s;
401
13.6k
            }
402
403
            /* Timeout is very simple; we just close it */
404
            /* Warning: we happen to know forceClose will not use first parameter so pass nullptr here */
405
13.6k
            forceClose(nullptr, s, ERR_WEBSOCKET_TIMEOUT);
406
407
13.6k
            return s;
408
13.6k
        });
409
410
13.6k
        return this;
411
13.6k
    }
EpollEchoServer.cpp:uWS::WebSocketContext<false, true, test()::PerSocketData>::init()
Line
Count
Source
248
13.9k
    WebSocketContext<SSL, isServer, USERDATA> *init() {
249
        /* Adopting a socket does not trigger open event.
250
         * We arreive as WebSocket with timeout set and
251
         * any backpressure from HTTP state kept. */
252
253
        /* Handle socket disconnections */
254
13.9k
        us_socket_context_on_close(SSL, getSocketContext(), [](auto *s, int code, void *reason) {
255
            /* For whatever reason, if we already have emitted close event, do not emit it again */
256
13.9k
            WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
257
13.9k
            if (!webSocketData->isShuttingDown) {
258
                /* Emit close event */
259
13.9k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
260
261
                /* At this point we iterate all currently held subscriptions and emit an event for all of them */
262
13.9k
                if (webSocketData->subscriber && webSocketContextData->subscriptionHandler) {
263
13.9k
                    for (Topic *t : webSocketData->subscriber->topics) {
264
13.9k
                        webSocketContextData->subscriptionHandler((WebSocket<SSL, isServer, USERDATA> *) s, t->name, (int) t->size() - 1, (int) t->size());
265
13.9k
                    }
266
13.9k
                }
267
268
                /* Make sure to unsubscribe from any pub/sub node at exit */
269
13.9k
                webSocketContextData->topicTree->freeSubscriber(webSocketData->subscriber);
270
13.9k
                webSocketData->subscriber = nullptr;
271
272
13.9k
                auto *ws = (WebSocket<SSL, isServer, USERDATA> *) s;
273
13.9k
                if (webSocketContextData->closeHandler) {
274
13.9k
                    webSocketContextData->closeHandler(ws, 1006, {(char *) reason, (size_t) code});
275
13.9k
                }
276
13.9k
                ((USERDATA *) ws->getUserData())->~USERDATA();
277
13.9k
            }
278
279
            /* Destruct in-placed data struct */
280
13.9k
            webSocketData->~WebSocketData();
281
282
13.9k
            return s;
283
13.9k
        });
284
285
        /* Handle WebSocket data streams */
286
13.9k
        us_socket_context_on_data(SSL, getSocketContext(), [](auto *s, char *data, int length) {
287
288
            /* We need the websocket data */
289
13.9k
            WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
290
291
            /* When in websocket shutdown mode, we do not care for ANY message, whether responding close frame or not.
292
             * We only care for the TCP FIN really, not emitting any message after closing is key */
293
13.9k
            if (webSocketData->isShuttingDown) {
294
13.9k
                return s;
295
13.9k
            }
296
297
13.9k
            auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
298
13.9k
            auto *asyncSocket = (AsyncSocket<SSL> *) s;
299
300
            /* Every time we get data and not in shutdown state we simply reset the timeout */
301
13.9k
            asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
302
13.9k
            webSocketData->hasTimedOut = false;
303
304
            /* We always cork on data */
305
13.9k
            asyncSocket->cork();
306
307
            /* This parser has virtually no overhead */
308
13.9k
            WebSocketProtocol<isServer, WebSocketContext<SSL, isServer, USERDATA>>::consume(data, (unsigned int) length, (WebSocketState<isServer> *) webSocketData, s);
309
310
            /* Uncorking a closed socekt is fine, in fact it is needed */
311
13.9k
            asyncSocket->uncork();
312
313
            /* If uncorking was successful and we are in shutdown state then send TCP FIN */
314
13.9k
            if (asyncSocket->getBufferedAmount() == 0) {
315
                /* We can now be in shutdown state */
316
13.9k
                if (webSocketData->isShuttingDown) {
317
                    /* Shutting down a closed socket is handled by uSockets and just fine */
318
13.9k
                    asyncSocket->shutdown();
319
13.9k
                }
320
13.9k
            }
321
322
13.9k
            return s;
323
13.9k
        });
324
325
        /* Handle HTTP write out (note: SSL_read may trigger this spuriously, the app need to handle spurious calls) */
326
13.9k
        us_socket_context_on_writable(SSL, getSocketContext(), [](auto *s) {
327
328
            /* NOTE: Are we called here corked? If so, the below write code is broken, since
329
             * we will have 0 as getBufferedAmount due to writing to cork buffer, then sending TCP FIN before
330
             * we actually uncorked and sent off things */
331
332
            /* It makes sense to check for us_is_shut_down here and return if so, to avoid shutting down twice */
333
13.9k
            if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) {
334
13.9k
                return s;
335
13.9k
            }
336
337
13.9k
            AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
338
13.9k
            WebSocketData *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
339
340
            /* We store old backpressure since it is unclear whether write drained anything,
341
             * however, in case of coming here with 0 backpressure we still need to emit drain event */
342
13.9k
            unsigned int backpressure = asyncSocket->getBufferedAmount();
343
344
            /* Drain as much as possible */
345
13.9k
            asyncSocket->write(nullptr, 0);
346
347
            /* Behavior: if we actively drain backpressure, always reset timeout (even if we are in shutdown) */
348
            /* Also reset timeout if we came here with 0 backpressure */
349
13.9k
            if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
350
13.9k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
351
13.9k
                asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
352
13.9k
                webSocketData->hasTimedOut = false;
353
13.9k
            }
354
355
            /* Are we in (WebSocket) shutdown mode? */
356
13.9k
            if (webSocketData->isShuttingDown) {
357
                /* Check if we just now drained completely */
358
13.9k
                if (asyncSocket->getBufferedAmount() == 0) {
359
                    /* Now perform the actual TCP/TLS shutdown which was postponed due to backpressure */
360
13.9k
                    asyncSocket->shutdown();
361
13.9k
                }
362
13.9k
            } else if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
363
                /* Only call drain if we actually drained backpressure or if we came here with 0 backpressure */
364
13.9k
                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
365
13.9k
                if (webSocketContextData->drainHandler) {
366
13.9k
                    webSocketContextData->drainHandler((WebSocket<SSL, isServer, USERDATA> *) s);
367
13.9k
                }
368
                /* No need to check for closed here as we leave the handler immediately*/
369
13.9k
            }
370
371
13.9k
            return s;
372
13.9k
        });
373
374
        /* Handle FIN, WebSocket does not support half-closed sockets, so simply close */
375
13.9k
        us_socket_context_on_end(SSL, getSocketContext(), [](auto *s) {
376
377
            /* If we get a fin, we just close I guess */
378
13.9k
            us_socket_close(SSL, (us_socket_t *) s, (int) ERR_TCP_FIN.length(), (void *) ERR_TCP_FIN.data());
379
380
13.9k
            return s;
381
13.9k
        });
382
383
13.9k
        us_socket_context_on_long_timeout(SSL, getSocketContext(), [](auto *s) {
384
13.9k
            ((WebSocket<SSL, isServer, USERDATA> *) s)->end(1000, "please reconnect");
385
386
13.9k
            return s;
387
13.9k
        });
388
389
        /* Handle socket timeouts, simply close them so to not confuse client with FIN */
390
13.9k
        us_socket_context_on_timeout(SSL, getSocketContext(), [](auto *s) {
391
392
13.9k
            auto *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
393
13.9k
            auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
394
395
13.9k
            if (webSocketContextData->sendPingsAutomatically && !webSocketData->isShuttingDown && !webSocketData->hasTimedOut) {
396
13.9k
                webSocketData->hasTimedOut = true;
397
13.9k
                us_socket_timeout(SSL, s, webSocketContextData->idleTimeoutComponents.second);
398
                /* Send ping without being corked */
399
13.9k
                ((AsyncSocket<SSL> *) s)->write("\x89\x00", 2);
400
13.9k
                return s;
401
13.9k
            }
402
403
            /* Timeout is very simple; we just close it */
404
            /* Warning: we happen to know forceClose will not use first parameter so pass nullptr here */
405
13.9k
            forceClose(nullptr, s, ERR_WEBSOCKET_TIMEOUT);
406
407
13.9k
            return s;
408
13.9k
        });
409
410
13.9k
        return this;
411
13.9k
    }
412
413
33.2k
    void free() {
414
33.2k
        WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, (us_socket_context_t *) this);
415
33.2k
        webSocketContextData->~WebSocketContextData();
416
417
33.2k
        us_socket_context_free(SSL, (us_socket_context_t *) this);
418
33.2k
    }
EpollEchoServerPubSub.cpp:uWS::WebSocketContext<true, true, test()::PerSocketData>::free()
Line
Count
Source
413
5.74k
    void free() {
414
5.74k
        WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, (us_socket_context_t *) this);
415
5.74k
        webSocketContextData->~WebSocketContextData();
416
417
5.74k
        us_socket_context_free(SSL, (us_socket_context_t *) this);
418
5.74k
    }
EpollHelloWorld.cpp:uWS::WebSocketContext<false, true, test()::PerSocketData>::free()
Line
Count
Source
413
13.6k
    void free() {
414
13.6k
        WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, (us_socket_context_t *) this);
415
13.6k
        webSocketContextData->~WebSocketContextData();
416
417
13.6k
        us_socket_context_free(SSL, (us_socket_context_t *) this);
418
13.6k
    }
EpollEchoServer.cpp:uWS::WebSocketContext<false, true, test()::PerSocketData>::free()
Line
Count
Source
413
13.9k
    void free() {
414
13.9k
        WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, (us_socket_context_t *) this);
415
13.9k
        webSocketContextData->~WebSocketContextData();
416
417
13.9k
        us_socket_context_free(SSL, (us_socket_context_t *) this);
418
13.9k
    }
419
420
public:
421
    /* WebSocket contexts are always child contexts to a HTTP context so no SSL options are needed as they are inherited */
422
33.2k
    static WebSocketContext *create(Loop */*loop*/, us_socket_context_t *parentSocketContext, TopicTree<TopicTreeMessage, TopicTreeBigMessage> *topicTree) {
423
33.2k
        WebSocketContext *webSocketContext = (WebSocketContext *) us_create_child_socket_context(SSL, parentSocketContext, sizeof(WebSocketContextData<SSL, USERDATA>));
424
33.2k
        if (!webSocketContext) {
425
0
            return nullptr;
426
0
        }
427
428
        /* Init socket context data */
429
33.2k
        new ((WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, (us_socket_context_t *)webSocketContext)) WebSocketContextData<SSL, USERDATA>(topicTree);
430
33.2k
        return webSocketContext->init();
431
33.2k
    }
EpollEchoServerPubSub.cpp:uWS::WebSocketContext<true, true, test()::PerSocketData>::create(uWS::Loop*, us_socket_context_t*, uWS::TopicTree<uWS::TopicTreeMessage, uWS::TopicTreeBigMessage>*)
Line
Count
Source
422
5.74k
    static WebSocketContext *create(Loop */*loop*/, us_socket_context_t *parentSocketContext, TopicTree<TopicTreeMessage, TopicTreeBigMessage> *topicTree) {
423
5.74k
        WebSocketContext *webSocketContext = (WebSocketContext *) us_create_child_socket_context(SSL, parentSocketContext, sizeof(WebSocketContextData<SSL, USERDATA>));
424
5.74k
        if (!webSocketContext) {
425
0
            return nullptr;
426
0
        }
427
428
        /* Init socket context data */
429
5.74k
        new ((WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, (us_socket_context_t *)webSocketContext)) WebSocketContextData<SSL, USERDATA>(topicTree);
430
5.74k
        return webSocketContext->init();
431
5.74k
    }
EpollHelloWorld.cpp:uWS::WebSocketContext<false, true, test()::PerSocketData>::create(uWS::Loop*, us_socket_context_t*, uWS::TopicTree<uWS::TopicTreeMessage, uWS::TopicTreeBigMessage>*)
Line
Count
Source
422
13.6k
    static WebSocketContext *create(Loop */*loop*/, us_socket_context_t *parentSocketContext, TopicTree<TopicTreeMessage, TopicTreeBigMessage> *topicTree) {
423
13.6k
        WebSocketContext *webSocketContext = (WebSocketContext *) us_create_child_socket_context(SSL, parentSocketContext, sizeof(WebSocketContextData<SSL, USERDATA>));
424
13.6k
        if (!webSocketContext) {
425
0
            return nullptr;
426
0
        }
427
428
        /* Init socket context data */
429
13.6k
        new ((WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, (us_socket_context_t *)webSocketContext)) WebSocketContextData<SSL, USERDATA>(topicTree);
430
13.6k
        return webSocketContext->init();
431
13.6k
    }
EpollEchoServer.cpp:uWS::WebSocketContext<false, true, test()::PerSocketData>::create(uWS::Loop*, us_socket_context_t*, uWS::TopicTree<uWS::TopicTreeMessage, uWS::TopicTreeBigMessage>*)
Line
Count
Source
422
13.9k
    static WebSocketContext *create(Loop */*loop*/, us_socket_context_t *parentSocketContext, TopicTree<TopicTreeMessage, TopicTreeBigMessage> *topicTree) {
423
13.9k
        WebSocketContext *webSocketContext = (WebSocketContext *) us_create_child_socket_context(SSL, parentSocketContext, sizeof(WebSocketContextData<SSL, USERDATA>));
424
13.9k
        if (!webSocketContext) {
425
0
            return nullptr;
426
0
        }
427
428
        /* Init socket context data */
429
13.9k
        new ((WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, (us_socket_context_t *)webSocketContext)) WebSocketContextData<SSL, USERDATA>(topicTree);
430
13.9k
        return webSocketContext->init();
431
13.9k
    }
432
};
433
434
}
435
436
#endif // UWS_WEBSOCKETCONTEXT_H