/src/uWebSockets/fuzzing/EpollEchoServerPubSub.cpp
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /* We rely on wrapped syscalls */  | 
2  |  | #include "libEpollFuzzer/epoll_fuzzer.h"  | 
3  |  |  | 
4  |  | #include "App.h"  | 
5  |  | #include <vector>  | 
6  |  |  | 
7  |  | /* We keep this one for teardown later on */  | 
8  |  | struct us_listen_socket_t *listen_socket;  | 
9  |  |  | 
10  |  | /* This test is run by libEpollFuzzer */  | 
11  | 9.25k  | void test() { | 
12  |  |  | 
13  |  |     /* ws->getUserData returns one of these */  | 
14  | 9.25k  |     struct PerSocketData { | 
15  |  |         /* Fill with user data */  | 
16  | 9.25k  |         std::vector<std::string> topics;  | 
17  | 9.25k  |         int nr = 0;  | 
18  | 9.25k  |     };  | 
19  |  |  | 
20  |  |     /* Keep in mind that uWS::SSLApp({options}) is the same as uWS::App() when compiled without SSL support. | 
21  |  |      * You may swap to using uWS:App() if you don't need SSL */  | 
22  | 9.25k  |     uWS::SSLApp *app = new uWS::SSLApp({ | 
23  |  |         /* There are example certificates in uWebSockets.js repo */  | 
24  | 9.25k  |       .key_file_name = "../misc/key.pem",  | 
25  | 9.25k  |       .cert_file_name = "../misc/cert.pem",  | 
26  | 9.25k  |       .passphrase = "1234"  | 
27  | 9.25k  |   });  | 
28  |  |       | 
29  | 9.25k  |     app->ws<PerSocketData>("/*", { | 
30  |  |         /* Settings */  | 
31  | 9.25k  |         .compression = uWS::DISABLED,  | 
32  | 9.25k  |         .maxPayloadLength = 512, // also have a low value here for fuzzing  | 
33  | 9.25k  |         .idleTimeout = 60,  | 
34  | 9.25k  |         .maxBackpressure = 128, // we want a low number so that we can reach this in fuzzing  | 
35  | 9.25k  |         .closeOnBackpressureLimit = false, // this one could be tested as well  | 
36  | 9.25k  |         .resetIdleTimeoutOnSend = true, // and this  | 
37  | 9.25k  |         .sendPingsAutomatically = false, // and this  | 
38  |  |         /* Handlers */  | 
39  | 9.25k  |         .upgrade = nullptr,  | 
40  | 106k  |         .open = [](auto *ws) { | 
41  |  |             /* Open event here, you may access ws->getUserData() which points to a PerSocketData struct */  | 
42  |  |  | 
43  | 106k  |             PerSocketData *perSocketData = (PerSocketData *) ws->getUserData();  | 
44  |  |  | 
45  | 10.7M  |             for (int i = 0; i < 100; i++) { | 
46  | 10.6M  |                 std::string topic = std::to_string((uintptr_t)ws) + "-" + std::to_string(i);  | 
47  | 10.6M  |                 perSocketData->topics.push_back(topic);  | 
48  | 10.6M  |                 ws->subscribe(topic);  | 
49  | 10.6M  |             }  | 
50  | 106k  |         },  | 
51  | 1.04M  |         .message = [&app](auto *ws, std::string_view message, uWS::OpCode opCode) { | 
52  | 1.04M  |             PerSocketData *perSocketData = (PerSocketData *) ws->getUserData();  | 
53  |  |  | 
54  | 1.04M  |             app->publish(perSocketData->topics[++perSocketData->nr % 100], message, opCode);  | 
55  | 1.04M  |         },  | 
56  | 9.25k  |         .drain = [](auto */*ws*/) { | 
57  |  |             /* Check ws->getBufferedAmount() here */  | 
58  |  |             //std::cout << "drain" << std::endl;  | 
59  | 7.32k  |         },  | 
60  | 9.25k  |         .ping = [](auto */*ws*/, std::string_view ) { | 
61  |  |             /* Not implemented yet */  | 
62  | 4.58k  |         },  | 
63  | 9.25k  |         .pong = [](auto */*ws*/, std::string_view ) { | 
64  |  |             /* Not implemented yet */  | 
65  | 752  |         },  | 
66  | 106k  |         .close = [](auto */*ws*/, int /*code*/, std::string_view /*message*/) { | 
67  |  |             /* You may access ws->getUserData() here */  | 
68  | 106k  |         }  | 
69  | 9.25k  |     }).listen(9001, [](auto *listen_s) { | 
70  | 5.94k  |         if (listen_s) { | 
71  |  |             //std::cout << "Listening on port " << 9001 << std::endl;  | 
72  | 5.93k  |             listen_socket = listen_s;  | 
73  | 5.93k  |         }  | 
74  | 5.94k  |     });  | 
75  |  |       | 
76  | 9.25k  |     app->run();  | 
77  |  |  | 
78  | 9.25k  |     delete app;  | 
79  |  |  | 
80  | 9.25k  |     uWS::Loop::get()->free();  | 
81  | 9.25k  | }  | 
82  |  |  | 
83  |  | /* Thus function should shutdown the event-loop and let the test fall through */  | 
84  | 16.4k  | void teardown() { | 
85  |  |   /* If we are called twice there's a bug (it potentially could if  | 
86  |  |    * all open sockets cannot be error-closed in one epoll_wait call).  | 
87  |  |    * But we only allow 1k FDs and we have a buffer of 1024 from epoll_wait */  | 
88  | 16.4k  |   if (!listen_socket) { | 
89  | 0  |     exit(-1);  | 
90  | 0  |   }  | 
91  |  |  | 
92  |  |   /* We might have open sockets still, and these will be error-closed by epoll_wait */  | 
93  |  |   // us_socket_context_close - close all open sockets created with this socket context  | 
94  | 16.4k  |     if (listen_socket) { | 
95  | 16.4k  |         us_listen_socket_close(0, listen_socket);  | 
96  | 16.4k  |         listen_socket = NULL;  | 
97  | 16.4k  |     }  | 
98  | 16.4k  | }  |