BVB Source Codes

uWebSockets Show main.cpp Source code

Return Download uWebSockets: download main.cpp Source code - Download uWebSockets Source code - Type:.cpp
  1. // NOTE: This is not part of the library, this file holds examples and tests
  2.  
  3. #include "uWS.h"
  4. #include <iostream>
  5. #include <chrono>
  6. #include <cmath>
  7. #include <thread>
  8. #include <fstream>
  9. #include <vector>
  10. #include <set>
  11. #include <unordered_set>
  12. #include <unordered_map>
  13. #include <map>
  14. #include <atomic>
  15.  
  16. int countOccurrences(std::string word, std::string &document) {
  17.     int count = 0;
  18.     for (size_t pos = document.find(word); pos != std::string::npos; pos = document.find(word, pos + word.length())) {
  19.         count++;
  20.     }
  21.     return count;
  22. }
  23.  
  24. void testAutobahn() {
  25.     uWS::Hub h;
  26.  
  27.     uWS::Group<uWS::SERVER> *sslGroup = h.createGroup<uWS::SERVER>(uWS::PERMESSAGE_DEFLATE);
  28.     uWS::Group<uWS::SERVER> *group = h.createGroup<uWS::SERVER>(uWS::PERMESSAGE_DEFLATE);
  29.  
  30.     auto messageHandler = [](uWS::WebSocket<uWS::SERVER> *ws, char *message, size_t length, uWS::OpCode opCode) {
  31.         ws->send(message, length, opCode);
  32.     };
  33.  
  34.     sslGroup->onMessage(messageHandler);
  35.     group->onMessage(messageHandler);
  36.  
  37.     sslGroup->onDisconnection([sslGroup](uWS::WebSocket<uWS::SERVER> *ws, int code, char *message, size_t length) {
  38.         static int disconnections = 0;
  39.         if (++disconnections == 519) {
  40.             std::cout << "SSL server done with Autobahn, shutting down!" << std::endl;
  41.             sslGroup->close();
  42.         }
  43.     });
  44.  
  45.     group->onDisconnection([group](uWS::WebSocket<uWS::SERVER> *ws, int code, char *message, size_t length) {
  46.         static int disconnections = 0;
  47.         if (++disconnections == 519) {
  48.             std::cout << "Non-SSL server done with Autobahn, shutting down!" << std::endl;
  49.             group->close();
  50.         }
  51.     });
  52.  
  53.     uS::TLS::Context c = uS::TLS::createContext("misc/ssl/cert.pem",
  54.                                                 "misc/ssl/key.pem",
  55.                                                 "1234");
  56.     if (!h.listen(3001, c, 0, sslGroup) || !h.listen(3000, nullptr, 0, group)) {
  57.         std::cout << "FAILURE: Error listening for Autobahn connections!" << std::endl;
  58.         exit(-1);
  59.     } else {
  60.         std::cout << "Acepting Autobahn connections (SSL/non-SSL)" << std::endl;
  61.     }
  62.  
  63.     std::thread t([]() {
  64.         if (!system("wstest -m fuzzingclient -s misc/Autobahn.json")) {
  65.  
  66.         }
  67.     });
  68.  
  69.     h.run();
  70.     t.join();
  71.  
  72.     // "FAILED", "OK", "NON-STRICT"
  73.     std::ifstream fin("misc/autobahn/index.json");
  74.     fin.seekg (0, fin.end);
  75.     int length = fin.tellg();
  76.     fin.seekg (0, fin.beg);
  77.     char *buffer = new char[length];
  78.     fin.read(buffer, length);
  79.     std::string index(buffer, length);
  80.  
  81.     std::cout << std::endl << std::endl;
  82.     std::cout << "OK: " << countOccurrences("\"OK\"", index) << std::endl;
  83.     std::cout << "NON-STRICT: " << countOccurrences("\"NON-STRICT\"", index) << std::endl;
  84.     std::cout << "FAILED: " << countOccurrences("\"FAILED\"", index) << std::endl;
  85.  
  86.     delete sslGroup;
  87.     delete group;
  88.     delete [] buffer;
  89. }
  90.  
  91. void serveBenchmark() {
  92.     uWS::Hub h;
  93.  
  94.     h.onMessage([&h](uWS::WebSocket<uWS::SERVER> *ws, char *message, size_t length, uWS::OpCode opCode) {
  95.         ws->send(message, length, opCode);
  96.     });
  97.  
  98.     //h.getDefaultGroup<uWS::SERVER>().startAutoPing(1000);
  99.     h.listen(3000);
  100.     h.run();
  101. }
  102.  
  103. void measureInternalThroughput(unsigned int payloadLength, int echoes, bool ssl) {
  104.     uWS::Hub h;
  105.  
  106.     char *payload = new char[payloadLength];
  107.     for (unsigned int i = 0; i < payloadLength; i++) {
  108.         payload[i] = rand();
  109.     }
  110.  
  111.     const char *closeMessage = "I'm closing now";
  112.     size_t closeMessageLength = strlen(closeMessage);
  113.  
  114.     uS::TLS::Context c = uS::TLS::createContext("misc/ssl/cert.pem",
  115.                                                 "misc/ssl/key.pem",
  116.                                                 "1234");
  117.  
  118.     h.onConnection([payload, payloadLength, echoes](uWS::WebSocket<uWS::CLIENT> *ws, uWS::HttpRequest req) {
  119.         for (int i = 0; i < echoes; i++) {
  120.             ws->send(payload, payloadLength, uWS::OpCode::BINARY);
  121.         }
  122.     });
  123.  
  124.     h.onError([](void *user) {
  125.         std::cout << "FAILURE: Connection failed! Timeout?" << std::endl;
  126.         exit(-1);
  127.     });
  128.  
  129.     h.onMessage([payload, payloadLength, closeMessage, closeMessageLength, echoes](uWS::WebSocket<uWS::CLIENT> *ws, char *message, size_t length, uWS::OpCode opCode) {
  130.         if (strncmp(message, payload, payloadLength) || payloadLength != length) {
  131.             std::cout << "FAIL: Messages differ!" << std::endl;
  132.             exit(-1);
  133.         }
  134.  
  135.         static int echoesPerformed = 0;
  136.         if (echoesPerformed++ == echoes) {
  137.             echoesPerformed = 0;
  138.             ws->close(1000, closeMessage, closeMessageLength);
  139.         } else {
  140.             ws->send(payload, payloadLength, opCode);
  141.         }
  142.     });
  143.  
  144.     h.onDisconnection([](uWS::WebSocket<uWS::CLIENT> *ws, int code, char *message, size_t length) {
  145.         std::cout << "CLIENT CLOSE: " << code << std::endl;
  146.     });
  147.  
  148.     h.onMessage([](uWS::WebSocket<uWS::SERVER> *ws, char *message, size_t length, uWS::OpCode opCode) {
  149.         ws->send(message, length, opCode);
  150.     });
  151.  
  152.     h.onDisconnection([&h, closeMessage, closeMessageLength](uWS::WebSocket<uWS::SERVER> *ws, int code, char *message, size_t length) {
  153.         std::cout << "SERVER CLOSE: " << code << std::endl;
  154.         if (!length) {
  155.             std::cout << "FAIL: No close message! Code: " << code << std::endl;
  156.             exit(-1);
  157.         }
  158.  
  159.         if (strncmp(message, closeMessage, closeMessageLength) || closeMessageLength != length) {
  160.             std::cout << "FAIL: Close message differ!" << std::endl;
  161.             exit(-1);
  162.         }
  163.  
  164.         if (code != 1000) {
  165.             std::cout << "FAIL: Close code differ!" << std::endl;
  166.             exit(-1);
  167.         }
  168.  
  169.         h.getDefaultGroup<uWS::SERVER>().close();
  170.     });
  171.  
  172.     // we need to update libuv internal timepoint!
  173. #ifndef USE_ASIO
  174.     h.run();
  175. #endif
  176.  
  177.     if (ssl) {
  178.         if (!h.listen(3000, c)) {
  179.             std::cout << "FAIL: ERR_LISTEN" << std::endl;
  180.             exit(-1);
  181.         }
  182.         h.connect("wss://localhost:3000", nullptr);
  183.     } else {
  184.         if (!h.listen(3000)) {
  185.             std::cout << "FAIL: ERR_LISTEN" << std::endl;
  186.             exit(-1);
  187.         }
  188.         h.connect("ws://localhost:3000", nullptr);
  189.     }
  190.  
  191.     std::chrono::time_point<std::chrono::high_resolution_clock> start, end;
  192.     start = std::chrono::high_resolution_clock::now();
  193.     h.run();
  194.     end = std::chrono::high_resolution_clock::now();
  195.     int ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
  196.     if (!ms) {
  197.         std::cout << "Too small load!" << std::endl;
  198.     } else {
  199.         std::cout << "Throughput: " << (float(echoes) / float(ms)) << " echoes/ms (" << ms << " ms elapsed)" << std::endl;
  200.     }
  201.  
  202.     delete [] payload;
  203. }
  204.  
  205. void testStress() {
  206.     for (int i = 0; i < 25; i++) {
  207.         int payloadLength = std::pow(2, i);
  208.         int echoes = 1;//std::max<int>(std::pow(2, 24 - i) / 50, 1);
  209.  
  210.         std::cout << "[Size: " << payloadLength << ", echoes: " << echoes << "]" << std::endl;
  211.         for (int ssl = 0; ssl < 2; ssl++) {
  212.             std::cout << "SSL: " << bool(ssl) << std::endl;
  213.             measureInternalThroughput(payloadLength, echoes, ssl);
  214.         }
  215.     }
  216. }
  217.  
  218. void testConnections() {
  219.     uWS::Hub h;
  220.  
  221.     h.onError([](void *user) {
  222.         switch ((long) user) {
  223.         case 1:
  224.             std::cout << "Client emitted error on invalid URI" << std::endl;
  225.             break;
  226.         case 2:
  227.             std::cout << "Client emitted error on resolve failure" << std::endl;
  228.             break;
  229.         case 3:
  230.             std::cout << "Client emitted error on connection timeout (non-SSL)" << std::endl;
  231.             break;
  232.         case 5:
  233.             std::cout << "Client emitted error on connection timeout (SSL)" << std::endl;
  234.             break;
  235.         case 6:
  236.             std::cout << "Client emitted error on HTTP response without upgrade (non-SSL)" << std::endl;
  237.             break;
  238.         case 7:
  239.             std::cout << "Client emitted error on HTTP response without upgrade (SSL)" << std::endl;
  240.             break;
  241.         case 10:
  242.             std::cout << "Client emitted error on poll error" << std::endl;
  243.             break;
  244.         default:
  245.             std::cout << "FAILURE: " << user << " should not emit error!" << std::endl;
  246.             exit(-1);
  247.         }
  248.     });
  249.  
  250.     h.onConnection([](uWS::WebSocket<uWS::CLIENT> *ws, uWS::HttpRequest req) {
  251.         switch ((long) ws->getUserData()) {
  252.         case 8:
  253.             std::cout << "Client established a remote connection over non-SSL" << std::endl;
  254.             ws->close(1000);
  255.             break;
  256.         case 9:
  257.             std::cout << "Client established a remote connection over SSL" << std::endl;
  258.             ws->close(1000);
  259.             break;
  260.         default:
  261.             std::cout << "FAILURE: " << ws->getUserData() << " should not connect!" << std::endl;
  262.             exit(-1);
  263.         }
  264.     });
  265.  
  266.     h.onDisconnection([](uWS::WebSocket<uWS::CLIENT> *ws, int code, char *message, size_t length) {
  267.         std::cout << "Client got disconnected with data: " << ws->getUserData() << ", code: " << code << ", message: <" << std::string(message, length) << ">" << std::endl;
  268.     });
  269.  
  270.     h.connect("invalid URI", (void *) 1);
  271.     h.connect("ws://validButUnknown.yolo", (void *) 2);
  272.     h.connect("ws://echo.websocket.org", (void *) 3, {}, 10);
  273.     h.connect("ws://echo.websocket.org", (void *) 8);
  274.     h.connect("wss://echo.websocket.org", (void *) 5, {}, 10);
  275.     h.connect("wss://echo.websocket.org", (void *) 9);
  276.     h.connect("ws://google.com", (void *) 6);
  277.     h.connect("wss://google.com", (void *) 7);
  278.     h.connect("ws://127.0.0.1:6000", (void *) 10, {}, 60000);
  279.  
  280.     h.run();
  281.     std::cout << "Falling through testConnections" << std::endl;
  282. }
  283.  
  284. void testListening() {
  285.     uWS::Hub h;
  286.  
  287.     h.onError([](int port) {
  288.         switch (port) {
  289.         case 80:
  290.             std::cout << "Server emits error listening to port 80 (permission denied)" << std::endl;
  291.             break;
  292.         case 3000:
  293.             std::cout << "Server emits error listening to port 3000 twice" << std::endl;
  294.             break;
  295.         default:
  296.             std::cout << "FAILURE: port " << port << " should not emit error" << std::endl;
  297.             exit(-1);
  298.         }
  299.     });
  300.  
  301.     h.listen(80);
  302.     if (h.listen(3000)) {
  303.         std::cout << "Server listens to port 3000" << std::endl;
  304.     }
  305.     h.listen(3000);
  306.     h.getDefaultGroup<uWS::SERVER>().close();
  307.     h.run();
  308.     std::cout << "Server falls through after group closes" << std::endl;
  309. }
  310.  
  311. void testClosing() {
  312.     uWS::Hub h;
  313.     const char *closeMessage = "Closing you down!";
  314.  
  315.     h.onConnection([&h, closeMessage](uWS::WebSocket<uWS::SERVER> *ws, uWS::HttpRequest req) {
  316.         ws->terminate();
  317.         h.onConnection([&h, closeMessage](uWS::WebSocket<uWS::SERVER> *ws, uWS::HttpRequest req) {
  318.             ws->close(1000, closeMessage, strlen(closeMessage));
  319.         });
  320.         h.connect("ws://localhost:3000", (void *) 2);
  321.     });
  322.  
  323.     h.onDisconnection([closeMessage](uWS::WebSocket<uWS::CLIENT> *ws, int code, char *message, size_t length) {
  324.         switch ((long) ws->getUserData()) {
  325.         case 1:
  326.             if (code == 1006) {
  327.                 std::cout << "Client gets terminated on first connection" << std::endl;
  328.             } else {
  329.                 std::cout << "FAILURE: Terminate leads to invalid close code!" << std::endl;
  330.                 exit(-1);
  331.             }
  332.             break;
  333.         case 2:
  334.             if (code == 1000 && length == strlen(closeMessage) && !strncmp(closeMessage, message, length)) {
  335.                 std::cout << "Client gets closed on second connection with correct close code" << std::endl;
  336.             } else {
  337.                 std::cout << "FAILURE: Close leads to invalid close code or message!" << std::endl;
  338.                 exit(-1);
  339.             }
  340.             break;
  341.         }
  342.     });
  343.  
  344.     h.onDisconnection([&h, closeMessage](uWS::WebSocket<uWS::SERVER> *ws, int code, char *message, size_t length) {
  345.         if (code == 1006) {
  346.             std::cout << "Server recives terminate close code after terminating" << std::endl;
  347.         } else if (code != 1000) {
  348.             std::cout << "FAILURE: Server does not receive correct close code!" << std::endl;
  349.             exit(-1);
  350.         } else {
  351.             std::cout << "Server receives correct close code after closing" << std::endl;
  352.             h.getDefaultGroup<uWS::SERVER>().close();
  353.         }
  354.     });
  355.  
  356.     if (!h.listen(3000)) {
  357.         std::cout << "FAILURE: Cannot listen to port 3000!" << std::endl;
  358.         exit(-1);
  359.     }
  360.     h.connect("ws://localhost:3000", (void *) 1);
  361.  
  362.     h.run();
  363.     std::cout << "Falling through after testClosing!" << std::endl;
  364. }
  365.  
  366. void testBroadcast() {
  367.     uWS::Hub h;
  368.  
  369.     const char *broadcastMessage = "This will be broadcasted!";
  370.     size_t broadcastMessageLength = strlen(broadcastMessage);
  371.  
  372.     int connections = 14;
  373.     h.onConnection([&h, &connections, broadcastMessage, broadcastMessageLength](uWS::WebSocket<uWS::SERVER> *ws, uWS::HttpRequest req) {
  374.         if (!--connections) {
  375.             std::cout << "Broadcasting & closing now!" << std::endl;
  376.             h.getDefaultGroup<uWS::SERVER>().broadcast(broadcastMessage, broadcastMessageLength, uWS::OpCode::TEXT);
  377.             h.getDefaultGroup<uWS::SERVER>().close();
  378.         }
  379.     });
  380.  
  381.     int broadcasts = connections;
  382.     h.onMessage([&broadcasts, broadcastMessage, broadcastMessageLength](uWS::WebSocket<uWS::CLIENT> *ws, char *message, size_t length, uWS::OpCode opCode) {
  383.         if (length != broadcastMessageLength || strncmp(message, broadcastMessage, broadcastMessageLength)) {
  384.             std::cout << "FAILURE: bad broadcast message!" << std::endl;
  385.             exit(-1);
  386.         } else {
  387.             broadcasts--;
  388.         }
  389.     });
  390.  
  391.     h.onDisconnection([](uWS::WebSocket<uWS::CLIENT> *ws, int code, char *message, size_t length) {
  392.         if (code != 1000) {
  393.             std::cout << "FAILURE: Invalid close code!" << std::endl;
  394.             exit(-1);
  395.         }
  396.     });
  397.  
  398.     h.listen(3000);
  399.  
  400.     for (int i = 0; i < connections; i++) {
  401.         h.connect("ws://localhost:3000", nullptr);
  402.     }
  403.  
  404.     h.run();
  405.  
  406.     if (broadcasts != 0) {
  407.         std::cout << "FAILURE: Invalid amount of broadcasts received!" << std::endl;
  408.         exit(-1);
  409.     }
  410.  
  411.     std::cout << "Falling through now!" << std::endl;
  412. }
  413.  
  414. void testRouting() {
  415.     uWS::Hub h;
  416.  
  417.     int correctStrings = 0;
  418.  
  419.     h.onConnection([&correctStrings](uWS::WebSocket<uWS::CLIENT> *ws, uWS::HttpRequest req) {
  420.         if (req.getHeader("sec-websocket-protocol").toString() == "someSubProtocolHere") {
  421.             correctStrings++;
  422.         }
  423.         ws->close();
  424.     });
  425.  
  426.     h.onConnection([&correctStrings](uWS::WebSocket<uWS::SERVER> *ws, uWS::HttpRequest req) {
  427.         if (req.getHeader("sec-websocket-protocol").toString() == "someSubProtocolHere") {
  428.             correctStrings++;
  429.         }
  430.  
  431.         if (req.getHeader("some-random-header").toString() == "someRandomValue") {
  432.             correctStrings++;
  433.         }
  434.  
  435.         if (req.getUrl().toString() == "/somePathHere") {
  436.             correctStrings++;
  437.         }
  438.     });
  439.  
  440.     h.onDisconnection([&h](uWS::WebSocket<uWS::SERVER> *ws, int code, char *message, size_t length) {
  441.         h.getDefaultGroup<uWS::SERVER>().close();
  442.     });
  443.  
  444.     h.listen(3000);
  445.     h.connect("ws://localhost:3000/somePathHere", nullptr, {{"sec-websocket-protocol", "someSubProtocolHere"}, {"some-random-header", "someRandomValue"}});
  446.  
  447.     h.run();
  448.  
  449.     if (correctStrings != 4) {
  450.         std::cout << "FAILURE: incorrect paths or subprotocols " << correctStrings << std::endl;
  451.         exit(-1);
  452.     } else {
  453.         std::cout << "testRouting passed, falling through" << std::endl;
  454.     }
  455. }
  456.  
  457. void testReusePort() {
  458.     uWS::Hub h;
  459.  
  460.     uWS::Group<uWS::SERVER> *group1 = h.createGroup<uWS::SERVER>();
  461.     uWS::Group<uWS::SERVER> *group2 = h.createGroup<uWS::SERVER>();
  462.  
  463.     if (h.listen(3000, nullptr, uS::REUSE_PORT, group1) && h.listen(3000, nullptr, uS::REUSE_PORT, group2)) {
  464.         std::cout << "Can listen to same port twice!" << std::endl;
  465.     } else {
  466.         std::cout << "FAILURE: Cannot listen to same port twice!" << std::endl;
  467.         exit(-1);
  468.     }
  469.  
  470.     group1->close();
  471.     group2->close();
  472.  
  473.     h.run();
  474.  
  475.     delete group1;
  476.     delete group2;
  477. }
  478.  
  479. void testTransfers() {
  480.     for (int ssl = 0; ssl < 2; ssl++) {
  481.         uWS::Group<uWS::SERVER> *tServerGroup = nullptr;
  482.         uWS::Group<uWS::CLIENT> *clientGroup = nullptr;
  483.  
  484.         int receivedMessages = 0;
  485.  
  486.         std::mutex m;
  487.         uWS::WebSocket<uWS::CLIENT> *client;
  488.  
  489.         std::thread t([&tServerGroup, &client, &receivedMessages, &clientGroup, &m]{
  490.             uWS::Hub th;
  491.             tServerGroup = &th.getDefaultGroup<uWS::SERVER>();
  492.  
  493.             bool transferred = false;
  494.  
  495.             th.onTransfer([&transferred](uWS::WebSocket<uWS::SERVER> *ws) {
  496.                 if (ws->getUserData() != (void *) 12345) {
  497.                     std::cout << "onTransfer called with websocket with invalid user data set!" << std::endl;
  498.                     exit(-1);
  499.                 }
  500.  
  501.                 transferred = true;
  502.             });
  503.  
  504.             th.onMessage([&tServerGroup, &client, &receivedMessages, &clientGroup, &m, &transferred](uWS::WebSocket<uWS::SERVER> *ws, char *message, size_t length, uWS::OpCode opCode) {
  505.                 if (!transferred) {
  506.                     std::cout << "FAILURE: onTransfer was not triggered in time" << std::endl;
  507.                     exit(-1);
  508.                 }
  509.  
  510.                 switch(++receivedMessages) {
  511.                 case 1:
  512.                     m.lock();
  513.                     client->send("second message");
  514.                     m.unlock();
  515.                     break;
  516.                 case 2: {
  517.                     const char *str = "some broadcast here";
  518.                     clientGroup->broadcast(str, strlen(str), uWS::OpCode::TEXT);
  519.                     break;
  520.                 }
  521.                 case 3: {
  522.                     usleep(10000);
  523.                     char *tmp = new char[1024 * 1024 * 16];
  524.                     memset(tmp, 0, 1024 * 1024 * 16);
  525.                     client->send(tmp, 1024 * 1024 * 16, uWS::OpCode::BINARY);
  526.                     delete [] tmp;
  527.                     break;
  528.                 }
  529.                 case 4:
  530.                     tServerGroup->close();
  531.                     break;
  532.                 }
  533.  
  534.                 if (opCode != uWS::OpCode::BINARY) {
  535.                     std::cout << "Message " << receivedMessages << ": " << std::string(message, length) << std::endl;
  536.                 } else {
  537.                     std::cout << "Message " << receivedMessages << ": binary" << std::endl;
  538.                 }
  539.             });
  540.  
  541.             th.getDefaultGroup<uWS::SERVER>().listen(uWS::TRANSFERS);
  542.             th.run();
  543.         });
  544.  
  545.         // we do not care about correctness here!
  546.         sleep(1);
  547.  
  548.         uWS::Hub h;
  549.  
  550.         clientGroup = &h.getDefaultGroup<uWS::CLIENT>();
  551.  
  552.         clientGroup->listen(uWS::TRANSFERS);
  553.  
  554.         h.onConnection([&tServerGroup](uWS::WebSocket<uWS::SERVER> *ws, uWS::HttpRequest req) {
  555.             ws->setUserData((void *) 12345);
  556.             ws->transfer(tServerGroup);
  557.         });
  558.  
  559.         h.onConnection([&client, &m](uWS::WebSocket<uWS::CLIENT> *ws, uWS::HttpRequest req) {
  560.             m.lock();
  561.             client = ws;
  562.             ws->send("first message here");
  563.             m.unlock();
  564.         });
  565.  
  566.         h.onDisconnection([&h](uWS::WebSocket<uWS::CLIENT> *ws, int code, char *message, size_t length) {
  567.             h.getDefaultGroup<uWS::SERVER>().close();
  568.             h.getDefaultGroup<uWS::CLIENT>().close();
  569.         });
  570.  
  571.         if (ssl) {
  572.             if (!h.listen(3000,
  573.                           uS::TLS::createContext("misc/ssl/cert.pem",
  574.                           "misc/ssl/key.pem", "1234"))) {
  575.                 std::cerr << "FAILURE: Cannot listen!" << std::endl;
  576.                 exit(-1);
  577.             }
  578.             h.connect("wss://localhost:3000", nullptr);
  579.         } else {
  580.             if (!h.listen(3000)) {
  581.                 std::cerr << "FAILURE: Cannot listen!" << std::endl;
  582.                 exit(-1);
  583.             }
  584.             h.connect("ws://localhost:3000", nullptr);
  585.         }
  586.  
  587.         h.run();
  588.         t.join();
  589.     }
  590.     std::cout << "Falling through testMultithreading" << std::endl;
  591. }
  592.  
  593. void testSendCallback() {
  594.     uWS::Hub h;
  595.  
  596.     h.onConnection([&h](uWS::WebSocket<uWS::SERVER> *ws, uWS::HttpRequest req) {
  597.         ws->send("1234", 4, uWS::OpCode::TEXT, [](uWS::WebSocket<uWS::SERVER> *ws, void *data, bool cancelled, void *reserved) {
  598.             if (data) {
  599.                 if (data != (void *) 13) {
  600.                     std::cout << "FAILURE: invalid data passed to send callback!" << std::endl;
  601.                     exit(-1);
  602.                 } else {
  603.                     std::cout << "Correct data was sent to send callback" << std::endl;
  604.                 }
  605.             } else {
  606.                 std::cout << "FAILURE: No data was passed along!" << std::endl;
  607.                 exit(-1);
  608.             }
  609.         }, (void *) 13);
  610.         h.getDefaultGroup<uWS::SERVER>().close();
  611.     });
  612.  
  613.     h.listen(3000);
  614.     h.connect("ws://localhost:3000", nullptr);
  615.     h.run();
  616. }
  617.  
  618. void testAutoPing() {
  619.     uWS::Hub h;
  620.  
  621.     int pongs = 0, pings = 0;
  622.  
  623.     h.onPing([&pings](uWS::WebSocket<uWS::CLIENT> *ws, char *message, size_t length) {
  624.         std::cout << "PING" << std::endl;
  625.         pings++;
  626.     });
  627.  
  628.     h.onMessage([](uWS::WebSocket<uWS::CLIENT> *ws, char *message, size_t length, uWS::OpCode opCode) {
  629.         std::cout << std::string(message, length) << std::endl;
  630.         ws->send(message, length, opCode);
  631.     });
  632.  
  633.     h.onPong([&pings, &pongs, &h](uWS::WebSocket<uWS::SERVER> *ws, char *message, size_t length) {
  634.         std::cout << "PONG" << std::endl;
  635.         pongs++;
  636.  
  637.         if (pongs == 3) {
  638.             if (pings != pongs) {
  639.                 std::cout << "FAILURE: mismatching ping/pongs" << std::endl;
  640.                 exit(-1);
  641.             }
  642.             h.getDefaultGroup<uWS::SERVER>().close();
  643.         }
  644.     });
  645.  
  646.     h.getDefaultGroup<uWS::SERVER>().startAutoPing(1000);
  647.     h.listen(3000);
  648.     h.connect("ws://localhost:3000", nullptr);
  649.     h.run();
  650. }
  651.  
  652. void testSmallSends() {
  653.     uWS::Hub h;
  654.  
  655.     int length = 0;
  656.     h.onConnection([&h, &length](uWS::WebSocket<uWS::SERVER> *ws, uWS::HttpRequest req) {
  657.         std::cout << "Connected, will send small messages now" << std::endl;
  658.         while (length < 2048) {
  659.             char *message = new char[length];
  660.             memset(message, 0, length);
  661.             ws->send(message, length, uWS::OpCode::TEXT);
  662.             delete [] message;
  663.             length++;
  664.         }
  665.         h.getDefaultGroup<uWS::SERVER>().close();
  666.     });
  667.  
  668.     h.listen(3000);
  669.     h.connect("ws://localhost:3000", nullptr);
  670.  
  671.     h.run();
  672.     std::cout << "Falling through testSmallSends" << std::endl;
  673. }
  674.  
  675. // WIP - add excluded messages!
  676. void testMessageBatch() {
  677.     uWS::Hub h;
  678.  
  679.     std::vector<std::string> messages = {"hello", "world"};
  680.     std::vector<int> excludes;
  681.  
  682.     h.onConnection([&messages, &excludes](uWS::WebSocket<uWS::SERVER> *ws, uWS::HttpRequest req) {
  683.         uWS::WebSocket<uWS::SERVER>::PreparedMessage *prepared = ws->prepareMessageBatch(messages, excludes, uWS::OpCode::TEXT, false, nullptr);
  684.         ws->sendPrepared(prepared, nullptr);
  685.         ws->finalizeMessage(prepared);
  686.     });
  687.  
  688.     int receivedMessages = 0;
  689.  
  690.     h.onMessage([&receivedMessages, &h](uWS::WebSocket<uWS::CLIENT> *ws, char *message, size_t length, uWS::OpCode opCode) {
  691.         std::cout << "Received message from batch: " << std::string(message, length) << std::endl;
  692.         if (receivedMessages == 0) {
  693.             if (!strncmp(message, "hello", length)) {
  694.                 receivedMessages++;
  695.             }
  696.         } else {
  697.             if (!strncmp(message, "world", length)) {
  698.                 receivedMessages++;
  699.             }
  700.         }
  701.  
  702.         if (receivedMessages == 2) {
  703.             h.getDefaultGroup<uWS::SERVER>().close();
  704.         }
  705.     });
  706.  
  707.     h.listen(3000);
  708.     h.connect("ws://localhost:3000", nullptr);
  709.     h.run();
  710. }
  711.  
  712. void testHTTP() {
  713.     uWS::Hub h;
  714.     std::atomic<int> expectedRequests(0);
  715.  
  716.     auto controlData = [&h, &expectedRequests](uWS::HttpResponse *res, char *data, size_t length, size_t remainingBytes) {
  717.         std::string *buffer = (std::string *) res->httpSocket->getUserData();
  718.         buffer->append(data, length);
  719.  
  720.         std::cout << "HTTP POST, chunk: " << length << ", total: " << buffer->length() << ", remainingBytes: " << remainingBytes << std::endl;
  721.  
  722.         if (!remainingBytes) {
  723.             // control the contents
  724.             for (unsigned int i = 0; i < buffer->length(); i++) {
  725.                 if ((*buffer)[i] != char('0' + i % 10)) {
  726.                     std::cout << "FAILURE: corrupt data received in HTTP post!" << std::endl;
  727.                     exit(-1);
  728.                 }
  729.             }
  730.  
  731.             expectedRequests++;
  732.  
  733.             delete (std::string *) res->httpSocket->getUserData();
  734.             res->end();
  735.         }
  736.     };
  737.  
  738.     h.onHttpData([&controlData](uWS::HttpResponse *res, char *data, size_t length, size_t remainingBytes) {
  739.         controlData(res, data, length, remainingBytes);
  740.     });
  741.  
  742.     h.onHttpRequest([&h, &expectedRequests, &controlData](uWS::HttpResponse *res, uWS::HttpRequest req, char *data, size_t length, size_t remainingBytes) {
  743.  
  744.         std::cout << req.getUrl().toString() << std::endl;
  745.  
  746.         if (req.getUrl().toString() == "/segmentedUrl") {
  747.             if (req.getMethod() == uWS::HttpMethod::METHOD_GET && req.getHeader("host").toString() == "localhost") {
  748.                 expectedRequests++;
  749.                 res->end();
  750.                 return;
  751.             }
  752.         } else if (req.getUrl().toString() == "/closeServer") {
  753.             if (req.getMethod() == uWS::HttpMethod::METHOD_PUT) {
  754.                 res->setUserData((void *) 1234);
  755.                 // this will trigger a cancelled request
  756.                 h.getDefaultGroup<uWS::SERVER>().close();
  757.                 expectedRequests++;
  758.                 return;
  759.             }
  760.         } else if (req.getUrl().toString() == "/postTest") {
  761.             if (req.getMethod() == uWS::HttpMethod::METHOD_POST) {
  762.                 res->httpSocket->setUserData(new std::string);
  763.                 controlData(res, data, length, remainingBytes);
  764.                 return;
  765.             }
  766.         } else if (req.getUrl().toString() == "/packedTest") {
  767.             if (req.getMethod() == uWS::HttpMethod::METHOD_GET) {
  768.                 expectedRequests++;
  769.                 res->end();
  770.                 return;
  771.             }
  772.         } else if (req.getUrl().toString() == "/firstRequest") {
  773.             // store response in user data
  774.             res->httpSocket->setUserData(res);
  775.             return;
  776.         } else if (req.getUrl().toString() == "/secondRequest") {
  777.             // respond to request out of order
  778.             std::string secondResponse = "Second request responded to";
  779.             res->end(secondResponse.data(), secondResponse.length());
  780.             std::string firstResponse = "First request responded to";
  781.             ((uWS::HttpResponse *) res->httpSocket->getUserData())->end(firstResponse.data(), firstResponse.length());
  782.             return;
  783.         }
  784.  
  785.         std::cerr << "FAILURE: Unexpected request!" << std::endl;
  786.         exit(-1);
  787.     });
  788.  
  789.     h.onCancelledHttpRequest([&expectedRequests](uWS::HttpResponse *res) {
  790.         if (res->getUserData() == (void *) 1234) {
  791.             // let's say we want this one cancelled
  792.             expectedRequests++;
  793.         } else {
  794.             std::cerr << "FAILURE: Unexpected cancelled request!" << std::endl;
  795.             exit(-1);
  796.         }
  797.     });
  798.  
  799.     h.onConnection([&expectedRequests](uWS::WebSocket<uWS::SERVER> *ws, uWS::HttpRequest req) {
  800.         if (req.getUrl().toString() == "/upgradeUrl") {
  801.             if (req.getMethod() == uWS::HttpMethod::METHOD_GET && req.getHeader("upgrade").toString() == "websocket") {
  802.                 expectedRequests++;
  803.                 return;
  804.             }
  805.         }
  806.  
  807.         std::cerr << "FAILURE: Unexpected request!" << std::endl;
  808.         exit(-1);
  809.     });
  810.  
  811.     h.onDisconnection([](uWS::WebSocket<uWS::SERVER> *ws, int code, char *message, size_t length) {
  812.         delete (std::string *) ws->getUserData();
  813.     });
  814.  
  815.     h.listen(3000);
  816.  
  817.     std::thread t([&expectedRequests]() {
  818.         FILE *nc;
  819.  
  820.         // invalid data
  821.         nc = popen("nc localhost 3000 &> /dev/null", "w");
  822.         fputs("invalid http", nc);
  823.         pclose(nc);
  824.  
  825.         nc = popen("nc localhost 3000 &> /dev/null", "w");
  826.         fputs("\r\n\r\n", nc);
  827.         pclose(nc);
  828.  
  829.         nc = popen("nc localhost 3000 &> /dev/null", "w");
  830.         fputs("\r\n", nc);
  831.         pclose(nc);
  832.  
  833.         nc = popen("nc localhost 3000 &> /dev/null", "w");
  834.         fputs("\r\n\r", nc);
  835.         pclose(nc);
  836.  
  837.         nc = popen("nc localhost 3000 &> /dev/null", "w");
  838.         fputs("\r", nc);
  839.         pclose(nc);
  840.  
  841.         nc = popen("nc localhost 3000 &> /dev/null", "w");
  842.         fputs("\n", nc);
  843.         pclose(nc);
  844.  
  845.         nc = popen("nc localhost 3000 &> /dev/null", "w");
  846.         fputs("GET \r\n", nc);
  847.         pclose(nc);
  848.  
  849.         nc = popen("nc localhost 3000 &> /dev/null", "w");
  850.         fputs("GET / HTTP/1.1\r\n", nc);
  851.         pclose(nc);
  852.  
  853.         nc = popen("nc localhost 3000 &> /dev/null", "w");
  854.         fputs("GET / HTTP/1.1\r\nHost: localhost:3000", nc);
  855.         pclose(nc);
  856.  
  857.         // segmented GET
  858.         nc = popen("nc localhost 3000 &> /dev/null", "w");
  859.         fputs("GET /segme", nc);
  860.         fflush(nc);
  861.         usleep(100000);
  862.  
  863.         fputs("ntedUrl HTTP/1.1\r", nc);
  864.         fflush(nc);
  865.         usleep(100000);
  866.  
  867.         fputs("\nHost: loca", nc);
  868.         fflush(nc);
  869.         usleep(100000);
  870.  
  871.         fputs("lhost\r\n\r\n", nc);
  872.         fflush(nc);
  873.         usleep(100000);
  874.         pclose(nc);
  875.  
  876.         // segmented upgrade
  877.         nc = popen("nc localhost 3000 &> /dev/null", "w");
  878.         fputs("GET /upgra", nc);
  879.         fflush(nc);
  880.         usleep(100000);
  881.  
  882.         fputs("deUrl HTTP/1.1\r", nc);
  883.         fflush(nc);
  884.         usleep(100000);
  885.  
  886.         fputs("\nSec-WebSocket-Key: 123456789012341234567890\r", nc);
  887.         fflush(nc);
  888.         usleep(100000);
  889.  
  890.         fputs("\nUpgrade: websoc", nc);
  891.         fflush(nc);
  892.         usleep(100000);
  893.  
  894.         fputs("ket\r\n\r\n", nc);
  895.         fflush(nc);
  896.         usleep(100000);
  897.         pclose(nc);
  898.  
  899.         // slow GET should get disconnected
  900.         nc = popen("nc localhost 3000 &> /dev/null", "w");
  901.         sleep(3);
  902.         fputs("GET /slowRequest HTTP/1.1\r\n\r\n", nc);
  903.         pclose(nc);
  904.  
  905.         // post tests with increading data length
  906.         for (int j = 0; j < 10; j++) {
  907.             nc = popen("nc localhost 3000 &> /dev/null", "w");
  908.             fputs("POST /postTest HTTP/1.1\r\nContent-Length: ", nc);
  909.  
  910.             int contentLength = j * 1000000;
  911.             std::cout << "POSTing " << contentLength << " bytes" << std::endl;
  912.  
  913.             fputs(std::to_string(contentLength).c_str(), nc);
  914.             fputs("\r\n\r\n", nc);
  915.             for (int i = 0; i < (contentLength / 10); i++) {
  916.                 fputs("0123456789", nc);
  917.             }
  918.             pclose(nc);
  919.         }
  920.  
  921.         // todo: two-in-one GET, two-in-one GET, upgrade, etc
  922.  
  923.         // segmented second GET
  924.         nc = popen("nc localhost 3000 &> /dev/null", "w");
  925.         fputs("GET /packedTest HTTP/1.1\r\n\r\nGET /packedTest HTTP/", nc);
  926.         fflush(nc);
  927.         usleep(100000);
  928.         fputs("1.1\r\n\r\n", nc);
  929.         pclose(nc);
  930.  
  931.         nc = popen("nc localhost 3000 &> /dev/null", "w");
  932.         fputs("GET /packedTest HTTP/1.1\r\n\r\nGET /packedTest HTTP/1.1\r\n\r\n", nc);
  933.         pclose(nc);
  934.  
  935.         // out of order responses
  936.         nc = popen("nc localhost 3000 &> /dev/null", "w");
  937.         fputs("GET /firstRequest HTTP/1.1\r\n\r\nGET /secondRequest HTTP/1.1\r\n\r\n", nc);
  938.         pclose(nc);
  939.  
  940.         // shutdown
  941.         nc = popen("nc localhost 3000 &> /dev/null", "w");
  942.         fputs("PUT /closeServer HTTP/1.1\r\n\r\n", nc);
  943.         pclose(nc);
  944.         if (expectedRequests != 18) {
  945.             std::cerr << "FAILURE: expectedRequests differ: " << expectedRequests << std::endl;
  946.             exit(-1);
  947.         }
  948.     });
  949.  
  950.     h.run();
  951.     t.join();
  952. }
  953.  
  954. // todo: move this out to examples folder, it is not a test but a stragiht up example of EventSource support
  955. void serveEventSource() {
  956.     uWS::Hub h;
  957.  
  958.     std::string document = "<script>var es = new EventSource('/eventSource'); es.onmessage = function(message) {document.write('<p><b>Server sent event:</b> ' + message.data + '</p>');};</script>";
  959.     std::string header = "HTTP/1.1 200 OK\r\nContent-Type: text/event-stream\r\n\r\n";
  960.  
  961.     // stop and delete the libuv timer on http disconnection
  962.     h.onHttpDisconnection([](uWS::HttpSocket<uWS::SERVER> *s) {
  963.         Timer *timer = (Timer *) s->getUserData();
  964.         if (timer) {
  965.             timer->stop();
  966.             timer->close();
  967.         }
  968.     });
  969.  
  970.     // terminate any upgrade attempt, this is http only
  971.     h.onHttpUpgrade([](uWS::HttpSocket<uWS::SERVER> *s, uWS::HttpRequest req) {
  972.         s->terminate();
  973.     });
  974.  
  975.     // httpRequest borde vara defaultsatt till att hantera upgrades, ta bort onupgrade! (s盲tter man request avs盲tts upgrade handlern)
  976.     h.onHttpRequest([&h, &document, &header](uWS::HttpResponse *res, uWS::HttpRequest req, char *data, size_t length, size_t remainingBytes) {
  977.         std::string url = req.getUrl().toString();
  978.  
  979.         if (url == "/") {
  980.             // respond with the document
  981.             res->end((char *) document.data(), document.length());
  982.             return;
  983.         } else if (url == "/eventSource") {
  984.  
  985.             if (!res->getUserData()) {
  986.                 // establish a text/event-stream connection where we can send messages server -> client at any point in time
  987.                 res->write((char *) header.data(), header.length());
  988.  
  989.                 // create and attach a libuv timer to the socket and let it send messages to the client each second
  990.                 Timer *timer = new Timer(h.getLoop());
  991.                 timer->setData(res);
  992.                 timer->start([](Timer *timer) {
  993.                     // send a message to the browser
  994.                     std::string message = "data: Clock sent from the server: " + std::to_string(clock()) + "\n\n";
  995.                     ((uWS::HttpResponse *) timer->getData())->write((char *) message.data(), message.length());
  996.                 }, 1000, 1000);
  997.                 res->setUserData(timer);
  998.             } else {
  999.                 // why would the client send a new request at this point?
  1000.                 res->getHttpSocket()->terminate();
  1001.             }
  1002.         } else {
  1003.             res->getHttpSocket()->terminate();
  1004.         }
  1005.     });
  1006.  
  1007.     h.listen(3000);
  1008.     h.run();
  1009. }
  1010.  
  1011. void serveHttp() {
  1012.     uWS::Hub h;
  1013.  
  1014.     std::string document = "<h2>Well hello there, this is a basic test!</h2>";
  1015.  
  1016.     h.onHttpRequest([&document](uWS::HttpResponse *res, uWS::HttpRequest req, char *data, size_t length, size_t remainingBytes) {
  1017.         res->end(document.data(), document.length());
  1018.     });
  1019.  
  1020.     h.listen(3000);
  1021.     h.run();
  1022. }
  1023.  
  1024. void testReceivePerformance() {
  1025.     // Binary "Rock it with HTML5 WebSocket"
  1026.     unsigned char webSocketMessage[] = {0x82, 0x9c, 0x37, 0x22, 0x79, 0xa5, 0x65, 0x4d, 0x1a, 0xce, 0x17, 0x4b, 0x0d, 0x85, 0x40, 0x4b
  1027.     ,0x0d, 0xcd, 0x17, 0x6a, 0x2d, 0xe8, 0x7b, 0x17, 0x59, 0xf2, 0x52, 0x40, 0x2a, 0xca, 0x54, 0x49
  1028.     ,0x1c, 0xd1};
  1029.  
  1030. //    // Text "Rock it with HTML5 WebSocket"
  1031. //    unsigned char webSocketMessage[] = {0x81, 0x9c, 0x37, 0x22, 0x79, 0xa5, 0x65, 0x4d, 0x1a, 0xce, 0x17, 0x4b, 0x0d, 0x85, 0x40, 0x4b
  1032. //    ,0x0d, 0xcd, 0x17, 0x6a, 0x2d, 0xe8, 0x7b, 0x17, 0x59, 0xf2, 0x52, 0x40, 0x2a, 0xca, 0x54, 0x49
  1033. //    ,0x1c, 0xd1};
  1034.  
  1035. //    // Pong "Rock it with HTML5 WebSocket"
  1036. //    unsigned char webSocketMessage[] = {0x8a, 0x9c, 0x37, 0x22, 0x79, 0xa5, 0x65, 0x4d, 0x1a, 0xce, 0x17, 0x4b, 0x0d, 0x85, 0x40, 0x4b
  1037. //    ,0x0d, 0xcd, 0x17, 0x6a, 0x2d, 0xe8, 0x7b, 0x17, 0x59, 0xf2, 0x52, 0x40, 0x2a, 0xca, 0x54, 0x49
  1038. //    ,0x1c, 0xd1};
  1039.  
  1040.     // time this!
  1041.     int messages = 1000000;
  1042.     size_t bufferLength = sizeof(webSocketMessage) * messages;
  1043.     char *buffer = new char[bufferLength + 4];
  1044.     char *originalBuffer = new char[bufferLength];
  1045.     for (int i = 0; i < messages; i++) {
  1046.         memcpy(originalBuffer + sizeof(webSocketMessage) * i, webSocketMessage, sizeof(webSocketMessage));
  1047.     }
  1048.  
  1049.     uWS::Hub h;
  1050.  
  1051.     h.onConnection([originalBuffer, buffer, bufferLength, messages, &h](uWS::WebSocket<uWS::SERVER> *ws, uWS::HttpRequest req) {
  1052.         for (int i = 0; i < 100; i++) {
  1053.             memcpy(buffer, originalBuffer, bufferLength);
  1054.  
  1055.             auto now = std::chrono::high_resolution_clock::now();
  1056.             uWS::WebSocketProtocol<uWS::SERVER, uWS::WebSocket<uWS::SERVER>>::consume(buffer, bufferLength, ws);
  1057.             int us = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - now).count();
  1058.  
  1059.             std::cout << "Messages per microsecond: " << (double(messages) / double(us)) << std::endl;
  1060.         }
  1061.  
  1062.         h.getDefaultGroup<uWS::SERVER>().close();
  1063.     });
  1064.  
  1065.     h.onMessage([](uWS::WebSocket<uWS::SERVER> *ws, char *message, size_t length, uWS::OpCode opCode) {
  1066.  
  1067.     });
  1068.  
  1069.     h.listen(3000);
  1070.     h.connect("ws://localhost:3000", nullptr);
  1071.     h.run();
  1072.  
  1073.     delete [] buffer;
  1074.     delete [] originalBuffer;
  1075. }
  1076.  
  1077. void testThreadSafety() {
  1078.  
  1079.     uS::TLS::Context c = uS::TLS::createContext("misc/ssl/cert.pem",
  1080.                                                 "misc/ssl/key.pem",
  1081.                                                 "1234");
  1082.  
  1083.     for (int ssl = 0; ssl < 2; ssl++) {
  1084.         std::cout << "SSL: " << ssl << std::endl;
  1085.         uWS::Hub h;
  1086.  
  1087.         uWS::WebSocket<uWS::SERVER> *sharedSocket;
  1088.  
  1089.         std::mutex holdUp;
  1090.         holdUp.lock();
  1091.  
  1092.         std::thread *sendingThreads[10];
  1093.  
  1094.         for (std::thread *&thread : sendingThreads) {
  1095.             thread = new std::thread([&holdUp, &sharedSocket]() {
  1096.                 holdUp.lock();
  1097.                 std::cout << "Starting sending thread" << std::endl;
  1098.                 holdUp.unlock();
  1099.  
  1100.                 for (int i = 0; i < 1000; i++) {
  1101.                     sharedSocket->send("Hello from thread");
  1102.                     std::this_thread::sleep_for(std::chrono::milliseconds(1));
  1103.                 }
  1104.             });
  1105.         }
  1106.  
  1107.         h.onConnection([&sharedSocket, &holdUp](uWS::WebSocket<uWS::SERVER> *ws, uWS::HttpRequest req) {
  1108.             sharedSocket = ws;
  1109.             holdUp.unlock();
  1110.         });
  1111.  
  1112.         int remainingMessages = 1000 * 10;
  1113.  
  1114.         h.onMessage([&sharedSocket, &holdUp, &remainingMessages, &h](uWS::WebSocket<uWS::CLIENT> *ws, char *message, size_t length, uWS::OpCode opCode) {
  1115.             if (strncmp("Hello from thread", message, length)) {
  1116.                 std::cout << "FAILURE: Invalid data received!" << std::endl;
  1117.                 exit(-1);
  1118.             }
  1119.  
  1120.             if (!--remainingMessages) {
  1121.                 h.getDefaultGroup<uWS::SERVER>().close();
  1122.             }
  1123.         });
  1124.  
  1125.  
  1126.         if (ssl) {
  1127.             if (!h.listen(3000, c)) {
  1128.                 std::cout << "FAILURE: cannot listen!" << std::endl;
  1129.             }
  1130.             h.connect("wss://localhost:3000", nullptr);
  1131.         } else {
  1132.             if (!h.listen(3000)) {
  1133.                 std::cout << "FAILURE: cannot listen!" << std::endl;
  1134.             }
  1135.             h.connect("ws://localhost:3000", nullptr);
  1136.         }
  1137.  
  1138.         h.run();
  1139.  
  1140.         for (std::thread *thread : sendingThreads) {
  1141.             thread->join();
  1142.             delete thread;
  1143.         }
  1144.  
  1145.         std::cout << "Everything received" << std::endl;
  1146.     }
  1147. }
  1148.  
  1149. int main(int argc, char *argv[])
  1150. {
  1151.     //serveEventSource();
  1152.     //serveHttp();
  1153.     //serveBenchmark();
  1154.  
  1155. #ifdef UWS_THREADSAFE
  1156.     testThreadSafety();
  1157. #endif
  1158.  
  1159.     // These will run on Travis OS X
  1160.     testReceivePerformance();
  1161.     testStress();
  1162.     testHTTP();
  1163.     testSmallSends();
  1164.     testSendCallback();
  1165.     testRouting();
  1166.     testClosing();
  1167.     testListening();
  1168.     testBroadcast();
  1169.     testMessageBatch();
  1170.     testAutoPing();
  1171.     testConnections();
  1172.     testTransfers();
  1173.  
  1174.     // Linux-only feature
  1175. #ifdef __linux__
  1176.     testReusePort();
  1177. #endif
  1178.  
  1179.     //testAutobahn();
  1180. }
  1181.  
downloadmain.cpp Source code - Download uWebSockets Source code
Related Source Codes/Software:
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
postal - 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11

 Back to top