1 /* We simply call the root header file "App.h", giving you uWS::App and uWS::SSLApp */
2 #include "App.h"
3 
4 /* This is a simple WebSocket "sync" upgrade example.
5  * You may compile it with "WITH_OPENSSL=1 make" or with "make" */
6 
main()7 int main() {
8     /* ws->getUserData returns one of these */
9     struct PerSocketData {
10         /* Define your user data */
11         int something;
12     };
13 
14     /* Keep in mind that uWS::SSLApp({options}) is the same as uWS::App() when compiled without SSL support.
15      * You may swap to using uWS:App() if you don't need SSL */
16     uWS::SSLApp({
17         /* There are example certificates in uWebSockets.js repo */
18 	    .key_file_name = "../misc/key.pem",
19 	    .cert_file_name = "../misc/cert.pem",
20 	    .passphrase = "1234"
21 	}).ws<PerSocketData>("/*", {
22         /* Settings */
23         .compression = uWS::SHARED_COMPRESSOR,
24         .maxPayloadLength = 16 * 1024,
25         .idleTimeout = 10,
26         .maxBackpressure = 1 * 1024 * 1024,
27         /* Handlers */
28         .upgrade = [](auto *res, auto *req, auto *context) {
29 
30             /* You may read from req only here, and COPY whatever you need into your PerSocketData.
31              * PerSocketData is valid from .open to .close event, accessed with ws->getUserData().
32              * HttpRequest (req) is ONLY valid in this very callback, so any data you will need later
33              * has to be COPIED into PerSocketData here. */
34 
35             /* Immediately upgrading without doing anything "async" before, is simple */
36             res->template upgrade<PerSocketData>({
37                 /* We initialize PerSocketData struct here */
38                 .something = 13
39             }, req->getHeader("sec-websocket-key"),
40                 req->getHeader("sec-websocket-protocol"),
41                 req->getHeader("sec-websocket-extensions"),
42                 context);
43 
44             /* If you don't want to upgrade you can instead respond with custom HTTP here,
45              * such as res->writeStatus(...)->writeHeader(...)->end(...); or similar.*/
46 
47             /* Performing async upgrade, such as checking with a database is a little more complex;
48              * see UpgradeAsync example instead. */
49         },
50         .open = [](auto *ws) {
51             /* Open event here, you may access ws->getUserData() which points to a PerSocketData struct.
52              * Here we simply validate that indeed, something == 13 as set in upgrade handler. */
53             std::cout << "Something is: " << static_cast<PerSocketData *>(ws->getUserData())->something << std::endl;
54         },
55         .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) {
56             /* We simply echo whatever data we get */
57             ws->send(message, opCode);
58         },
59         .drain = [](auto */*ws*/) {
60             /* Check ws->getBufferedAmount() here */
61         },
62         .ping = [](auto */*ws*/, std::string_view) {
63             /* You don't need to handle this one, we automatically respond to pings as per standard */
64         },
65         .pong = [](auto */*ws*/, std::string_view) {
66             /* You don't need to handle this one either */
67         },
68         .close = [](auto */*ws*/, int /*code*/, std::string_view /*message*/) {
69             /* You may access ws->getUserData() here, but sending or
70              * doing any kind of I/O with the socket is not valid. */
71         }
72     }).listen(9001, [](auto *listen_socket) {
73         if (listen_socket) {
74             std::cout << "Listening on port " << 9001 << std::endl;
75         }
76     }).run();
77 }
78