_ZN3uWS12TemplatedAppILb0EEC2ENS_20SocketContextOptionsE:
  217|  6.41k|    TemplatedApp(SocketContextOptions options = {}) {
  218|  6.41k|        httpContext = HttpContext<SSL>::create(Loop::get(), options);
  219|       |
  220|       |        /* Register default handler for 404 (can be overridden by user) */
  221|  6.41k|        this->any("/*", [](auto *res, auto */*req*/) {
  222|  6.41k|		    res->writeStatus("404 File Not Found");
  223|  6.41k|	        res->end("<html><body><h1>File Not Found</h1><hr><i>uWebSockets/20 Server</i></body></html>");
  224|  6.41k|        });
  225|  6.41k|    }
_ZNK3uWS20SocketContextOptionscv27us_socket_context_options_tEv:
   71|  6.41k|        operator struct us_socket_context_options_t() const {
   72|  6.41k|            struct us_socket_context_options_t socket_context_options;
   73|  6.41k|            memcpy(&socket_context_options, this, sizeof(SocketContextOptions));
   74|  6.41k|            return socket_context_options;
   75|  6.41k|        }
_ZZN3uWS12TemplatedAppILb0EEC1ENS_20SocketContextOptionsEENKUlPT_PT0_E_clINS_12HttpResponseILb0EEENS_11HttpRequestEEEDaS4_S6_:
  221|  4.04k|        this->any("/*", [](auto *res, auto */*req*/) {
  222|  4.04k|		    res->writeStatus("404 File Not Found");
  223|  4.04k|	        res->end("<html><body><h1>File Not Found</h1><hr><i>uWebSockets/20 Server</i></body></html>");
  224|  4.04k|        });
_ZN3uWS12TemplatedAppILb0EED2Ev:
  177|  12.8k|    ~TemplatedApp() {
  178|       |        /* Let's just put everything here */
  179|  12.8k|        if (httpContext) {
  ------------------
  |  Branch (179:13): [True: 6.41k, False: 6.41k]
  ------------------
  180|  6.41k|            httpContext->free();
  181|       |
  182|       |            /* Free all our webSocketContexts in a type less way */
  183|  12.8k|            for (auto &webSocketContextDeleter : webSocketContextDeleters) {
  ------------------
  |  Branch (183:48): [True: 12.8k, False: 6.41k]
  ------------------
  184|  12.8k|                webSocketContextDeleter();
  185|  12.8k|            }
  186|  6.41k|        }
  187|       |
  188|       |        /* Delete TopicTree */
  189|  12.8k|        if (topicTree) {
  ------------------
  |  Branch (189:13): [True: 6.41k, False: 6.41k]
  ------------------
  190|  6.41k|            delete topicTree;
  191|       |
  192|       |            /* And unregister loop callbacks */
  193|       |            /* We must unregister any loop post handler here */
  194|  6.41k|            Loop::get()->removePostHandler(topicTree);
  195|  6.41k|            Loop::get()->removePreHandler(topicTree);
  196|  6.41k|        }
  197|  12.8k|    }
EpollHelloWorld.cpp:_ZN3uWS12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS1_NSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEONS1_17WebSocketBehaviorIT_EE:
  270|  12.8k|    TemplatedApp &&ws(std::string pattern, WebSocketBehavior<UserData> &&behavior) {
  271|       |        /* Don't compile if alignment rules cannot be satisfied */
  272|  12.8k|        static_assert(alignof(UserData) <= LIBUS_EXT_ALIGNMENT,
  273|  12.8k|        "µWebSockets cannot satisfy UserData alignment requirements. You need to recompile µSockets with LIBUS_EXT_ALIGNMENT adjusted accordingly.");
  274|       |
  275|  12.8k|        if (!httpContext) {
  ------------------
  |  Branch (275:13): [True: 0, False: 12.8k]
  ------------------
  276|      0|            return std::move(*this);
  277|      0|        }
  278|       |
  279|       |        /* Terminate on misleading idleTimeout values */
  280|  12.8k|        if (behavior.idleTimeout && behavior.idleTimeout < 8) {
  ------------------
  |  Branch (280:13): [True: 12.8k, False: 0]
  |  Branch (280:37): [True: 0, False: 12.8k]
  ------------------
  281|      0|            std::cerr << "Error: idleTimeout must be either 0 or greater than 8!" << std::endl;
  282|      0|            std::terminate();
  283|      0|        }
  284|       |
  285|       |        /* Maximum idleTimeout is 16 minutes */
  286|  12.8k|        if (behavior.idleTimeout > 240 * 4) {
  ------------------
  |  Branch (286:13): [True: 0, False: 12.8k]
  ------------------
  287|      0|            std::cerr << "Error: idleTimeout must not be greater than 960 seconds!" << std::endl;
  288|      0|            std::terminate();
  289|      0|        }
  290|       |
  291|       |        /* Maximum maxLifetime is 4 hours */
  292|  12.8k|        if (behavior.maxLifetime > 240) {
  ------------------
  |  Branch (292:13): [True: 0, False: 12.8k]
  ------------------
  293|      0|            std::cerr << "Error: maxLifetime must not be greater than 240 minutes!" << std::endl;
  294|      0|            std::terminate();
  295|      0|        }
  296|       |
  297|       |        /* If we don't have a TopicTree yet, create one now */
  298|  12.8k|        if (!topicTree) {
  ------------------
  |  Branch (298:13): [True: 6.41k, False: 6.41k]
  ------------------
  299|       |
  300|  6.41k|            bool needsUncork = false;
  301|  6.41k|            topicTree = new TopicTree<TopicTreeMessage, TopicTreeBigMessage>([needsUncork](Subscriber *s, TopicTreeMessage &message, TopicTree<TopicTreeMessage, TopicTreeBigMessage>::IteratorFlags flags) mutable {
  302|       |                /* Subscriber's user is the socket */
  303|       |                /* Unfortunately we need to cast is to PerSocketData = int
  304|       |                 * since many different WebSocketContexts use the same
  305|       |                 * TopicTree now */
  306|  6.41k|                auto *ws = (WebSocket<SSL, true, int> *) s->user;
  307|       |
  308|       |                /* If this is the first message we try and cork */
  309|  6.41k|                if (flags & TopicTree<TopicTreeMessage, TopicTreeBigMessage>::IteratorFlags::FIRST) {
  310|  6.41k|                    if (ws->canCork() && !ws->isCorked()) {
  311|  6.41k|                        ((AsyncSocket<SSL> *)ws)->cork();
  312|  6.41k|                        needsUncork = true;
  313|  6.41k|                    }
  314|  6.41k|                }
  315|       |
  316|       |                /* If we ever overstep maxBackpresure, exit immediately */
  317|  6.41k|                if (WebSocket<SSL, true, int>::SendStatus::DROPPED == ws->send(message.message, (OpCode)message.opCode, message.compress)) {
  318|  6.41k|                    if (needsUncork) {
  319|  6.41k|                        ((AsyncSocket<SSL> *)ws)->uncork();
  320|  6.41k|                        needsUncork = false;
  321|  6.41k|                    }
  322|       |                    /* Stop draining */
  323|  6.41k|                    return true;
  324|  6.41k|                }
  325|       |
  326|       |                /* If this is the last message we uncork if we are corked */
  327|  6.41k|                if (flags & TopicTree<TopicTreeMessage, TopicTreeBigMessage>::IteratorFlags::LAST) {
  328|       |                    /* We should not uncork in all cases? */
  329|  6.41k|                    if (needsUncork) {
  330|  6.41k|                        ((AsyncSocket<SSL> *)ws)->uncork();
  331|  6.41k|                    }
  332|  6.41k|                }
  333|       |
  334|       |                /* Success */
  335|  6.41k|                return false;
  336|  6.41k|            });
  337|       |
  338|       |            /* And hook it up with the loop */
  339|       |            /* We empty for both pre and post just to make sure */
  340|  6.41k|            Loop::get()->addPostHandler(topicTree, [topicTree = topicTree](Loop */*loop*/) {
  341|       |                /* Commit pub/sub batches every loop iteration */
  342|  6.41k|                topicTree->drain();
  343|  6.41k|            });
  344|       |
  345|  6.41k|            Loop::get()->addPreHandler(topicTree, [topicTree = topicTree](Loop */*loop*/) {
  346|       |                /* Commit pub/sub batches every loop iteration */
  347|  6.41k|                topicTree->drain();
  348|  6.41k|            });
  349|  6.41k|        }
  350|       |
  351|       |        /* Every route has its own websocket context with its own behavior and user data type */
  352|  12.8k|        auto *webSocketContext = WebSocketContext<SSL, true, UserData>::create(Loop::get(), (us_socket_context_t *) httpContext, topicTree);
  353|       |
  354|       |        /* We need to clear this later on */
  355|  12.8k|        webSocketContextDeleters.push_back([webSocketContext]() {
  356|  12.8k|            webSocketContext->free();
  357|  12.8k|        });
  358|       |
  359|       |        /* We also keep this list for easy closing */
  360|  12.8k|        webSocketContexts.push_back((void *)webSocketContext);
  361|       |
  362|       |        /* Quick fix to disable any compression if set */
  363|       |#ifdef UWS_NO_ZLIB
  364|       |        behavior.compression = DISABLED;
  365|       |#endif
  366|       |
  367|       |        /* If we are the first one to use compression, initialize it */
  368|  12.8k|        if (behavior.compression) {
  ------------------
  |  Branch (368:13): [True: 6.41k, False: 6.41k]
  ------------------
  369|  6.41k|            LoopData *loopData = (LoopData *) us_loop_ext(us_socket_context_loop(SSL, webSocketContext->getSocketContext()));
  370|       |
  371|       |            /* Initialize loop's deflate inflate streams */
  372|  6.41k|            if (!loopData->zlibContext) {
  ------------------
  |  Branch (372:17): [True: 6.41k, False: 0]
  ------------------
  373|  6.41k|                loopData->zlibContext = new ZlibContext;
  374|  6.41k|                loopData->inflationStream = new InflationStream(CompressOptions::DEDICATED_DECOMPRESSOR);
  375|  6.41k|                loopData->deflationStream = new DeflationStream(CompressOptions::DEDICATED_COMPRESSOR);
  376|  6.41k|            }
  377|  6.41k|        }
  378|       |
  379|       |        /* Copy all handlers */
  380|  12.8k|        webSocketContext->getExt()->openHandler = std::move(behavior.open);
  381|  12.8k|        webSocketContext->getExt()->messageHandler = std::move(behavior.message);
  382|  12.8k|        webSocketContext->getExt()->droppedHandler = std::move(behavior.dropped);
  383|  12.8k|        webSocketContext->getExt()->drainHandler = std::move(behavior.drain);
  384|  12.8k|        webSocketContext->getExt()->subscriptionHandler = std::move(behavior.subscription);
  385|  12.8k|        webSocketContext->getExt()->closeHandler = std::move([closeHandler = std::move(behavior.close)](WebSocket<SSL, true, UserData> *ws, int code, std::string_view message) mutable {
  386|  12.8k|            if (closeHandler) {
  387|  12.8k|                closeHandler(ws, code, message);
  388|  12.8k|            }
  389|       |
  390|       |            /* Destruct user data after returning from close handler */
  391|  12.8k|            ((UserData *) ws->getUserData())->~UserData();
  392|  12.8k|        });
  393|  12.8k|        webSocketContext->getExt()->pingHandler = std::move(behavior.ping);
  394|  12.8k|        webSocketContext->getExt()->pongHandler = std::move(behavior.pong);
  395|       |
  396|       |        /* Copy settings */
  397|  12.8k|        webSocketContext->getExt()->maxPayloadLength = behavior.maxPayloadLength;
  398|  12.8k|        webSocketContext->getExt()->maxBackpressure = behavior.maxBackpressure;
  399|  12.8k|        webSocketContext->getExt()->closeOnBackpressureLimit = behavior.closeOnBackpressureLimit;
  400|  12.8k|        webSocketContext->getExt()->resetIdleTimeoutOnSend = behavior.resetIdleTimeoutOnSend;
  401|  12.8k|        webSocketContext->getExt()->sendPingsAutomatically = behavior.sendPingsAutomatically;
  402|  12.8k|        webSocketContext->getExt()->maxLifetime = behavior.maxLifetime;
  403|  12.8k|        webSocketContext->getExt()->compression = behavior.compression;
  404|       |
  405|       |        /* Calculate idleTimeoutCompnents */
  406|  12.8k|        webSocketContext->getExt()->calculateIdleTimeoutCompnents(behavior.idleTimeout);
  407|       |
  408|  12.8k|        httpContext->onHttp("GET", pattern, [webSocketContext, behavior = std::move(behavior)](auto *res, auto *req) mutable {
  409|       |
  410|       |            /* If we have this header set, it's a websocket */
  411|  12.8k|            std::string_view secWebSocketKey = req->getHeader("sec-websocket-key");
  412|  12.8k|            if (secWebSocketKey.length() == 24) {
  413|       |
  414|       |                /* Emit upgrade handler */
  415|  12.8k|                if (behavior.upgrade) {
  416|       |
  417|       |                    /* Nasty, ugly Safari 15 hack */
  418|  12.8k|                    if (hasBrokenCompression(req->getHeader("user-agent"))) {
  419|  12.8k|                        std::string_view secWebSocketExtensions = req->getHeader("sec-websocket-extensions");
  420|  12.8k|                        memset((void *) secWebSocketExtensions.data(), ' ', secWebSocketExtensions.length());
  421|  12.8k|                    }
  422|       |
  423|  12.8k|                    behavior.upgrade(res, req, (struct us_socket_context_t *) webSocketContext);
  424|  12.8k|                } else {
  425|       |                    /* Default handler upgrades to WebSocket */
  426|  12.8k|                    std::string_view secWebSocketProtocol = req->getHeader("sec-websocket-protocol");
  427|  12.8k|                    std::string_view secWebSocketExtensions = req->getHeader("sec-websocket-extensions");
  428|       |
  429|       |                    /* Safari 15 hack */
  430|  12.8k|                    if (hasBrokenCompression(req->getHeader("user-agent"))) {
  431|  12.8k|                        secWebSocketExtensions = "";
  432|  12.8k|                    }
  433|       |
  434|  12.8k|                    res->template upgrade<UserData>({}, secWebSocketKey, secWebSocketProtocol, secWebSocketExtensions, (struct us_socket_context_t *) webSocketContext);
  435|  12.8k|                }
  436|       |
  437|       |                /* We are going to get uncorked by the Http get return */
  438|       |
  439|       |                /* We do not need to check for any close or shutdown here as we immediately return from get handler */
  440|       |
  441|  12.8k|            } else {
  442|       |                /* Tell the router that we did not handle this request */
  443|  12.8k|                req->setYield(true);
  444|  12.8k|            }
  445|  12.8k|        }, true);
  446|  12.8k|        return std::move(*this);
  447|  12.8k|    }
EpollHelloWorld.cpp:_ZZN3uWS12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS1_NSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEONS1_17WebSocketBehaviorIT_EEENKUlPNS_4LoopEE_clESH_:
  340|  1.59M|            Loop::get()->addPostHandler(topicTree, [topicTree = topicTree](Loop */*loop*/) {
  341|       |                /* Commit pub/sub batches every loop iteration */
  342|  1.59M|                topicTree->drain();
  343|  1.59M|            });
EpollHelloWorld.cpp:_ZZN3uWS12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS1_NSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEONS1_17WebSocketBehaviorIT_EEENKUlPNS_4LoopEE0_clESH_:
  345|  1.59M|            Loop::get()->addPreHandler(topicTree, [topicTree = topicTree](Loop */*loop*/) {
  346|       |                /* Commit pub/sub batches every loop iteration */
  347|  1.59M|                topicTree->drain();
  348|  1.59M|            });
EpollHelloWorld.cpp:_ZZN3uWS12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS1_NSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEONS1_17WebSocketBehaviorIT_EEENKUlvE_clEv:
  355|  12.8k|        webSocketContextDeleters.push_back([webSocketContext]() {
  356|  12.8k|            webSocketContext->free();
  357|  12.8k|        });
EpollHelloWorld.cpp:_ZZN3uWS12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS1_NSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEONS1_17WebSocketBehaviorIT_EEENUlPNS_9WebSocketILb0ELb1ES3_EEiNS5_17basic_string_viewIcS8_EEE_clESI_iSK_:
  385|  40.1k|        webSocketContext->getExt()->closeHandler = std::move([closeHandler = std::move(behavior.close)](WebSocket<SSL, true, UserData> *ws, int code, std::string_view message) mutable {
  386|  40.1k|            if (closeHandler) {
  ------------------
  |  Branch (386:17): [True: 39.0k, False: 1.08k]
  ------------------
  387|  39.0k|                closeHandler(ws, code, message);
  388|  39.0k|            }
  389|       |
  390|       |            /* Destruct user data after returning from close handler */
  391|  40.1k|            ((UserData *) ws->getUserData())->~UserData();
  392|  40.1k|        });
EpollHelloWorld.cpp:_ZZN3uWS12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS1_NSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEONS1_17WebSocketBehaviorIT_EEENUlPSD_PT0_E_clINS_12HttpResponseILb0EEENS_11HttpRequestEEEDaSG_SI_:
  408|  50.8k|        httpContext->onHttp("GET", pattern, [webSocketContext, behavior = std::move(behavior)](auto *res, auto *req) mutable {
  409|       |
  410|       |            /* If we have this header set, it's a websocket */
  411|  50.8k|            std::string_view secWebSocketKey = req->getHeader("sec-websocket-key");
  412|  50.8k|            if (secWebSocketKey.length() == 24) {
  ------------------
  |  Branch (412:17): [True: 40.1k, False: 10.6k]
  ------------------
  413|       |
  414|       |                /* Emit upgrade handler */
  415|  40.1k|                if (behavior.upgrade) {
  ------------------
  |  Branch (415:21): [True: 0, False: 40.1k]
  ------------------
  416|       |
  417|       |                    /* Nasty, ugly Safari 15 hack */
  418|      0|                    if (hasBrokenCompression(req->getHeader("user-agent"))) {
  ------------------
  |  Branch (418:25): [True: 0, False: 0]
  ------------------
  419|      0|                        std::string_view secWebSocketExtensions = req->getHeader("sec-websocket-extensions");
  420|      0|                        memset((void *) secWebSocketExtensions.data(), ' ', secWebSocketExtensions.length());
  421|      0|                    }
  422|       |
  423|      0|                    behavior.upgrade(res, req, (struct us_socket_context_t *) webSocketContext);
  424|  40.1k|                } else {
  425|       |                    /* Default handler upgrades to WebSocket */
  426|  40.1k|                    std::string_view secWebSocketProtocol = req->getHeader("sec-websocket-protocol");
  427|  40.1k|                    std::string_view secWebSocketExtensions = req->getHeader("sec-websocket-extensions");
  428|       |
  429|       |                    /* Safari 15 hack */
  430|  40.1k|                    if (hasBrokenCompression(req->getHeader("user-agent"))) {
  ------------------
  |  Branch (430:25): [True: 226, False: 39.9k]
  ------------------
  431|    226|                        secWebSocketExtensions = "";
  432|    226|                    }
  433|       |
  434|  40.1k|                    res->template upgrade<UserData>({}, secWebSocketKey, secWebSocketProtocol, secWebSocketExtensions, (struct us_socket_context_t *) webSocketContext);
  435|  40.1k|                }
  436|       |
  437|       |                /* We are going to get uncorked by the Http get return */
  438|       |
  439|       |                /* We do not need to check for any close or shutdown here as we immediately return from get handler */
  440|       |
  441|  40.1k|            } else {
  442|       |                /* Tell the router that we did not handle this request */
  443|  10.6k|                req->setYield(true);
  444|  10.6k|            }
  445|  50.8k|        }, true);
_ZN3uWS20hasBrokenCompressionENSt3__117basic_string_viewIcNS0_11char_traitsIcEEEE:
   29|  40.1k|    inline bool hasBrokenCompression(std::string_view userAgent) {
   30|  40.1k|        size_t posStart = userAgent.find(" Version/15.");
   31|  40.1k|        if (posStart == std::string_view::npos) return false;
  ------------------
  |  Branch (31:13): [True: 26.3k, False: 13.8k]
  ------------------
   32|  13.8k|        posStart += 12;
   33|       |
   34|  13.8k|        size_t posEnd = userAgent.find(' ', posStart);
   35|  13.8k|        if (posEnd == std::string_view::npos) return false;
  ------------------
  |  Branch (35:13): [True: 524, False: 13.3k]
  ------------------
   36|       |
   37|  13.3k|        unsigned int minorVersion = 0;
   38|  13.3k|        auto result = std::from_chars(userAgent.data() + posStart, userAgent.data() + posEnd, minorVersion);
   39|  13.3k|        if (result.ec != std::errc()) return false;
  ------------------
  |  Branch (39:13): [True: 5.39k, False: 7.93k]
  ------------------
   40|  7.93k|        if (result.ptr != userAgent.data() + posEnd) return false; // do not accept trailing chars
  ------------------
  |  Branch (40:13): [True: 3.89k, False: 4.03k]
  ------------------
   41|  4.03k|        if (minorVersion > 3) return false; // we target just Safari 15.0 - 15.3
  ------------------
  |  Branch (41:13): [True: 2.68k, False: 1.35k]
  ------------------
   42|       |
   43|  1.35k|        if (userAgent.find(" Safari/", posEnd) == std::string_view::npos) return false;
  ------------------
  |  Branch (43:13): [True: 1.12k, False: 226]
  ------------------
   44|       |
   45|    226|        return true;
   46|  1.35k|    }
_ZN3uWS12TemplatedAppILb0EE3getENSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEON5ofats13any_invocableIFvPNS_12HttpResponseILb0EEEPNS_11HttpRequestEEEE:
  465|  6.41k|    TemplatedApp &&get(std::string pattern, MoveOnlyFunction<void(HttpResponse<SSL> *, HttpRequest *)> &&handler) {
  466|  6.41k|        if (httpContext) {
  ------------------
  |  Branch (466:13): [True: 6.41k, False: 0]
  ------------------
  467|  6.41k|            httpContext->onHttp("GET", pattern, std::move(handler));
  468|  6.41k|        }
  469|  6.41k|        return std::move(*this);
  470|  6.41k|    }
_ZN3uWS12TemplatedAppILb0EE4postENSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEON5ofats13any_invocableIFvPNS_12HttpResponseILb0EEEPNS_11HttpRequestEEEE:
  472|  6.41k|    TemplatedApp &&post(std::string pattern, MoveOnlyFunction<void(HttpResponse<SSL> *, HttpRequest *)> &&handler) {
  473|  6.41k|        if (httpContext) {
  ------------------
  |  Branch (473:13): [True: 6.41k, False: 0]
  ------------------
  474|  6.41k|            httpContext->onHttp("POST", pattern, std::move(handler));
  475|  6.41k|        }
  476|  6.41k|        return std::move(*this);
  477|  6.41k|    }
_ZN3uWS12TemplatedAppILb0EE3anyENSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEON5ofats13any_invocableIFvPNS_12HttpResponseILb0EEEPNS_11HttpRequestEEEE:
  529|  12.8k|    TemplatedApp &&any(std::string pattern, MoveOnlyFunction<void(HttpResponse<SSL> *, HttpRequest *)> &&handler) {
  530|  12.8k|        if (httpContext) {
  ------------------
  |  Branch (530:13): [True: 12.8k, False: 0]
  ------------------
  531|  12.8k|            httpContext->onHttp("*", pattern, std::move(handler));
  532|  12.8k|        }
  533|  12.8k|        return std::move(*this);
  534|  12.8k|    }
_ZN3uWS12TemplatedAppILb0EE6listenEiON5ofats13any_invocableIFvP18us_listen_socket_tEEE:
  555|  6.41k|    TemplatedApp &&listen(int port, MoveOnlyFunction<void(us_listen_socket_t *)> &&handler) {
  556|  6.41k|        handler(httpContext ? httpContext->listen(nullptr, port, 0) : nullptr);
  ------------------
  |  Branch (556:17): [True: 6.41k, False: 0]
  ------------------
  557|  6.41k|        return std::move(*this);
  558|  6.41k|    }
_ZN3uWS12TemplatedAppILb0EEC2EOS1_:
  202|  6.41k|    TemplatedApp(TemplatedApp &&other) {
  203|       |        /* Move HttpContext */
  204|  6.41k|        httpContext = other.httpContext;
  205|  6.41k|        other.httpContext = nullptr;
  206|       |
  207|       |        /* Move webSocketContextDeleters */
  208|  6.41k|        webSocketContextDeleters = std::move(other.webSocketContextDeleters);
  209|       |
  210|  6.41k|        webSocketContexts = std::move(other.webSocketContexts);
  211|       |
  212|       |        /* Move TopicTree */
  213|  6.41k|        topicTree = other.topicTree;
  214|  6.41k|        other.topicTree = nullptr;
  215|  6.41k|    }
_ZN3uWS12TemplatedAppILb0EE13addServerNameENSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS_20SocketContextOptionsE:
   95|  6.41k|    TemplatedApp &&addServerName(std::string hostname_pattern, SocketContextOptions options = {}) {
   96|       |
   97|       |        /* Do nothing if not even on SSL */
   98|  6.41k|        if constexpr (SSL) {
  ------------------
  |  Branch (98:23): [Folded - Ignored]
  ------------------
   99|       |            /* First we create a new router for this domain */
  100|  6.41k|            auto *domainRouter = new HttpRouter<typename HttpContextData<SSL>::RouterData>();
  101|       |
  102|  6.41k|            us_socket_context_add_server_name(SSL, (struct us_socket_context_t *) httpContext, hostname_pattern.c_str(), options, domainRouter);
  103|  6.41k|        }
  104|       |
  105|  6.41k|        return std::move(*this);
  106|  6.41k|    }
_ZN3uWS12TemplatedAppILb0EE16removeServerNameENSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
  108|  6.41k|    TemplatedApp &&removeServerName(std::string hostname_pattern) {
  109|       |    
  110|       |        /* This will do for now, would be better if us_socket_context_remove_server_name returned the user data */
  111|  6.41k|        auto *domainRouter = us_socket_context_find_server_name_userdata(SSL, (struct us_socket_context_t *) httpContext, hostname_pattern.c_str());
  112|  6.41k|        if (domainRouter) {
  ------------------
  |  Branch (112:13): [True: 0, False: 6.41k]
  ------------------
  113|      0|            delete (HttpRouter<typename HttpContextData<SSL>::RouterData> *) domainRouter;
  114|      0|        }
  115|       |
  116|  6.41k|        us_socket_context_remove_server_name(SSL, (struct us_socket_context_t *) httpContext, hostname_pattern.c_str());
  117|  6.41k|        return std::move(*this);
  118|  6.41k|    }
_ZN3uWS12TemplatedAppILb0EE17missingServerNameEN5ofats13any_invocableIFvPKcEEE:
  120|  6.41k|    TemplatedApp &&missingServerName(MoveOnlyFunction<void(const char *hostname)> handler) {
  121|       |
  122|  6.41k|        if (!constructorFailed()) {
  ------------------
  |  Branch (122:13): [True: 6.41k, False: 0]
  ------------------
  123|  6.41k|            httpContext->getSocketContextData()->missingServerNameHandler = std::move(handler);
  124|       |
  125|  6.41k|            us_socket_context_on_server_name(SSL, (struct us_socket_context_t *) httpContext, [](struct us_socket_context_t *context, const char *hostname) {
  126|       |
  127|       |                /* This is the only requirements of being friends with HttpContextData */
  128|  6.41k|                HttpContext<SSL> *httpContext = (HttpContext<SSL> *) context;
  129|  6.41k|                httpContext->getSocketContextData()->missingServerNameHandler(hostname);
  130|  6.41k|            });
  131|  6.41k|        }
  132|       |
  133|  6.41k|        return std::move(*this);
  134|  6.41k|    }
_ZN3uWS12TemplatedAppILb0EE17constructorFailedEv:
  227|  6.41k|    bool constructorFailed() {
  228|  6.41k|        return !httpContext;
  229|  6.41k|    }
_ZN3uWS12TemplatedAppILb0EE15getNativeHandleEv:
  137|  6.41k|    void *getNativeHandle() {
  138|  6.41k|        return us_socket_context_get_native_handle(SSL, (struct us_socket_context_t *) httpContext);
  139|  6.41k|    }
_ZN3uWS12TemplatedAppILb0EE3runEv:
  590|  6.41k|    TemplatedApp &&run() {
  591|  6.41k|        uWS::run();
  592|  6.41k|        return std::move(*this);
  593|  6.41k|    }

_ZN3uWS11AsyncSocketILb0EE4corkEv:
  133|   440k|    void cork() {
  134|       |        /* Extra check for invalid corking of others */
  135|   440k|        if (getLoopData()->corkOffset && getLoopData()->corkedSocket != this) {
  ------------------
  |  Branch (135:13): [True: 0, False: 440k]
  |  Branch (135:42): [True: 0, False: 0]
  ------------------
  136|      0|            std::cerr << "Error: Cork buffer must not be acquired without checking canCork!" << std::endl;
  137|      0|            std::terminate();
  138|      0|        }
  139|       |
  140|       |        /* What if another socket is corked? */
  141|   440k|        getLoopData()->corkedSocket = this;
  142|   440k|    }
_ZN3uWS11AsyncSocketILb0EE11getLoopDataEv:
   85|  3.03M|    LoopData *getLoopData() {
   86|  3.03M|        return (LoopData *) us_loop_ext(us_socket_context_loop(SSL, us_socket_context(SSL, (us_socket_t *) this)));
   87|  3.03M|    }
_ZN3uWS11AsyncSocketILb0EE6uncorkEPKcib:
  327|   440k|    std::pair<int, bool> uncork(const char *src = nullptr, int length = 0, bool optionally = false) {
  328|   440k|        LoopData *loopData = getLoopData();
  329|       |
  330|   440k|        if (loopData->corkedSocket == this) {
  ------------------
  |  Branch (330:13): [True: 440k, False: 0]
  ------------------
  331|   440k|            loopData->corkedSocket = nullptr;
  332|       |
  333|   440k|            if (loopData->corkOffset) {
  ------------------
  |  Branch (333:17): [True: 52.6k, False: 388k]
  ------------------
  334|       |                /* Corked data is already accounted for via its write call */
  335|  52.6k|                auto [written, failed] = write(loopData->corkBuffer, (int) loopData->corkOffset, false, length);
  336|  52.6k|                loopData->corkOffset = 0;
  337|       |
  338|  52.6k|                if (failed) {
  ------------------
  |  Branch (338:21): [True: 44.4k, False: 8.21k]
  ------------------
  339|       |                    /* We do not need to care for buffering here, write does that */
  340|  44.4k|                    return {0, true};
  341|  44.4k|                }
  342|  52.6k|            }
  343|       |
  344|       |            /* We should only return with new writes, not things written to cork already */
  345|   396k|            return write(src, length, optionally, 0);
  346|   440k|        } else {
  347|       |            /* We are not even corked! */
  348|      0|            return {0, false};
  349|      0|        }
  350|   440k|    }
_ZN3uWS11AsyncSocketILb0EE5writeEPKcibi:
  236|  1.75M|    std::pair<int, bool> write(const char *src, int length, bool optionally = false, int nextLength = 0) {
  237|       |        /* Fake success if closed, simple fix to allow uncork of closed socket to succeed */
  238|  1.75M|        if (us_socket_is_closed(SSL, (us_socket_t *) this)) {
  ------------------
  |  Branch (238:13): [True: 300k, False: 1.45M]
  ------------------
  239|   300k|            return {length, false};
  240|   300k|        }
  241|       |
  242|  1.45M|        LoopData *loopData = getLoopData();
  243|  1.45M|        AsyncSocketData<SSL> *asyncSocketData = getAsyncSocketData();
  244|       |
  245|       |        /* We are limited if we have a per-socket buffer */
  246|  1.45M|        if (asyncSocketData->buffer.length()) {
  ------------------
  |  Branch (246:13): [True: 104k, False: 1.34M]
  ------------------
  247|       |            /* Write off as much as we can */
  248|   104k|            int written = us_socket_write(SSL, (us_socket_t *) this, asyncSocketData->buffer.data(), (int) asyncSocketData->buffer.length(), /*nextLength != 0 | */length);
  249|       |
  250|       |            /* On failure return, otherwise continue down the function */
  251|   104k|            if ((unsigned int) written < asyncSocketData->buffer.length()) {
  ------------------
  |  Branch (251:17): [True: 99.8k, False: 5.10k]
  ------------------
  252|       |
  253|       |                /* Update buffering (todo: we can do better here if we keep track of what happens to this guy later on) */
  254|  99.8k|                asyncSocketData->buffer.erase((unsigned int) written);
  255|       |
  256|  99.8k|                if (optionally) {
  ------------------
  |  Branch (256:21): [True: 2.42k, False: 97.4k]
  ------------------
  257|       |                    /* Thankfully we can exit early here */
  258|  2.42k|                    return {0, true};
  259|  97.4k|                } else {
  260|       |                    /* This path is horrible and points towards erroneous usage */
  261|  97.4k|                    asyncSocketData->buffer.append(src, (unsigned int) length);
  262|       |
  263|  97.4k|                    return {length, true};
  264|  97.4k|                }
  265|  99.8k|            }
  266|       |
  267|       |            /* At this point we simply have no buffer and can continue as normal */
  268|  5.10k|            asyncSocketData->buffer.clear();
  269|  5.10k|        }
  270|       |
  271|  1.35M|        if (length) {
  ------------------
  |  Branch (271:13): [True: 1.30M, False: 44.0k]
  ------------------
  272|  1.30M|            if (loopData->corkedSocket == this) {
  ------------------
  |  Branch (272:17): [True: 1.26M, False: 48.0k]
  ------------------
  273|       |                /* We are corked */
  274|  1.26M|                if (LoopData::CORK_BUFFER_SIZE - loopData->corkOffset >= (unsigned int) length) {
  ------------------
  |  Branch (274:21): [True: 1.26M, False: 0]
  ------------------
  275|       |                    /* If the entire chunk fits in cork buffer */
  276|  1.26M|                    memcpy(loopData->corkBuffer + loopData->corkOffset, src, (unsigned int) length);
  277|  1.26M|                    loopData->corkOffset += (unsigned int) length;
  278|       |                    /* Fall through to default return */
  279|  1.26M|                } else {
  280|       |                    /* Strategy differences between SSL and non-SSL regarding syscall minimizing */
  281|      0|                    if constexpr (false) {
  ------------------
  |  Branch (281:35): [Folded - Ignored]
  ------------------
  282|       |                        /* Cork up as much as we can */
  283|      0|                        unsigned int stripped = LoopData::CORK_BUFFER_SIZE - loopData->corkOffset;
  284|      0|                        memcpy(loopData->corkBuffer + loopData->corkOffset, src, stripped);
  285|      0|                        loopData->corkOffset = LoopData::CORK_BUFFER_SIZE;
  286|       |
  287|      0|                        auto [written, failed] = uncork(src + stripped, length - (int) stripped, optionally);
  288|      0|                        return {written + (int) stripped, failed};
  289|      0|                    }
  290|       |
  291|       |                    /* For non-SSL we take the penalty of two syscalls */
  292|      0|                    return uncork(src, length, optionally);
  293|      0|                }
  294|  1.26M|            } else {
  295|       |                /* We are not corked */
  296|  48.0k|                int written = us_socket_write(SSL, (us_socket_t *) this, src, length, nextLength != 0);
  297|       |
  298|       |                /* Did we fail? */
  299|  48.0k|                if (written < length) {
  ------------------
  |  Branch (299:21): [True: 45.5k, False: 2.57k]
  ------------------
  300|       |                    /* If the write was optional then just bail out */
  301|  45.5k|                    if (optionally) {
  ------------------
  |  Branch (301:25): [True: 0, False: 45.5k]
  ------------------
  302|      0|                        return {written, true};
  303|      0|                    }
  304|       |
  305|       |                    /* Fall back to worst possible case (should be very rare for HTTP) */
  306|       |                    /* At least we can reserve room for next chunk if we know it up front */
  307|  45.5k|                    if (nextLength) {
  ------------------
  |  Branch (307:25): [True: 0, False: 45.5k]
  ------------------
  308|      0|                        asyncSocketData->buffer.reserve(asyncSocketData->buffer.length() + (size_t) (length - written + nextLength));
  309|      0|                    }
  310|       |
  311|       |                    /* Buffer this chunk */
  312|  45.5k|                    asyncSocketData->buffer.append(src + written, (size_t) (length - written));
  313|       |
  314|       |                    /* Return the failure */
  315|  45.5k|                    return {length, true};
  316|  45.5k|                }
  317|       |                /* Fall through to default return */
  318|  48.0k|            }
  319|  1.30M|        }
  320|       |
  321|       |        /* Default fall through return */
  322|  1.30M|        return {length, false};
  323|  1.35M|    }
_ZN3uWS11AsyncSocketILb0EE7timeoutEj:
   95|   174k|    void timeout(unsigned int seconds) {
   96|   174k|        us_socket_timeout(SSL, (us_socket_t *) this, seconds);
   97|   174k|    }
_ZN3uWS11AsyncSocketILb0EE17getBufferedAmountEv:
  193|   109k|    unsigned int getBufferedAmount() {
  194|       |        /* We return the actual amount of bytes in backbuffer, including pendingRemoval */
  195|   109k|        return (unsigned int) getAsyncSocketData()->buffer.totalLength();
  196|   109k|    }
_ZN3uWS11AsyncSocketILb0EE8shutdownEv:
  100|  2.25k|    void shutdown() {
  101|  2.25k|        us_socket_shutdown(SSL, (us_socket_t *) this);
  102|  2.25k|    }
_ZN3uWS11AsyncSocketILb0EE5closeEv:
  117|  34.6k|    us_socket_t *close() {
  118|  34.6k|        return us_socket_close(SSL, (us_socket_t *) this, 0, nullptr);
  119|  34.6k|    }
_ZN3uWS11AsyncSocketILb0EE18getAsyncSocketDataEv:
   90|  2.16M|    AsyncSocketData<SSL> *getAsyncSocketData() {
   91|  2.16M|        return (AsyncSocketData<SSL> *) us_socket_ext(SSL, (us_socket_t *) this);
   92|  2.16M|    }
_ZN3uWS11AsyncSocketILb0EE8isCorkedEv:
  145|   135k|    bool isCorked() {
  146|   135k|        return getLoopData()->corkedSocket == this;
  147|   135k|    }
_ZN3uWS11AsyncSocketILb0EE13getSendBufferEm:
  155|  22.7k|    std::pair<char *, SendBufferAttribute> getSendBuffer(size_t size) {
  156|       |        /* First step is to determine if we already have backpressure or not */
  157|  22.7k|        LoopData *loopData = getLoopData();
  158|  22.7k|        BackPressure &backPressure = getAsyncSocketData()->buffer;
  159|  22.7k|        size_t existingBackpressure = backPressure.length();
  160|  22.7k|        if ((!existingBackpressure) && (isCorked() || canCork()) && (loopData->corkOffset + size < LoopData::CORK_BUFFER_SIZE)) {
  ------------------
  |  Branch (160:13): [True: 5.53k, False: 17.2k]
  |  Branch (160:41): [True: 5.53k, False: 0]
  |  Branch (160:55): [True: 0, False: 0]
  |  Branch (160:69): [True: 5.40k, False: 130]
  ------------------
  161|       |            /* Cork automatically if we can */
  162|  5.40k|            if (isCorked()) {
  ------------------
  |  Branch (162:17): [True: 5.40k, False: 0]
  ------------------
  163|  5.40k|                char *sendBuffer = loopData->corkBuffer + loopData->corkOffset;
  164|  5.40k|                loopData->corkOffset += (unsigned int) size;
  165|  5.40k|                return {sendBuffer, SendBufferAttribute::NEEDS_NOTHING};
  166|  5.40k|            } else {
  167|      0|                cork();
  168|      0|                char *sendBuffer = loopData->corkBuffer + loopData->corkOffset;
  169|      0|                loopData->corkOffset += (unsigned int) size;
  170|      0|                return {sendBuffer, SendBufferAttribute::NEEDS_UNCORK};
  171|      0|            }
  172|  17.3k|        } else {
  173|       |
  174|       |            /* If we are corked and there is already data in the cork buffer,
  175|       |            mark how much is ours and reset it */
  176|  17.3k|            unsigned int ourCorkOffset = 0;
  177|  17.3k|            if (isCorked() && loopData->corkOffset) {
  ------------------
  |  Branch (177:17): [True: 17.3k, False: 0]
  |  Branch (177:31): [True: 74, False: 17.2k]
  ------------------
  178|     74|                ourCorkOffset = loopData->corkOffset;
  179|     74|                loopData->corkOffset = 0;
  180|     74|            }
  181|       |
  182|       |            /* Fallback is to use the backpressure as buffer */
  183|  17.3k|            backPressure.resize(ourCorkOffset + existingBackpressure + size);
  184|       |
  185|       |            /* And copy corkbuffer in front */
  186|  17.3k|            memcpy((char *) backPressure.data() + existingBackpressure, loopData->corkBuffer, ourCorkOffset);
  187|       |
  188|  17.3k|            return {(char *) backPressure.data() + ourCorkOffset + existingBackpressure, SendBufferAttribute::NEEDS_DRAIN};
  189|  17.3k|        }
  190|  22.7k|    }
_ZN3uWS11AsyncSocketILb0EE13corkUncheckedEv:
  121|  40.1k|    void corkUnchecked() {
  122|       |        /* What if another socket is corked? */
  123|  40.1k|        getLoopData()->corkedSocket = this;
  124|  40.1k|    }
_ZN3uWS11AsyncSocketILb0EE15getNativeHandleEv:
   80|  39.0k|    void *getNativeHandle() {
   81|  39.0k|        return us_socket_get_native_handle(SSL, (us_socket_t *) this);
   82|  39.0k|    }
_ZN3uWS11AsyncSocketILb0EE22getRemoteAddressAsTextEv:
  229|  39.0k|    std::string_view getRemoteAddressAsText() {
  230|  39.0k|        return addressAsText(getRemoteAddress());
  231|  39.0k|    }
_ZN3uWS11AsyncSocketILb0EE13addressAsTextENSt3__117basic_string_viewIcNS2_11char_traitsIcEEEE:
  199|  39.0k|    std::string_view addressAsText(std::string_view binary) {
  200|  39.0k|        static thread_local char buf[64];
  201|  39.0k|        int ipLength = 0;
  202|       |
  203|  39.0k|        if (!binary.length()) {
  ------------------
  |  Branch (203:13): [True: 0, False: 39.0k]
  ------------------
  204|      0|            return {};
  205|      0|        }
  206|       |
  207|  39.0k|        unsigned char *b = (unsigned char *) binary.data();
  208|       |
  209|  39.0k|        if (binary.length() == 4) {
  ------------------
  |  Branch (209:13): [True: 20.3k, False: 18.7k]
  ------------------
  210|  20.3k|            ipLength = snprintf(buf, 64, "%u.%u.%u.%u", b[0], b[1], b[2], b[3]);
  211|  20.3k|        } else {
  212|  18.7k|            ipLength = snprintf(buf, 64, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
  213|  18.7k|                b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11],
  214|  18.7k|                b[12], b[13], b[14], b[15]);
  215|  18.7k|        }
  216|       |
  217|  39.0k|        return {buf, (unsigned int) ipLength};
  218|  39.0k|    }
_ZN3uWS11AsyncSocketILb0EE16getRemoteAddressEv:
  221|  39.0k|    std::string_view getRemoteAddress() {
  222|  39.0k|        static thread_local char buf[16];
  223|  39.0k|        int ipLength = 16;
  224|  39.0k|        us_socket_remote_address(SSL, (us_socket_t *) this, buf, &ipLength);
  225|  39.0k|        return std::string_view(buf, (unsigned int) ipLength);
  226|  39.0k|    }

_ZN3uWS15AsyncSocketDataILb0EEC2Ev:
   82|  1.74M|    AsyncSocketData() = default;
_ZN3uWS12BackPressureC2Ev:
   32|  1.74M|    BackPressure() = default;
_ZN3uWS12BackPressure6lengthEv:
   44|  1.68M|    size_t length() {
   45|  1.68M|        return buffer.length() - pendingRemoval;
   46|  1.68M|    }
_ZN3uWS12BackPressure4dataEv:
   57|   139k|    const char *data() {
   58|   139k|        return buffer.data() + pendingRemoval;
   59|   139k|    }
_ZN3uWS12BackPressure5eraseEj:
   36|  99.8k|    void erase(unsigned int length) {
   37|  99.8k|        pendingRemoval += length;
   38|       |        /* Always erase a minimum of 1/32th the current backpressure */
   39|  99.8k|        if (pendingRemoval > (buffer.length() >> 5)) {
  ------------------
  |  Branch (39:13): [True: 39.9k, False: 59.9k]
  ------------------
   40|  39.9k|            buffer.erase(0, pendingRemoval);
   41|  39.9k|            pendingRemoval = 0;
   42|  39.9k|        }
   43|  99.8k|    }
_ZN3uWS12BackPressure6appendEPKcm:
   33|   142k|    void append(const char *data, size_t length) {
   34|   142k|        buffer.append(data, length);
   35|   142k|    }
_ZN3uWS12BackPressure5clearEv:
   47|  5.10k|    void clear() {
   48|  5.10k|        pendingRemoval = 0;
   49|  5.10k|        buffer.clear();
   50|  5.10k|    }
_ZN3uWS12BackPressure11totalLengthEv:
   64|   109k|    size_t totalLength() {
   65|   109k|        return buffer.length();
   66|   109k|    }
_ZN3uWS12BackPressure6resizeEm:
   54|  17.3k|    void resize(size_t length) {
   55|  17.3k|        buffer.resize(length + pendingRemoval);
   56|  17.3k|    }
_ZN3uWS12BackPressureC2EOS0_:
   28|  80.3k|    BackPressure(BackPressure &&other) {
   29|  80.3k|        buffer = std::move(other.buffer);
   30|  80.3k|        pendingRemoval = other.pendingRemoval;
   31|  80.3k|    }
_ZN3uWS15AsyncSocketDataILb0EEC2EONS_12BackPressureE:
   77|  40.1k|    AsyncSocketData(BackPressure &&backpressure) : buffer(std::move(backpressure)) {
   78|       |
   79|  40.1k|    }

_ZN3uWS11BloomFilter5resetEv:
   75|  61.7k|    void reset() {
   76|  61.7k|        filter.reset();
   77|  61.7k|    }
_ZN3uWS11BloomFilter3addENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
   64|   143k|    void add(std::string_view key) {
   65|   143k|        if (key.length() >= 2) {
  ------------------
  |  Branch (65:13): [True: 139k, False: 3.91k]
  ------------------
   66|   139k|            ScrambleArea s = getFeatures(key);
   67|   139k|            s.val = perfectHash(s.val);
   68|   139k|            filter[s.p[0]] = 1;
   69|   139k|            filter[s.p[1]] = 1;
   70|   139k|            filter[s.p[2]] = 1;
   71|   139k|            filter[s.p[3]] = 1;
   72|   139k|        }
   73|   143k|    }
_ZN3uWS11BloomFilter11getFeaturesENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
   41|   637k|    ScrambleArea getFeatures(std::string_view key) {
   42|   637k|        ScrambleArea s;
   43|   637k|        s.p[0] = reinterpret_cast<const unsigned char&>(key[0]);
   44|   637k|        s.p[1] = reinterpret_cast<const unsigned char&>(key[key.length() - 1]);
   45|   637k|        s.p[2] = reinterpret_cast<const unsigned char&>(key[key.length() - 2]);
   46|   637k|        s.p[3] = reinterpret_cast<const unsigned char&>(key[key.length() >> 1]);
   47|   637k|        return s;
   48|   637k|    }
_ZN3uWS11BloomFilter11perfectHashEj:
   32|   637k|    static inline uint32_t perfectHash(uint32_t features) {
   33|   637k|        return features *= 1843993368;
   34|   637k|    }
_ZN3uWS11BloomFilter9mightHaveENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
   51|   497k|    bool mightHave(std::string_view key) {
   52|   497k|        if (key.length() < 2) {
  ------------------
  |  Branch (52:13): [True: 0, False: 497k]
  ------------------
   53|      0|            return true;
   54|      0|        }
   55|       |    
   56|   497k|        ScrambleArea s = getFeatures(key);
   57|   497k|        s.val = perfectHash(s.val);
   58|   497k|        return filter[s.p[0]] &&
  ------------------
  |  Branch (58:16): [True: 215k, False: 282k]
  ------------------
   59|   497k|        filter[s.p[1]] &&
  ------------------
  |  Branch (59:9): [True: 134k, False: 80.2k]
  ------------------
   60|   497k|        filter[s.p[2]] &&
  ------------------
  |  Branch (60:9): [True: 133k, False: 1.81k]
  ------------------
   61|   497k|        filter[s.p[3]];
  ------------------
  |  Branch (61:9): [True: 131k, False: 1.73k]
  ------------------
   62|   497k|    }

_ZN3uWS24isParsingChunkedEncodingEm:
   95|  35.1k|    inline bool isParsingChunkedEncoding(uint64_t state) {
   96|  35.1k|        return state & ~STATE_SIZE_MASK;
   97|  35.1k|    }
_ZN3uWS13ChunkIteratorC2EPNSt3__117basic_string_viewIcNS1_11char_traitsIcEEEEPmb:
  201|  35.2k|        ChunkIterator(std::string_view *data, uint64_t *state, bool trailer = false) : data(data), state(state), trailer(trailer) {
  202|  35.2k|            chunk = uWS::getNextChunk(*data, *state, trailer);
  203|  35.2k|        }
EpollHelloWorld.cpp:_ZN3uWSL12getNextChunkERNSt3__117basic_string_viewIcNS0_11char_traitsIcEEEERmb:
  104|  68.8k|    static std::optional<std::string_view> getNextChunk(std::string_view &data, uint64_t &state, bool trailer = false) {
  105|       |
  106|  74.1k|        while (data.length()) {
  ------------------
  |  Branch (106:16): [True: 40.5k, False: 33.5k]
  ------------------
  107|       |
  108|       |            // if in "drop trailer mode", just drop up to what we have as size
  109|  40.5k|            if (((state & STATE_IS_CHUNKED) == 0) && hasChunkSize(state) && chunkSize(state)) {
  ------------------
  |  Branch (109:17): [True: 726, False: 39.8k]
  |  Branch (109:54): [True: 726, False: 0]
  |  Branch (109:77): [True: 726, False: 0]
  ------------------
  110|       |
  111|       |                //printf("Parsing trailer now\n");
  112|       |
  113|  1.44k|                while(data.length() && chunkSize(state)) {
  ------------------
  |  Branch (113:23): [True: 1.18k, False: 261]
  |  Branch (113:40): [True: 1.18k, False: 0]
  ------------------
  114|  1.18k|                    data.remove_prefix(1);
  115|  1.18k|                    decChunkSize(state, 1);
  116|       |
  117|  1.18k|                    if (chunkSize(state) == 0) {
  ------------------
  |  Branch (117:25): [True: 465, False: 720]
  ------------------
  118|       |
  119|       |                        /* This is an actual place where we need 0 as state */
  120|    465|                        state = 0;
  121|       |
  122|       |                        /* The parser MUST stop consuming here */
  123|    465|                        return std::nullopt;
  124|    465|                    }
  125|  1.18k|                }
  126|    261|                continue;
  127|    726|            }
  128|       |
  129|  39.8k|            if (!hasChunkSize(state)) {
  ------------------
  |  Branch (129:17): [True: 6.16k, False: 33.6k]
  ------------------
  130|  6.16k|                consumeHexNumber(data, state);
  131|  6.16k|                if (isParsingInvalidChunkedEncoding(state)) {
  ------------------
  |  Branch (131:21): [True: 1.07k, False: 5.09k]
  ------------------
  132|  1.07k|                    return std::nullopt;
  133|  1.07k|                }
  134|  5.09k|                if (hasChunkSize(state) && chunkSize(state) == 2) {
  ------------------
  |  Branch (134:21): [True: 3.35k, False: 1.73k]
  |  Branch (134:44): [True: 761, False: 2.59k]
  ------------------
  135|       |
  136|       |                    //printf("Setting state to trailer-parsing and emitting empty chunk\n");
  137|       |
  138|       |                    // set trailer state and increase size to 4
  139|    761|                    if (trailer) {
  ------------------
  |  Branch (139:25): [True: 0, False: 761]
  ------------------
  140|      0|                        state = 4 /*| STATE_IS_CHUNKED*/ | STATE_HAS_SIZE;
  141|    761|                    } else {
  142|    761|                        state = 2 /*| STATE_IS_CHUNKED*/ | STATE_HAS_SIZE;
  143|    761|                    }
  144|       |
  145|    761|                    return std::string_view(nullptr, 0);
  146|    761|                }
  147|  4.32k|                continue;
  148|  5.09k|            }
  149|       |
  150|       |            // do we have data to emit all?
  151|  33.6k|            if (data.length() >= chunkSize(state)) {
  ------------------
  |  Branch (151:17): [True: 2.10k, False: 31.5k]
  ------------------
  152|       |                // emit all but 2 bytes then reset state to 0 and goto beginning
  153|       |                // not fin
  154|  2.10k|                std::string_view emitSoon;
  155|  2.10k|                bool shouldEmit = false;
  156|  2.10k|                if (chunkSize(state) > 2) {
  ------------------
  |  Branch (156:21): [True: 1.42k, False: 674]
  ------------------
  157|  1.42k|                    emitSoon = std::string_view(data.data(), chunkSize(state) - 2);
  158|  1.42k|                    shouldEmit = true;
  159|  1.42k|                }
  160|  2.10k|                data.remove_prefix(chunkSize(state));
  161|  2.10k|                state = STATE_IS_CHUNKED;
  162|  2.10k|                if (shouldEmit) {
  ------------------
  |  Branch (162:21): [True: 1.42k, False: 674]
  ------------------
  163|  1.42k|                    return emitSoon;
  164|  1.42k|                }
  165|    674|                continue;
  166|  31.5k|            } else {
  167|       |                /* We will consume all our input data */
  168|  31.5k|                std::string_view emitSoon;
  169|  31.5k|                if (chunkSize(state) > 2) {
  ------------------
  |  Branch (169:21): [True: 31.4k, False: 194]
  ------------------
  170|  31.4k|                    uint64_t maximalAppEmit = chunkSize(state) - 2;
  171|  31.4k|                    if (data.length() > maximalAppEmit) {
  ------------------
  |  Branch (171:25): [True: 356, False: 31.0k]
  ------------------
  172|    356|                        emitSoon = data.substr(0, maximalAppEmit);
  173|  31.0k|                    } else {
  174|       |                        //cb(data);
  175|  31.0k|                        emitSoon = data;
  176|  31.0k|                    }
  177|  31.4k|                }
  178|  31.5k|                decChunkSize(state, (unsigned int) data.length());
  179|  31.5k|                state |= STATE_IS_CHUNKED;
  180|       |                // new: decrease data by its size (bug)
  181|  31.5k|                data.remove_prefix(data.length()); // ny bug fix för getNextChunk
  182|  31.5k|                if (emitSoon.length()) {
  ------------------
  |  Branch (182:21): [True: 31.4k, False: 194]
  ------------------
  183|  31.4k|                    return emitSoon;
  184|  31.4k|                } else {
  185|    194|                    return std::nullopt;
  186|    194|                }
  187|  31.5k|            }
  188|  33.6k|        }
  189|       |
  190|  33.5k|        return std::nullopt;
  191|  68.8k|    }
_ZN3uWS12hasChunkSizeEm:
   90|  45.6k|    inline bool hasChunkSize(uint64_t state) {
   91|  45.6k|        return state & STATE_HAS_SIZE;
   92|  45.6k|    }
_ZN3uWS9chunkSizeEm:
   38|   152k|    inline uint64_t chunkSize(uint64_t state) {
   39|   152k|        return state & STATE_SIZE_MASK;
   40|   152k|    }
_ZN3uWS12decChunkSizeERmj:
   81|  32.7k|    inline void decChunkSize(uint64_t &state, unsigned int by) {
   82|       |
   83|       |        //unsigned int bits = state & STATE_IS_CHUNKED;
   84|       |
   85|  32.7k|        state = (state & ~STATE_SIZE_MASK) | (chunkSize(state) - by);
   86|       |
   87|       |        //state |= bits;
   88|  32.7k|    }
_ZN3uWS16consumeHexNumberERNSt3__117basic_string_viewIcNS0_11char_traitsIcEEEERm:
   43|  6.16k|    inline void consumeHexNumber(std::string_view &data, uint64_t &state) {
   44|       |        /* Consume everything higher than 32 */
   45|  17.3k|        while (data.length() && data.data()[0] > 32) {
  ------------------
  |  Branch (45:16): [True: 16.2k, False: 1.12k]
  |  Branch (45:33): [True: 12.2k, False: 3.97k]
  ------------------
   46|       |
   47|  12.2k|            unsigned char digit = (unsigned char)data.data()[0];
   48|  12.2k|            if (digit >= 'a') {
  ------------------
  |  Branch (48:17): [True: 4.90k, False: 7.33k]
  ------------------
   49|  4.90k|                digit = (unsigned char) (digit - ('a' - ':'));
   50|  7.33k|            } else if (digit >= 'A') {
  ------------------
  |  Branch (50:24): [True: 3.20k, False: 4.13k]
  ------------------
   51|  3.20k|                digit = (unsigned char) (digit - ('A' - ':'));
   52|  3.20k|            }
   53|       |
   54|  12.2k|            unsigned int number = ((unsigned int) digit - (unsigned int) '0');
   55|       |
   56|  12.2k|            if (number > 16 || (chunkSize(state) & STATE_SIZE_OVERFLOW)) {
  ------------------
  |  Branch (56:17): [True: 857, False: 11.3k]
  |  Branch (56:32): [True: 219, False: 11.1k]
  ------------------
   57|  1.07k|                state = STATE_IS_ERROR;
   58|  1.07k|                return;
   59|  1.07k|            }
   60|       |
   61|       |            // extract state bits
   62|  11.1k|            uint64_t bits = /*state &*/ STATE_IS_CHUNKED;
   63|       |
   64|  11.1k|            state = (state & STATE_SIZE_MASK) * 16ull + number;
   65|       |
   66|  11.1k|            state |= bits;
   67|  11.1k|            data.remove_prefix(1);
   68|  11.1k|        }
   69|       |        /* Consume everything not /n */
   70|  11.6k|        while (data.length() && data.data()[0] != '\n') {
  ------------------
  |  Branch (70:16): [True: 9.95k, False: 1.73k]
  |  Branch (70:33): [True: 6.59k, False: 3.35k]
  ------------------
   71|  6.59k|            data.remove_prefix(1);
   72|  6.59k|        }
   73|       |        /* Now we stand on \n so consume it and enable size */
   74|  5.09k|        if (data.length()) {
  ------------------
  |  Branch (74:13): [True: 3.35k, False: 1.73k]
  ------------------
   75|  3.35k|            state += 2; // include the two last /r/n
   76|  3.35k|            state |= STATE_HAS_SIZE | STATE_IS_CHUNKED;
   77|  3.35k|            data.remove_prefix(1);
   78|  3.35k|        }
   79|  5.09k|    }
_ZN3uWS13ChunkIterator5beginEv:
  209|  35.2k|        ChunkIterator begin() {
  210|  35.2k|            return *this;
  211|  35.2k|        }
_ZN3uWS13ChunkIterator3endEv:
  213|  35.2k|        ChunkIterator end() {
  214|  35.2k|            return ChunkIterator();
  215|  35.2k|        }
_ZN3uWS13ChunkIteratorC2Ev:
  205|  35.2k|        ChunkIterator() {
  206|       |
  207|  35.2k|        }
_ZNK3uWS13ChunkIteratorneERKS0_:
  224|  68.8k|        bool operator!=(const ChunkIterator &other) const {
  225|  68.8k|            return other.chunk.has_value() != chunk.has_value();
  226|  68.8k|        }
_ZN3uWS13ChunkIteratordeEv:
  217|  33.5k|        std::string_view operator*() {
  218|  33.5k|            if (!chunk.has_value()) {
  ------------------
  |  Branch (218:17): [True: 0, False: 33.5k]
  ------------------
  219|      0|                std::abort();
  220|      0|            }
  221|  33.5k|            return chunk.value();
  222|  33.5k|        }
_ZN3uWS13ChunkIteratorppEv:
  228|  33.5k|        ChunkIterator &operator++() {
  229|  33.5k|            chunk = uWS::getNextChunk(*data, *state, trailer);
  230|  33.5k|            return *this;
  231|  33.5k|        }
_ZN3uWS31isParsingInvalidChunkedEncodingEm:
   99|  41.4k|    inline bool isParsingInvalidChunkedEncoding(uint64_t state) {
  100|  41.4k|        return state == STATE_IS_ERROR;
  101|  41.4k|    }

_ZN3uWS11HttpContextILb0EE6createEPNS_4LoopE27us_socket_context_options_t:
  394|  6.41k|    static HttpContext *create(Loop *loop, us_socket_context_options_t options = {}) {
  395|  6.41k|        HttpContext *httpContext;
  396|       |
  397|  6.41k|        httpContext = (HttpContext *) us_create_socket_context(SSL, (us_loop_t *) loop, sizeof(HttpContextData<SSL>), options);
  398|       |
  399|  6.41k|        if (!httpContext) {
  ------------------
  |  Branch (399:13): [True: 0, False: 6.41k]
  ------------------
  400|      0|            return nullptr;
  401|      0|        }
  402|       |
  403|       |        /* Init socket context data */
  404|  6.41k|        new ((HttpContextData<SSL> *) us_socket_context_ext(SSL, (us_socket_context_t *) httpContext)) HttpContextData<SSL>();
  405|  6.41k|        return httpContext->init();
  406|  6.41k|    }
_ZN3uWS11HttpContextILb0EE4initEv:
   70|  6.41k|    HttpContext<SSL> *init() {
   71|       |        /* Handle socket connections */
   72|  6.41k|        us_socket_context_on_open(SSL, getSocketContext(), [](us_socket_t *s, int /*is_client*/, char */*ip*/, int /*ip_length*/) {
   73|       |            /* Any connected socket should timeout until it has a request */
   74|  6.41k|            us_socket_timeout(SSL, s, HTTP_IDLE_TIMEOUT_S);
   75|       |
   76|       |            /* Init socket ext */
   77|  6.41k|            new (us_socket_ext(SSL, s)) HttpResponseData<SSL>;
   78|       |
   79|       |            /* Call filter */
   80|  6.41k|            HttpContextData<SSL> *httpContextData = getSocketContextDataS(s);
   81|  6.41k|            for (auto &f : httpContextData->filterHandlers) {
   82|  6.41k|                f((HttpResponse<SSL> *) s, 1);
   83|  6.41k|            }
   84|       |
   85|  6.41k|            return s;
   86|  6.41k|        });
   87|       |
   88|       |        /* Handle socket disconnections */
   89|  6.41k|        us_socket_context_on_close(SSL, getSocketContext(), [](us_socket_t *s, int /*code*/, void */*reason*/) {
   90|       |            /* Get socket ext */
   91|  6.41k|            HttpResponseData<SSL> *httpResponseData = (HttpResponseData<SSL> *) us_socket_ext(SSL, s);
   92|       |
   93|       |            /* Call filter */
   94|  6.41k|            HttpContextData<SSL> *httpContextData = getSocketContextDataS(s);
   95|  6.41k|            for (auto &f : httpContextData->filterHandlers) {
   96|  6.41k|                f((HttpResponse<SSL> *) s, -1);
   97|  6.41k|            }
   98|       |
   99|       |            /* Signal broken HTTP request only if we have a pending request */
  100|  6.41k|            if (httpResponseData->onAborted) {
  101|  6.41k|                httpResponseData->onAborted();
  102|  6.41k|            }
  103|       |
  104|       |            /* Destruct socket ext */
  105|  6.41k|            httpResponseData->~HttpResponseData<SSL>();
  106|       |
  107|  6.41k|            return s;
  108|  6.41k|        });
  109|       |
  110|       |        /* Handle HTTP data streams */
  111|  6.41k|        us_socket_context_on_data(SSL, getSocketContext(), [](us_socket_t *s, char *data, int length) {
  112|       |
  113|       |            // total overhead is about 210k down to 180k
  114|       |            // ~210k req/sec is the original perf with write in data
  115|       |            // ~200k req/sec is with cork and formatting
  116|       |            // ~190k req/sec is with http parsing
  117|       |            // ~180k - 190k req/sec is with varying routing
  118|       |
  119|  6.41k|            HttpContextData<SSL> *httpContextData = getSocketContextDataS(s);
  120|       |
  121|       |            /* Do not accept any data while in shutdown state */
  122|  6.41k|            if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) {
  123|  6.41k|                return s;
  124|  6.41k|            }
  125|       |
  126|  6.41k|            HttpResponseData<SSL> *httpResponseData = (HttpResponseData<SSL> *) us_socket_ext(SSL, s);
  127|       |
  128|       |            /* Cork this socket */
  129|  6.41k|            ((AsyncSocket<SSL> *) s)->cork();
  130|       |
  131|       |            /* Mark that we are inside the parser now */
  132|  6.41k|            httpContextData->isParsingHttp = true;
  133|       |
  134|       |            // clients need to know the cursor after http parse, not servers!
  135|       |            // how far did we read then? we need to know to continue with websocket parsing data? or?
  136|       |
  137|  6.41k|            void *proxyParser = nullptr;
  138|       |#ifdef UWS_WITH_PROXY
  139|       |            proxyParser = &httpResponseData->proxyParser;
  140|       |#endif
  141|       |
  142|       |            /* The return value is entirely up to us to interpret. The HttpParser only care for whether the returned value is DIFFERENT or not from passed user */
  143|  6.41k|            auto [err, returnedSocket] = httpResponseData->consumePostPadded(data, (unsigned int) length, s, proxyParser, [httpContextData](void *s, HttpRequest *httpRequest) -> void * {
  144|       |                /* For every request we reset the timeout and hang until user makes action */
  145|       |                /* Warning: if we are in shutdown state, resetting the timer is a security issue! */
  146|  6.41k|                us_socket_timeout(SSL, (us_socket_t *) s, 0);
  147|       |
  148|       |                /* Reset httpResponse */
  149|  6.41k|                HttpResponseData<SSL> *httpResponseData = (HttpResponseData<SSL> *) us_socket_ext(SSL, (us_socket_t *) s);
  150|  6.41k|                httpResponseData->offset = 0;
  151|       |
  152|       |                /* Are we not ready for another request yet? Terminate the connection. */
  153|  6.41k|                if (httpResponseData->state & HttpResponseData<SSL>::HTTP_RESPONSE_PENDING) {
  154|  6.41k|                    us_socket_close(SSL, (us_socket_t *) s, 0, nullptr);
  155|  6.41k|                    return nullptr;
  156|  6.41k|                }
  157|       |
  158|       |                /* Mark pending request and emit it */
  159|  6.41k|                httpResponseData->state = HttpResponseData<SSL>::HTTP_RESPONSE_PENDING;
  160|       |
  161|       |                /* Mark this response as connectionClose if ancient or connection: close */
  162|  6.41k|                if (httpRequest->isAncient() || httpRequest->getHeader("connection").length() == 5) {
  163|  6.41k|                    httpResponseData->state |= HttpResponseData<SSL>::HTTP_CONNECTION_CLOSE;
  164|  6.41k|                }
  165|       |
  166|       |                /* Select the router based on SNI (only possible for SSL) */
  167|  6.41k|                auto *selectedRouter = &httpContextData->router;
  168|  6.41k|                if constexpr (SSL) {
  169|  6.41k|                    void *domainRouter = us_socket_server_name_userdata(SSL, (struct us_socket_t *) s);
  170|  6.41k|                    if (domainRouter) {
  171|  6.41k|                        selectedRouter = (decltype(selectedRouter)) domainRouter;
  172|  6.41k|                    }
  173|  6.41k|                }
  174|       |
  175|       |                /* Route the method and URL */
  176|  6.41k|                selectedRouter->getUserData() = {(HttpResponse<SSL> *) s, httpRequest};
  177|  6.41k|                if (!selectedRouter->route(httpRequest->getCaseSensitiveMethod(), httpRequest->getUrl())) {
  178|       |                    /* We have to force close this socket as we have no handler for it */
  179|  6.41k|                    us_socket_close(SSL, (us_socket_t *) s, 0, nullptr);
  180|  6.41k|                    return nullptr;
  181|  6.41k|                }
  182|       |
  183|       |                /* First of all we need to check if this socket was deleted due to upgrade */
  184|  6.41k|                if (httpContextData->upgradedWebSocket) {
  185|       |                    /* We differ between closed and upgraded below */
  186|  6.41k|                    return nullptr;
  187|  6.41k|                }
  188|       |
  189|       |                /* Was the socket closed? */
  190|  6.41k|                if (us_socket_is_closed(SSL, (struct us_socket_t *) s)) {
  191|  6.41k|                    return nullptr;
  192|  6.41k|                }
  193|       |
  194|       |                /* We absolutely have to terminate parsing if shutdown */
  195|  6.41k|                if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) {
  196|  6.41k|                    return nullptr;
  197|  6.41k|                }
  198|       |
  199|       |                /* Returning from a request handler without responding or attaching an onAborted handler is ill-use */
  200|  6.41k|                if (!((HttpResponse<SSL> *) s)->hasResponded() && !httpResponseData->onAborted) {
  201|       |                    /* Throw exception here? */
  202|  6.41k|                    std::cerr << "Error: Returning from a request handler without responding or attaching an abort handler is forbidden!" << std::endl;
  203|  6.41k|                    std::terminate();
  204|  6.41k|                }
  205|       |
  206|       |                /* If we have not responded and we have a data handler, we need to timeout to enfore client sending the data */
  207|  6.41k|                if (!((HttpResponse<SSL> *) s)->hasResponded() && httpResponseData->inStream) {
  208|  6.41k|                    us_socket_timeout(SSL, (us_socket_t *) s, HTTP_IDLE_TIMEOUT_S);
  209|  6.41k|                }
  210|       |
  211|       |                /* Continue parsing */
  212|  6.41k|                return s;
  213|       |
  214|  6.41k|            }, [httpResponseData](void *user, std::string_view data, bool fin) -> void * {
  215|       |                /* We always get an empty chunk even if there is no data */
  216|  6.41k|                if (httpResponseData->inStream) {
  217|       |
  218|       |                    /* Todo: can this handle timeout for non-post as well? */
  219|  6.41k|                    if (fin) {
  220|       |                        /* If we just got the last chunk (or empty chunk), disable timeout */
  221|  6.41k|                        us_socket_timeout(SSL, (struct us_socket_t *) user, 0);
  222|  6.41k|                    } else {
  223|       |                        /* We still have some more data coming in later, so reset timeout */
  224|       |                        /* Only reset timeout if we got enough bytes (16kb/sec) since last time we reset here */
  225|  6.41k|                        httpResponseData->received_bytes_per_timeout += (unsigned int) data.length();
  226|  6.41k|                        if (httpResponseData->received_bytes_per_timeout >= HTTP_RECEIVE_THROUGHPUT_BYTES * HTTP_IDLE_TIMEOUT_S) {
  227|  6.41k|                            us_socket_timeout(SSL, (struct us_socket_t *) user, HTTP_IDLE_TIMEOUT_S);
  228|  6.41k|                            httpResponseData->received_bytes_per_timeout = 0;
  229|  6.41k|                        }
  230|  6.41k|                    }
  231|       |
  232|       |                    /* We might respond in the handler, so do not change timeout after this */
  233|  6.41k|                    httpResponseData->inStream(data, fin);
  234|       |
  235|       |                    /* Was the socket closed? */
  236|  6.41k|                    if (us_socket_is_closed(SSL, (struct us_socket_t *) user)) {
  237|  6.41k|                        return nullptr;
  238|  6.41k|                    }
  239|       |
  240|       |                    /* We absolutely have to terminate parsing if shutdown */
  241|  6.41k|                    if (us_socket_is_shut_down(SSL, (us_socket_t *) user)) {
  242|  6.41k|                        return nullptr;
  243|  6.41k|                    }
  244|       |
  245|       |                    /* If we were given the last data chunk, reset data handler to ensure following
  246|       |                     * requests on the same socket won't trigger any previously registered behavior */
  247|  6.41k|                    if (fin) {
  248|  6.41k|                        httpResponseData->inStream = nullptr;
  249|  6.41k|                    }
  250|  6.41k|                }
  251|  6.41k|                return user;
  252|  6.41k|            });
  253|       |
  254|       |            /* Mark that we are no longer parsing Http */
  255|  6.41k|            httpContextData->isParsingHttp = false;
  256|       |
  257|       |            /* If we got fullptr that means the parser wants us to close the socket from error (same as calling the errorHandler) */
  258|  6.41k|            if (returnedSocket == FULLPTR) {
  259|       |                /* For errors, we only deliver them "at most once". We don't care if they get halfways delivered or not. */
  260|  6.41k|                us_socket_write(SSL, s, httpErrorResponses[err].data(), (int) httpErrorResponses[err].length(), false);
  261|  6.41k|                us_socket_shutdown(SSL, s);
  262|       |                /* Close any socket on HTTP errors */
  263|  6.41k|                us_socket_close(SSL, s, 0, nullptr);
  264|       |                /* This just makes the following code act as if the socket was closed from error inside the parser. */
  265|  6.41k|                returnedSocket = nullptr;
  266|  6.41k|            }
  267|       |
  268|       |            /* We need to uncork in all cases, except for nullptr (closed socket, or upgraded socket) */
  269|  6.41k|            if (returnedSocket != nullptr) {
  270|       |                /* Timeout on uncork failure */
  271|  6.41k|                auto [written, failed] = ((AsyncSocket<SSL> *) returnedSocket)->uncork();
  272|  6.41k|                if (failed) {
  273|       |                    /* All Http sockets timeout by this, and this behavior match the one in HttpResponse::cork */
  274|       |                    /* Warning: both HTTP_IDLE_TIMEOUT_S and HTTP_TIMEOUT_S are 10 seconds and both are used the same */
  275|  6.41k|                    ((AsyncSocket<SSL> *) s)->timeout(HTTP_IDLE_TIMEOUT_S);
  276|  6.41k|                }
  277|       |
  278|       |                /* We need to check if we should close this socket here now */
  279|  6.41k|                if (httpResponseData->state & HttpResponseData<SSL>::HTTP_CONNECTION_CLOSE) {
  280|  6.41k|                    if ((httpResponseData->state & HttpResponseData<SSL>::HTTP_RESPONSE_PENDING) == 0) {
  281|  6.41k|                        if (((AsyncSocket<SSL> *) s)->getBufferedAmount() == 0) {
  282|  6.41k|                            ((AsyncSocket<SSL> *) s)->shutdown();
  283|       |                            /* We need to force close after sending FIN since we want to hinder
  284|       |                             * clients from keeping to send their huge data */
  285|  6.41k|                            ((AsyncSocket<SSL> *) s)->close();
  286|  6.41k|                        }
  287|  6.41k|                    }
  288|  6.41k|                }
  289|       |
  290|  6.41k|                return (us_socket_t *) returnedSocket;
  291|  6.41k|            }
  292|       |
  293|       |            /* If we upgraded, check here (differ between nullptr close and nullptr upgrade) */
  294|  6.41k|            if (httpContextData->upgradedWebSocket) {
  295|       |                /* This path is only for upgraded websockets */
  296|  6.41k|                AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) httpContextData->upgradedWebSocket;
  297|       |
  298|       |                /* Uncork here as well (note: what if we failed to uncork and we then pub/sub before we even upgraded?) */
  299|  6.41k|                auto [written, failed] = asyncSocket->uncork();
  300|       |
  301|       |                /* If we succeeded in uncorking, check if we have sent WebSocket FIN */
  302|  6.41k|                if (!failed) {
  303|  6.41k|                    WebSocketData *webSocketData = (WebSocketData *) asyncSocket->getAsyncSocketData();
  304|  6.41k|                    if (webSocketData->isShuttingDown) {
  305|       |                        /* In that case, also send TCP FIN (this is similar to what we have in ws drain handler) */
  306|  6.41k|                        asyncSocket->shutdown();
  307|  6.41k|                    }
  308|  6.41k|                }
  309|       |
  310|       |                /* Reset upgradedWebSocket before we return */
  311|  6.41k|                httpContextData->upgradedWebSocket = nullptr;
  312|       |
  313|       |                /* Return the new upgraded websocket */
  314|  6.41k|                return (us_socket_t *) asyncSocket;
  315|  6.41k|            }
  316|       |
  317|       |            /* It is okay to uncork a closed socket and we need to */
  318|  6.41k|            ((AsyncSocket<SSL> *) s)->uncork();
  319|       |
  320|       |            /* We cannot return nullptr to the underlying stack in any case */
  321|  6.41k|            return s;
  322|  6.41k|        });
  323|       |
  324|       |        /* Handle HTTP write out (note: SSL_read may trigger this spuriously, the app need to handle spurious calls) */
  325|  6.41k|        us_socket_context_on_writable(SSL, getSocketContext(), [](us_socket_t *s) {
  326|       |
  327|  6.41k|            AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
  328|  6.41k|            HttpResponseData<SSL> *httpResponseData = (HttpResponseData<SSL> *) asyncSocket->getAsyncSocketData();
  329|       |
  330|       |            /* Ask the developer to write data and return success (true) or failure (false), OR skip sending anything and return success (true). */
  331|  6.41k|            if (httpResponseData->onWritable) {
  332|       |                /* We are now writable, so hang timeout again, the user does not have to do anything so we should hang until end or tryEnd rearms timeout */
  333|  6.41k|                us_socket_timeout(SSL, s, 0);
  334|       |
  335|       |                /* We expect the developer to return whether or not write was successful (true).
  336|       |                 * If write was never called, the developer should still return true so that we may drain. */
  337|  6.41k|                bool success = httpResponseData->callOnWritable(httpResponseData->offset);
  338|       |
  339|       |                /* The developer indicated that their onWritable failed. */
  340|  6.41k|                if (!success) {
  341|       |                    /* Skip testing if we can drain anything since that might perform an extra syscall */
  342|  6.41k|                    return s;
  343|  6.41k|                }
  344|       |
  345|       |                /* We don't want to fall through since we don't want to mess with timeout.
  346|       |                 * It makes little sense to drain any backpressure when the user has registered onWritable. */
  347|  6.41k|                return s;
  348|  6.41k|            }
  349|       |
  350|       |            /* Drain any socket buffer, this might empty our backpressure and thus finish the request */
  351|  6.41k|            /*auto [written, failed] = */asyncSocket->write(nullptr, 0, true, 0);
  352|       |
  353|       |            /* Should we close this connection after a response - and is this response really done? */
  354|  6.41k|            if (httpResponseData->state & HttpResponseData<SSL>::HTTP_CONNECTION_CLOSE) {
  355|  6.41k|                if ((httpResponseData->state & HttpResponseData<SSL>::HTTP_RESPONSE_PENDING) == 0) {
  356|  6.41k|                    if (asyncSocket->getBufferedAmount() == 0) {
  357|  6.41k|                        asyncSocket->shutdown();
  358|       |                        /* We need to force close after sending FIN since we want to hinder
  359|       |                         * clients from keeping to send their huge data */
  360|  6.41k|                        asyncSocket->close();
  361|  6.41k|                    }
  362|  6.41k|                }
  363|  6.41k|            }
  364|       |
  365|       |            /* Expect another writable event, or another request within the timeout */
  366|  6.41k|            asyncSocket->timeout(HTTP_IDLE_TIMEOUT_S);
  367|       |
  368|  6.41k|            return s;
  369|  6.41k|        });
  370|       |
  371|       |        /* Handle FIN, HTTP does not support half-closed sockets, so simply close */
  372|  6.41k|        us_socket_context_on_end(SSL, getSocketContext(), [](us_socket_t *s) {
  373|       |
  374|       |            /* We do not care for half closed sockets */
  375|  6.41k|            AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
  376|  6.41k|            return asyncSocket->close();
  377|       |
  378|  6.41k|        });
  379|       |
  380|       |        /* Handle socket timeouts, simply close them so to not confuse client with FIN */
  381|  6.41k|        us_socket_context_on_timeout(SSL, getSocketContext(), [](us_socket_t *s) {
  382|       |
  383|       |            /* Force close rather than gracefully shutdown and risk confusing the client with a complete download */
  384|  6.41k|            AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
  385|  6.41k|            return asyncSocket->close();
  386|       |
  387|  6.41k|        });
  388|       |
  389|  6.41k|        return this;
  390|  6.41k|    }
_ZN3uWS11HttpContextILb0EE16getSocketContextEv:
   53|   142k|    us_socket_context_t *getSocketContext() {
   54|   142k|        return (us_socket_context_t *) this;
   55|   142k|    }
_ZZN3uWS11HttpContextILb0EE4initEvENKUlP11us_socket_tiPciE_clES3_iS4_i:
   72|  1.74M|        us_socket_context_on_open(SSL, getSocketContext(), [](us_socket_t *s, int /*is_client*/, char */*ip*/, int /*ip_length*/) {
   73|       |            /* Any connected socket should timeout until it has a request */
   74|  1.74M|            us_socket_timeout(SSL, s, HTTP_IDLE_TIMEOUT_S);
   75|       |
   76|       |            /* Init socket ext */
   77|  1.74M|            new (us_socket_ext(SSL, s)) HttpResponseData<SSL>;
   78|       |
   79|       |            /* Call filter */
   80|  1.74M|            HttpContextData<SSL> *httpContextData = getSocketContextDataS(s);
   81|  1.74M|            for (auto &f : httpContextData->filterHandlers) {
  ------------------
  |  Branch (81:26): [True: 0, False: 1.74M]
  ------------------
   82|      0|                f((HttpResponse<SSL> *) s, 1);
   83|      0|            }
   84|       |
   85|  1.74M|            return s;
   86|  1.74M|        });
_ZN3uWS11HttpContextILb0EE21getSocketContextDataSEP11us_socket_t:
   65|  3.82M|    static HttpContextData<SSL> *getSocketContextDataS(us_socket_t *s) {
   66|  3.82M|        return (HttpContextData<SSL> *) us_socket_context_ext(SSL, getSocketContext(s));
   67|  3.82M|    }
_ZN3uWS11HttpContextILb0EE16getSocketContextEP11us_socket_t:
   57|  3.82M|    static us_socket_context_t *getSocketContext(us_socket_t *s) {
   58|  3.82M|        return (us_socket_context_t *) us_socket_context(SSL, s);
   59|  3.82M|    }
_ZZN3uWS11HttpContextILb0EE4initEvENKUlP11us_socket_tiPvE_clES3_iS4_:
   89|  1.70M|        us_socket_context_on_close(SSL, getSocketContext(), [](us_socket_t *s, int /*code*/, void */*reason*/) {
   90|       |            /* Get socket ext */
   91|  1.70M|            HttpResponseData<SSL> *httpResponseData = (HttpResponseData<SSL> *) us_socket_ext(SSL, s);
   92|       |
   93|       |            /* Call filter */
   94|  1.70M|            HttpContextData<SSL> *httpContextData = getSocketContextDataS(s);
   95|  1.70M|            for (auto &f : httpContextData->filterHandlers) {
  ------------------
  |  Branch (95:26): [True: 0, False: 1.70M]
  ------------------
   96|      0|                f((HttpResponse<SSL> *) s, -1);
   97|      0|            }
   98|       |
   99|       |            /* Signal broken HTTP request only if we have a pending request */
  100|  1.70M|            if (httpResponseData->onAborted) {
  ------------------
  |  Branch (100:17): [True: 1.16k, False: 1.69M]
  ------------------
  101|  1.16k|                httpResponseData->onAborted();
  102|  1.16k|            }
  103|       |
  104|       |            /* Destruct socket ext */
  105|  1.70M|            httpResponseData->~HttpResponseData<SSL>();
  106|       |
  107|  1.70M|            return s;
  108|  1.70M|        });
_ZZN3uWS11HttpContextILb0EE4initEvENKUlP11us_socket_tPciE_clES3_S4_i:
  111|   382k|        us_socket_context_on_data(SSL, getSocketContext(), [](us_socket_t *s, char *data, int length) {
  112|       |
  113|       |            // total overhead is about 210k down to 180k
  114|       |            // ~210k req/sec is the original perf with write in data
  115|       |            // ~200k req/sec is with cork and formatting
  116|       |            // ~190k req/sec is with http parsing
  117|       |            // ~180k - 190k req/sec is with varying routing
  118|       |
  119|   382k|            HttpContextData<SSL> *httpContextData = getSocketContextDataS(s);
  120|       |
  121|       |            /* Do not accept any data while in shutdown state */
  122|   382k|            if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) {
  ------------------
  |  Branch (122:17): [True: 0, False: 382k]
  ------------------
  123|      0|                return s;
  124|      0|            }
  125|       |
  126|   382k|            HttpResponseData<SSL> *httpResponseData = (HttpResponseData<SSL> *) us_socket_ext(SSL, s);
  127|       |
  128|       |            /* Cork this socket */
  129|   382k|            ((AsyncSocket<SSL> *) s)->cork();
  130|       |
  131|       |            /* Mark that we are inside the parser now */
  132|   382k|            httpContextData->isParsingHttp = true;
  133|       |
  134|       |            // clients need to know the cursor after http parse, not servers!
  135|       |            // how far did we read then? we need to know to continue with websocket parsing data? or?
  136|       |
  137|   382k|            void *proxyParser = nullptr;
  138|       |#ifdef UWS_WITH_PROXY
  139|       |            proxyParser = &httpResponseData->proxyParser;
  140|       |#endif
  141|       |
  142|       |            /* The return value is entirely up to us to interpret. The HttpParser only care for whether the returned value is DIFFERENT or not from passed user */
  143|   382k|            auto [err, returnedSocket] = httpResponseData->consumePostPadded(data, (unsigned int) length, s, proxyParser, [httpContextData](void *s, HttpRequest *httpRequest) -> void * {
  144|       |                /* For every request we reset the timeout and hang until user makes action */
  145|       |                /* Warning: if we are in shutdown state, resetting the timer is a security issue! */
  146|   382k|                us_socket_timeout(SSL, (us_socket_t *) s, 0);
  147|       |
  148|       |                /* Reset httpResponse */
  149|   382k|                HttpResponseData<SSL> *httpResponseData = (HttpResponseData<SSL> *) us_socket_ext(SSL, (us_socket_t *) s);
  150|   382k|                httpResponseData->offset = 0;
  151|       |
  152|       |                /* Are we not ready for another request yet? Terminate the connection. */
  153|   382k|                if (httpResponseData->state & HttpResponseData<SSL>::HTTP_RESPONSE_PENDING) {
  154|   382k|                    us_socket_close(SSL, (us_socket_t *) s, 0, nullptr);
  155|   382k|                    return nullptr;
  156|   382k|                }
  157|       |
  158|       |                /* Mark pending request and emit it */
  159|   382k|                httpResponseData->state = HttpResponseData<SSL>::HTTP_RESPONSE_PENDING;
  160|       |
  161|       |                /* Mark this response as connectionClose if ancient or connection: close */
  162|   382k|                if (httpRequest->isAncient() || httpRequest->getHeader("connection").length() == 5) {
  163|   382k|                    httpResponseData->state |= HttpResponseData<SSL>::HTTP_CONNECTION_CLOSE;
  164|   382k|                }
  165|       |
  166|       |                /* Select the router based on SNI (only possible for SSL) */
  167|   382k|                auto *selectedRouter = &httpContextData->router;
  168|   382k|                if constexpr (SSL) {
  169|   382k|                    void *domainRouter = us_socket_server_name_userdata(SSL, (struct us_socket_t *) s);
  170|   382k|                    if (domainRouter) {
  171|   382k|                        selectedRouter = (decltype(selectedRouter)) domainRouter;
  172|   382k|                    }
  173|   382k|                }
  174|       |
  175|       |                /* Route the method and URL */
  176|   382k|                selectedRouter->getUserData() = {(HttpResponse<SSL> *) s, httpRequest};
  177|   382k|                if (!selectedRouter->route(httpRequest->getCaseSensitiveMethod(), httpRequest->getUrl())) {
  178|       |                    /* We have to force close this socket as we have no handler for it */
  179|   382k|                    us_socket_close(SSL, (us_socket_t *) s, 0, nullptr);
  180|   382k|                    return nullptr;
  181|   382k|                }
  182|       |
  183|       |                /* First of all we need to check if this socket was deleted due to upgrade */
  184|   382k|                if (httpContextData->upgradedWebSocket) {
  185|       |                    /* We differ between closed and upgraded below */
  186|   382k|                    return nullptr;
  187|   382k|                }
  188|       |
  189|       |                /* Was the socket closed? */
  190|   382k|                if (us_socket_is_closed(SSL, (struct us_socket_t *) s)) {
  191|   382k|                    return nullptr;
  192|   382k|                }
  193|       |
  194|       |                /* We absolutely have to terminate parsing if shutdown */
  195|   382k|                if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) {
  196|   382k|                    return nullptr;
  197|   382k|                }
  198|       |
  199|       |                /* Returning from a request handler without responding or attaching an onAborted handler is ill-use */
  200|   382k|                if (!((HttpResponse<SSL> *) s)->hasResponded() && !httpResponseData->onAborted) {
  201|       |                    /* Throw exception here? */
  202|   382k|                    std::cerr << "Error: Returning from a request handler without responding or attaching an abort handler is forbidden!" << std::endl;
  203|   382k|                    std::terminate();
  204|   382k|                }
  205|       |
  206|       |                /* If we have not responded and we have a data handler, we need to timeout to enfore client sending the data */
  207|   382k|                if (!((HttpResponse<SSL> *) s)->hasResponded() && httpResponseData->inStream) {
  208|   382k|                    us_socket_timeout(SSL, (us_socket_t *) s, HTTP_IDLE_TIMEOUT_S);
  209|   382k|                }
  210|       |
  211|       |                /* Continue parsing */
  212|   382k|                return s;
  213|       |
  214|   382k|            }, [httpResponseData](void *user, std::string_view data, bool fin) -> void * {
  215|       |                /* We always get an empty chunk even if there is no data */
  216|   382k|                if (httpResponseData->inStream) {
  217|       |
  218|       |                    /* Todo: can this handle timeout for non-post as well? */
  219|   382k|                    if (fin) {
  220|       |                        /* If we just got the last chunk (or empty chunk), disable timeout */
  221|   382k|                        us_socket_timeout(SSL, (struct us_socket_t *) user, 0);
  222|   382k|                    } else {
  223|       |                        /* We still have some more data coming in later, so reset timeout */
  224|       |                        /* Only reset timeout if we got enough bytes (16kb/sec) since last time we reset here */
  225|   382k|                        httpResponseData->received_bytes_per_timeout += (unsigned int) data.length();
  226|   382k|                        if (httpResponseData->received_bytes_per_timeout >= HTTP_RECEIVE_THROUGHPUT_BYTES * HTTP_IDLE_TIMEOUT_S) {
  227|   382k|                            us_socket_timeout(SSL, (struct us_socket_t *) user, HTTP_IDLE_TIMEOUT_S);
  228|   382k|                            httpResponseData->received_bytes_per_timeout = 0;
  229|   382k|                        }
  230|   382k|                    }
  231|       |
  232|       |                    /* We might respond in the handler, so do not change timeout after this */
  233|   382k|                    httpResponseData->inStream(data, fin);
  234|       |
  235|       |                    /* Was the socket closed? */
  236|   382k|                    if (us_socket_is_closed(SSL, (struct us_socket_t *) user)) {
  237|   382k|                        return nullptr;
  238|   382k|                    }
  239|       |
  240|       |                    /* We absolutely have to terminate parsing if shutdown */
  241|   382k|                    if (us_socket_is_shut_down(SSL, (us_socket_t *) user)) {
  242|   382k|                        return nullptr;
  243|   382k|                    }
  244|       |
  245|       |                    /* If we were given the last data chunk, reset data handler to ensure following
  246|       |                     * requests on the same socket won't trigger any previously registered behavior */
  247|   382k|                    if (fin) {
  248|   382k|                        httpResponseData->inStream = nullptr;
  249|   382k|                    }
  250|   382k|                }
  251|   382k|                return user;
  252|   382k|            });
  253|       |
  254|       |            /* Mark that we are no longer parsing Http */
  255|   382k|            httpContextData->isParsingHttp = false;
  256|       |
  257|       |            /* If we got fullptr that means the parser wants us to close the socket from error (same as calling the errorHandler) */
  258|   382k|            if (returnedSocket == FULLPTR) {
  ------------------
  |  Branch (258:17): [True: 284k, False: 97.8k]
  ------------------
  259|       |                /* For errors, we only deliver them "at most once". We don't care if they get halfways delivered or not. */
  260|   284k|                us_socket_write(SSL, s, httpErrorResponses[err].data(), (int) httpErrorResponses[err].length(), false);
  261|   284k|                us_socket_shutdown(SSL, s);
  262|       |                /* Close any socket on HTTP errors */
  263|   284k|                us_socket_close(SSL, s, 0, nullptr);
  264|       |                /* This just makes the following code act as if the socket was closed from error inside the parser. */
  265|   284k|                returnedSocket = nullptr;
  266|   284k|            }
  267|       |
  268|       |            /* We need to uncork in all cases, except for nullptr (closed socket, or upgraded socket) */
  269|   382k|            if (returnedSocket != nullptr) {
  ------------------
  |  Branch (269:17): [True: 56.4k, False: 325k]
  ------------------
  270|       |                /* Timeout on uncork failure */
  271|  56.4k|                auto [written, failed] = ((AsyncSocket<SSL> *) returnedSocket)->uncork();
  272|  56.4k|                if (failed) {
  ------------------
  |  Branch (272:21): [True: 42.3k, False: 14.1k]
  ------------------
  273|       |                    /* All Http sockets timeout by this, and this behavior match the one in HttpResponse::cork */
  274|       |                    /* Warning: both HTTP_IDLE_TIMEOUT_S and HTTP_TIMEOUT_S are 10 seconds and both are used the same */
  275|  42.3k|                    ((AsyncSocket<SSL> *) s)->timeout(HTTP_IDLE_TIMEOUT_S);
  276|  42.3k|                }
  277|       |
  278|       |                /* We need to check if we should close this socket here now */
  279|  56.4k|                if (httpResponseData->state & HttpResponseData<SSL>::HTTP_CONNECTION_CLOSE) {
  ------------------
  |  Branch (279:21): [True: 1.04k, False: 55.4k]
  ------------------
  280|  1.04k|                    if ((httpResponseData->state & HttpResponseData<SSL>::HTTP_RESPONSE_PENDING) == 0) {
  ------------------
  |  Branch (280:25): [True: 845, False: 202]
  ------------------
  281|    845|                        if (((AsyncSocket<SSL> *) s)->getBufferedAmount() == 0) {
  ------------------
  |  Branch (281:29): [True: 197, False: 648]
  ------------------
  282|    197|                            ((AsyncSocket<SSL> *) s)->shutdown();
  283|       |                            /* We need to force close after sending FIN since we want to hinder
  284|       |                             * clients from keeping to send their huge data */
  285|    197|                            ((AsyncSocket<SSL> *) s)->close();
  286|    197|                        }
  287|    845|                    }
  288|  1.04k|                }
  289|       |
  290|  56.4k|                return (us_socket_t *) returnedSocket;
  291|  56.4k|            }
  292|       |
  293|       |            /* If we upgraded, check here (differ between nullptr close and nullptr upgrade) */
  294|   325k|            if (httpContextData->upgradedWebSocket) {
  ------------------
  |  Branch (294:17): [True: 40.1k, False: 285k]
  ------------------
  295|       |                /* This path is only for upgraded websockets */
  296|  40.1k|                AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) httpContextData->upgradedWebSocket;
  297|       |
  298|       |                /* Uncork here as well (note: what if we failed to uncork and we then pub/sub before we even upgraded?) */
  299|  40.1k|                auto [written, failed] = asyncSocket->uncork();
  300|       |
  301|       |                /* If we succeeded in uncorking, check if we have sent WebSocket FIN */
  302|  40.1k|                if (!failed) {
  ------------------
  |  Branch (302:21): [True: 1.98k, False: 38.1k]
  ------------------
  303|  1.98k|                    WebSocketData *webSocketData = (WebSocketData *) asyncSocket->getAsyncSocketData();
  304|  1.98k|                    if (webSocketData->isShuttingDown) {
  ------------------
  |  Branch (304:25): [True: 0, False: 1.98k]
  ------------------
  305|       |                        /* In that case, also send TCP FIN (this is similar to what we have in ws drain handler) */
  306|      0|                        asyncSocket->shutdown();
  307|      0|                    }
  308|  1.98k|                }
  309|       |
  310|       |                /* Reset upgradedWebSocket before we return */
  311|  40.1k|                httpContextData->upgradedWebSocket = nullptr;
  312|       |
  313|       |                /* Return the new upgraded websocket */
  314|  40.1k|                return (us_socket_t *) asyncSocket;
  315|  40.1k|            }
  316|       |
  317|       |            /* It is okay to uncork a closed socket and we need to */
  318|   285k|            ((AsyncSocket<SSL> *) s)->uncork();
  319|       |
  320|       |            /* We cannot return nullptr to the underlying stack in any case */
  321|   285k|            return s;
  322|   325k|        });
_ZZZN3uWS11HttpContextILb0EE4initEvENKUlP11us_socket_tPciE_clES3_S4_iENKUlPvPNS_11HttpRequestEE_clES6_S8_:
  143|  60.4k|            auto [err, returnedSocket] = httpResponseData->consumePostPadded(data, (unsigned int) length, s, proxyParser, [httpContextData](void *s, HttpRequest *httpRequest) -> void * {
  144|       |                /* For every request we reset the timeout and hang until user makes action */
  145|       |                /* Warning: if we are in shutdown state, resetting the timer is a security issue! */
  146|  60.4k|                us_socket_timeout(SSL, (us_socket_t *) s, 0);
  147|       |
  148|       |                /* Reset httpResponse */
  149|  60.4k|                HttpResponseData<SSL> *httpResponseData = (HttpResponseData<SSL> *) us_socket_ext(SSL, (us_socket_t *) s);
  150|  60.4k|                httpResponseData->offset = 0;
  151|       |
  152|       |                /* Are we not ready for another request yet? Terminate the connection. */
  153|  60.4k|                if (httpResponseData->state & HttpResponseData<SSL>::HTTP_RESPONSE_PENDING) {
  ------------------
  |  Branch (153:21): [True: 194, False: 60.2k]
  ------------------
  154|    194|                    us_socket_close(SSL, (us_socket_t *) s, 0, nullptr);
  155|    194|                    return nullptr;
  156|    194|                }
  157|       |
  158|       |                /* Mark pending request and emit it */
  159|  60.2k|                httpResponseData->state = HttpResponseData<SSL>::HTTP_RESPONSE_PENDING;
  160|       |
  161|       |                /* Mark this response as connectionClose if ancient or connection: close */
  162|  60.2k|                if (httpRequest->isAncient() || httpRequest->getHeader("connection").length() == 5) {
  ------------------
  |  Branch (162:21): [True: 0, False: 60.2k]
  |  Branch (162:21): [True: 625, False: 59.6k]
  |  Branch (162:49): [True: 625, False: 59.6k]
  ------------------
  163|    625|                    httpResponseData->state |= HttpResponseData<SSL>::HTTP_CONNECTION_CLOSE;
  164|    625|                }
  165|       |
  166|       |                /* Select the router based on SNI (only possible for SSL) */
  167|  60.2k|                auto *selectedRouter = &httpContextData->router;
  168|  60.2k|                if constexpr (SSL) {
  ------------------
  |  Branch (168:31): [Folded - Ignored]
  ------------------
  169|  60.2k|                    void *domainRouter = us_socket_server_name_userdata(SSL, (struct us_socket_t *) s);
  170|  60.2k|                    if (domainRouter) {
  171|  60.2k|                        selectedRouter = (decltype(selectedRouter)) domainRouter;
  172|  60.2k|                    }
  173|  60.2k|                }
  174|       |
  175|       |                /* Route the method and URL */
  176|  60.2k|                selectedRouter->getUserData() = {(HttpResponse<SSL> *) s, httpRequest};
  177|  60.2k|                if (!selectedRouter->route(httpRequest->getCaseSensitiveMethod(), httpRequest->getUrl())) {
  ------------------
  |  Branch (177:21): [True: 0, False: 60.2k]
  ------------------
  178|       |                    /* We have to force close this socket as we have no handler for it */
  179|      0|                    us_socket_close(SSL, (us_socket_t *) s, 0, nullptr);
  180|      0|                    return nullptr;
  181|      0|                }
  182|       |
  183|       |                /* First of all we need to check if this socket was deleted due to upgrade */
  184|  60.2k|                if (httpContextData->upgradedWebSocket) {
  ------------------
  |  Branch (184:21): [True: 40.1k, False: 20.1k]
  ------------------
  185|       |                    /* We differ between closed and upgraded below */
  186|  40.1k|                    return nullptr;
  187|  40.1k|                }
  188|       |
  189|       |                /* Was the socket closed? */
  190|  20.1k|                if (us_socket_is_closed(SSL, (struct us_socket_t *) s)) {
  ------------------
  |  Branch (190:21): [True: 976, False: 19.1k]
  ------------------
  191|    976|                    return nullptr;
  192|    976|                }
  193|       |
  194|       |                /* We absolutely have to terminate parsing if shutdown */
  195|  19.1k|                if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) {
  ------------------
  |  Branch (195:21): [True: 0, False: 19.1k]
  ------------------
  196|      0|                    return nullptr;
  197|      0|                }
  198|       |
  199|       |                /* Returning from a request handler without responding or attaching an onAborted handler is ill-use */
  200|  19.1k|                if (!((HttpResponse<SSL> *) s)->hasResponded() && !httpResponseData->onAborted) {
  ------------------
  |  Branch (200:21): [True: 4.29k, False: 14.8k]
  |  Branch (200:67): [True: 0, False: 4.29k]
  ------------------
  201|       |                    /* Throw exception here? */
  202|      0|                    std::cerr << "Error: Returning from a request handler without responding or attaching an abort handler is forbidden!" << std::endl;
  203|      0|                    std::terminate();
  204|      0|                }
  205|       |
  206|       |                /* If we have not responded and we have a data handler, we need to timeout to enfore client sending the data */
  207|  19.1k|                if (!((HttpResponse<SSL> *) s)->hasResponded() && httpResponseData->inStream) {
  ------------------
  |  Branch (207:21): [True: 4.29k, False: 14.8k]
  |  Branch (207:67): [True: 4.29k, False: 0]
  ------------------
  208|  4.29k|                    us_socket_timeout(SSL, (us_socket_t *) s, HTTP_IDLE_TIMEOUT_S);
  209|  4.29k|                }
  210|       |
  211|       |                /* Continue parsing */
  212|  19.1k|                return s;
  213|       |
  214|  19.1k|            }, [httpResponseData](void *user, std::string_view data, bool fin) -> void * {
_ZZZN3uWS11HttpContextILb0EE4initEvENKUlP11us_socket_tPciE_clES3_S4_iENKUlPvNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEbE_clES6_SB_b:
  214|  49.5k|            }, [httpResponseData](void *user, std::string_view data, bool fin) -> void * {
  215|       |                /* We always get an empty chunk even if there is no data */
  216|  49.5k|                if (httpResponseData->inStream) {
  ------------------
  |  Branch (216:21): [True: 34.9k, False: 14.5k]
  ------------------
  217|       |
  218|       |                    /* Todo: can this handle timeout for non-post as well? */
  219|  34.9k|                    if (fin) {
  ------------------
  |  Branch (219:25): [True: 3.13k, False: 31.8k]
  ------------------
  220|       |                        /* If we just got the last chunk (or empty chunk), disable timeout */
  221|  3.13k|                        us_socket_timeout(SSL, (struct us_socket_t *) user, 0);
  222|  31.8k|                    } else {
  223|       |                        /* We still have some more data coming in later, so reset timeout */
  224|       |                        /* Only reset timeout if we got enough bytes (16kb/sec) since last time we reset here */
  225|  31.8k|                        httpResponseData->received_bytes_per_timeout += (unsigned int) data.length();
  226|  31.8k|                        if (httpResponseData->received_bytes_per_timeout >= HTTP_RECEIVE_THROUGHPUT_BYTES * HTTP_IDLE_TIMEOUT_S) {
  ------------------
  |  Branch (226:29): [True: 11, False: 31.8k]
  ------------------
  227|     11|                            us_socket_timeout(SSL, (struct us_socket_t *) user, HTTP_IDLE_TIMEOUT_S);
  228|     11|                            httpResponseData->received_bytes_per_timeout = 0;
  229|     11|                        }
  230|  31.8k|                    }
  231|       |
  232|       |                    /* We might respond in the handler, so do not change timeout after this */
  233|  34.9k|                    httpResponseData->inStream(data, fin);
  234|       |
  235|       |                    /* Was the socket closed? */
  236|  34.9k|                    if (us_socket_is_closed(SSL, (struct us_socket_t *) user)) {
  ------------------
  |  Branch (236:25): [True: 0, False: 34.9k]
  ------------------
  237|      0|                        return nullptr;
  238|      0|                    }
  239|       |
  240|       |                    /* We absolutely have to terminate parsing if shutdown */
  241|  34.9k|                    if (us_socket_is_shut_down(SSL, (us_socket_t *) user)) {
  ------------------
  |  Branch (241:25): [True: 0, False: 34.9k]
  ------------------
  242|      0|                        return nullptr;
  243|      0|                    }
  244|       |
  245|       |                    /* If we were given the last data chunk, reset data handler to ensure following
  246|       |                     * requests on the same socket won't trigger any previously registered behavior */
  247|  34.9k|                    if (fin) {
  ------------------
  |  Branch (247:25): [True: 3.13k, False: 31.8k]
  ------------------
  248|  3.13k|                        httpResponseData->inStream = nullptr;
  249|  3.13k|                    }
  250|  34.9k|                }
  251|  49.5k|                return user;
  252|  49.5k|            });
_ZZN3uWS11HttpContextILb0EE4initEvENKUlP11us_socket_tE_clES3_:
  325|  2.65k|        us_socket_context_on_writable(SSL, getSocketContext(), [](us_socket_t *s) {
  326|       |
  327|  2.65k|            AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
  328|  2.65k|            HttpResponseData<SSL> *httpResponseData = (HttpResponseData<SSL> *) asyncSocket->getAsyncSocketData();
  329|       |
  330|       |            /* Ask the developer to write data and return success (true) or failure (false), OR skip sending anything and return success (true). */
  331|  2.65k|            if (httpResponseData->onWritable) {
  ------------------
  |  Branch (331:17): [True: 0, False: 2.65k]
  ------------------
  332|       |                /* We are now writable, so hang timeout again, the user does not have to do anything so we should hang until end or tryEnd rearms timeout */
  333|      0|                us_socket_timeout(SSL, s, 0);
  334|       |
  335|       |                /* We expect the developer to return whether or not write was successful (true).
  336|       |                 * If write was never called, the developer should still return true so that we may drain. */
  337|      0|                bool success = httpResponseData->callOnWritable(httpResponseData->offset);
  338|       |
  339|       |                /* The developer indicated that their onWritable failed. */
  340|      0|                if (!success) {
  ------------------
  |  Branch (340:21): [True: 0, False: 0]
  ------------------
  341|       |                    /* Skip testing if we can drain anything since that might perform an extra syscall */
  342|      0|                    return s;
  343|      0|                }
  344|       |
  345|       |                /* We don't want to fall through since we don't want to mess with timeout.
  346|       |                 * It makes little sense to drain any backpressure when the user has registered onWritable. */
  347|      0|                return s;
  348|      0|            }
  349|       |
  350|       |            /* Drain any socket buffer, this might empty our backpressure and thus finish the request */
  351|  2.65k|            /*auto [written, failed] = */asyncSocket->write(nullptr, 0, true, 0);
  352|       |
  353|       |            /* Should we close this connection after a response - and is this response really done? */
  354|  2.65k|            if (httpResponseData->state & HttpResponseData<SSL>::HTTP_CONNECTION_CLOSE) {
  ------------------
  |  Branch (354:17): [True: 875, False: 1.78k]
  ------------------
  355|    875|                if ((httpResponseData->state & HttpResponseData<SSL>::HTTP_RESPONSE_PENDING) == 0) {
  ------------------
  |  Branch (355:21): [True: 681, False: 194]
  ------------------
  356|    681|                    if (asyncSocket->getBufferedAmount() == 0) {
  ------------------
  |  Branch (356:25): [True: 224, False: 457]
  ------------------
  357|    224|                        asyncSocket->shutdown();
  358|       |                        /* We need to force close after sending FIN since we want to hinder
  359|       |                         * clients from keeping to send their huge data */
  360|    224|                        asyncSocket->close();
  361|    224|                    }
  362|    681|                }
  363|    875|            }
  364|       |
  365|       |            /* Expect another writable event, or another request within the timeout */
  366|  2.65k|            asyncSocket->timeout(HTTP_IDLE_TIMEOUT_S);
  367|       |
  368|  2.65k|            return s;
  369|  2.65k|        });
_ZZN3uWS11HttpContextILb0EE4initEvENKUlP11us_socket_tE0_clES3_:
  372|  31.2k|        us_socket_context_on_end(SSL, getSocketContext(), [](us_socket_t *s) {
  373|       |
  374|       |            /* We do not care for half closed sockets */
  375|  31.2k|            AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
  376|  31.2k|            return asyncSocket->close();
  377|       |
  378|  31.2k|        });
_ZZN3uWS11HttpContextILb0EE4initEvENKUlP11us_socket_tE1_clES3_:
  381|  2.05k|        us_socket_context_on_timeout(SSL, getSocketContext(), [](us_socket_t *s) {
  382|       |
  383|       |            /* Force close rather than gracefully shutdown and risk confusing the client with a complete download */
  384|  2.05k|            AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
  385|  2.05k|            return asyncSocket->close();
  386|       |
  387|  2.05k|        });
_ZN3uWS11HttpContextILb0EE4freeEv:
  409|  6.41k|    void free() {
  410|       |        /* Destruct socket context data */
  411|  6.41k|        HttpContextData<SSL> *httpContextData = getSocketContextData();
  412|  6.41k|        httpContextData->~HttpContextData<SSL>();
  413|       |
  414|       |        /* Free the socket context in whole */
  415|  6.41k|        us_socket_context_free(SSL, getSocketContext());
  416|  6.41k|    }
_ZN3uWS11HttpContextILb0EE20getSocketContextDataEv:
   61|  91.4k|    HttpContextData<SSL> *getSocketContextData() {
   62|  91.4k|        return (HttpContextData<SSL> *) us_socket_context_ext(SSL, getSocketContext());
   63|  91.4k|    }
_ZN3uWS11HttpContextILb0EE6onHttpENSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEES8_ON5ofats13any_invocableIFvPNS_12HttpResponseILb0EEEPNS_11HttpRequestEEEEb:
  423|  38.4k|    void onHttp(std::string method, std::string pattern, MoveOnlyFunction<void(HttpResponse<SSL> *, HttpRequest *)> &&handler, bool upgrade = false) {
  424|  38.4k|        HttpContextData<SSL> *httpContextData = getSocketContextData();
  425|       |
  426|       |        /* Todo: This is ugly, fix */
  427|  38.4k|        std::vector<std::string> methods;
  428|  38.4k|        if (method == "*") {
  ------------------
  |  Branch (428:13): [True: 12.8k, False: 25.6k]
  ------------------
  429|  12.8k|            methods = {"*"};
  430|  25.6k|        } else {
  431|  25.6k|            methods = {method};
  432|  25.6k|        }
  433|       |
  434|  38.4k|        uint32_t priority = method == "*" ? httpContextData->currentRouter->LOW_PRIORITY : (upgrade ? httpContextData->currentRouter->HIGH_PRIORITY : httpContextData->currentRouter->MEDIUM_PRIORITY);
  ------------------
  |  Branch (434:29): [True: 12.8k, False: 25.6k]
  |  Branch (434:93): [True: 12.8k, False: 12.8k]
  ------------------
  435|       |
  436|       |        /* If we are passed nullptr then remove this */
  437|  38.4k|        if (!handler) {
  ------------------
  |  Branch (437:13): [True: 0, False: 38.4k]
  ------------------
  438|      0|            httpContextData->currentRouter->remove(methods[0], pattern, priority);
  439|      0|            return;
  440|      0|        }
  441|       |
  442|       |        /* Record this route's parameter offsets */
  443|  38.4k|        std::map<std::string, unsigned short, std::less<>> parameterOffsets;
  444|  38.4k|        unsigned short offset = 0;
  445|   147k|        for (unsigned int i = 0; i < pattern.length(); i++) {
  ------------------
  |  Branch (445:34): [True: 109k, False: 38.4k]
  ------------------
  446|   109k|            if (pattern[i] == ':') {
  ------------------
  |  Branch (446:17): [True: 6.41k, False: 102k]
  ------------------
  447|  6.41k|                i++;
  448|  6.41k|                unsigned int start = i;
  449|  38.4k|                while (i < pattern.length() && pattern[i] != '/') {
  ------------------
  |  Branch (449:24): [True: 38.4k, False: 0]
  |  Branch (449:48): [True: 32.0k, False: 6.41k]
  ------------------
  450|  32.0k|                    i++;
  451|  32.0k|                }
  452|  6.41k|                parameterOffsets[std::string(pattern.data() + start, i - start)] = offset;
  453|       |                //std::cout << "<" << std::string(pattern.data() + start, i - start) << "> is offset " << offset;
  454|  6.41k|                offset++;
  455|  6.41k|            }
  456|   109k|        }
  457|       |
  458|  38.4k|        httpContextData->currentRouter->add(methods, pattern, [handler = std::move(handler), parameterOffsets = std::move(parameterOffsets)](auto *r) mutable {
  459|  38.4k|            auto user = r->getUserData();
  460|  38.4k|            user.httpRequest->setYield(false);
  461|  38.4k|            user.httpRequest->setParameters(r->getParameters());
  462|  38.4k|            user.httpRequest->setParameterOffsets(&parameterOffsets);
  463|       |
  464|       |            /* Middleware? Automatically respond to expectations */
  465|  38.4k|            std::string_view expect = user.httpRequest->getHeader("expect");
  466|  38.4k|            if (expect.length() && expect == "100-continue") {
  467|  38.4k|                user.httpResponse->writeContinue();
  468|  38.4k|            }
  469|       |
  470|  38.4k|            handler(user.httpResponse, user.httpRequest);
  471|       |
  472|       |            /* If any handler yielded, the router will keep looking for a suitable handler. */
  473|  38.4k|            if (user.httpRequest->getYield()) {
  474|  38.4k|                return false;
  475|  38.4k|            }
  476|  38.4k|            return true;
  477|  38.4k|        }, priority);
  478|  38.4k|    }
_ZZN3uWS11HttpContextILb0EE6onHttpENSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEES8_ON5ofats13any_invocableIFvPNS_12HttpResponseILb0EEEPNS_11HttpRequestEEEEbENUlPT_E_clINS_10HttpRouterINS_15HttpContextDataILb0EE10RouterDataEEEEEDaSK_:
  458|  70.9k|        httpContextData->currentRouter->add(methods, pattern, [handler = std::move(handler), parameterOffsets = std::move(parameterOffsets)](auto *r) mutable {
  459|  70.9k|            auto user = r->getUserData();
  460|  70.9k|            user.httpRequest->setYield(false);
  461|  70.9k|            user.httpRequest->setParameters(r->getParameters());
  462|  70.9k|            user.httpRequest->setParameterOffsets(&parameterOffsets);
  463|       |
  464|       |            /* Middleware? Automatically respond to expectations */
  465|  70.9k|            std::string_view expect = user.httpRequest->getHeader("expect");
  466|  70.9k|            if (expect.length() && expect == "100-continue") {
  ------------------
  |  Branch (466:17): [True: 738, False: 70.2k]
  |  Branch (466:36): [True: 212, False: 526]
  ------------------
  467|    212|                user.httpResponse->writeContinue();
  468|    212|            }
  469|       |
  470|  70.9k|            handler(user.httpResponse, user.httpRequest);
  471|       |
  472|       |            /* If any handler yielded, the router will keep looking for a suitable handler. */
  473|  70.9k|            if (user.httpRequest->getYield()) {
  ------------------
  |  Branch (473:17): [True: 10.6k, False: 60.2k]
  ------------------
  474|  10.6k|                return false;
  475|  10.6k|            }
  476|  60.2k|            return true;
  477|  70.9k|        }, priority);
_ZN3uWS11HttpContextILb0EE6listenEPKcii:
  481|  6.41k|    us_listen_socket_t *listen(const char *host, int port, int options) {
  482|  6.41k|        return us_socket_context_listen(SSL, getSocketContext(), host, port, options, sizeof(HttpResponseData<SSL>));
  483|  6.41k|    }

_ZN3uWS12optional_ptrIcEENSt3__18optionalIPT_EES4_:
   47|      2|std::optional<T *> optional_ptr(T *ptr) {
   48|      2|    return ptr ? std::optional<T *>(ptr) : std::nullopt;
  ------------------
  |  Branch (48:12): [True: 0, False: 2]
  ------------------
   49|      2|}
_ZN3uWS10HttpParser17consumePostPaddedEPcjPvS2_ON5ofats13any_invocableIFS2_S2_PNS_11HttpRequestEEEEONS4_IFS2_S2_NSt3__117basic_string_viewIcNSA_11char_traitsIcEEEEbEEE:
  583|   382k|    std::pair<unsigned int, void *> consumePostPadded(char *data, unsigned int length, void *user, void *reserved, MoveOnlyFunction<void *(void *, HttpRequest *)> &&requestHandler, MoveOnlyFunction<void *(void *, std::string_view, bool)> &&dataHandler) {
  584|       |
  585|       |        /* This resets BloomFilter by construction, but later we also reset it again.
  586|       |         * Optimize this to skip resetting twice (req could be made global) */
  587|   382k|        HttpRequest req;
  588|       |
  589|   382k|        if (remainingStreamingBytes) {
  ------------------
  |  Branch (589:13): [True: 33.4k, False: 348k]
  ------------------
  590|       |
  591|       |            /* It's either chunked or with a content-length */
  592|  33.4k|            if (isParsingChunkedEncoding(remainingStreamingBytes)) {
  ------------------
  |  Branch (592:17): [True: 32.3k, False: 1.06k]
  ------------------
  593|  32.3k|                std::string_view dataToConsume(data, length);
  594|  32.3k|                for (auto chunk : uWS::ChunkIterator(&dataToConsume, &remainingStreamingBytes)) {
  ------------------
  |  Branch (594:33): [True: 31.2k, False: 32.3k]
  ------------------
  595|  31.2k|                    dataHandler(user, chunk, chunk.length() == 0);
  596|  31.2k|                }
  597|  32.3k|                if (isParsingInvalidChunkedEncoding(remainingStreamingBytes)) {
  ------------------
  |  Branch (597:21): [True: 445, False: 31.8k]
  ------------------
  598|    445|                    return {HTTP_ERROR_400_BAD_REQUEST, FULLPTR};
  599|    445|                }
  600|  31.8k|                data = (char *) dataToConsume.data();
  601|  31.8k|                length = (unsigned int) dataToConsume.length();
  602|  31.8k|            } else {
  603|       |                // this is exactly the same as below!
  604|       |                // todo: refactor this
  605|  1.06k|                if (remainingStreamingBytes >= length) {
  ------------------
  |  Branch (605:21): [True: 872, False: 196]
  ------------------
  606|    872|                    void *returnedUser = dataHandler(user, std::string_view(data, length), remainingStreamingBytes == length);
  607|    872|                    remainingStreamingBytes -= length;
  608|    872|                    return {0, returnedUser};
  609|    872|                } else {
  610|    196|                    void *returnedUser = dataHandler(user, std::string_view(data, remainingStreamingBytes), true);
  611|       |
  612|    196|                    data += (unsigned int) remainingStreamingBytes;
  613|    196|                    length -= (unsigned int) remainingStreamingBytes;
  614|       |
  615|    196|                    remainingStreamingBytes = 0;
  616|       |
  617|    196|                    if (returnedUser != user) {
  ------------------
  |  Branch (617:25): [True: 0, False: 196]
  ------------------
  618|      0|                        return {0, returnedUser};
  619|      0|                    }
  620|    196|                }
  621|  1.06k|            }
  622|       |
  623|   348k|        } else if (fallback.length()) {
  ------------------
  |  Branch (623:20): [True: 14.3k, False: 334k]
  ------------------
  624|  14.3k|            unsigned int had = (unsigned int) fallback.length();
  625|       |
  626|  14.3k|            size_t maxCopyDistance = std::min<size_t>(MAX_FALLBACK_SIZE - fallback.length(), (size_t) length);
  627|       |
  628|       |            /* We don't want fallback to be short string optimized, since we want to move it */
  629|  14.3k|            fallback.reserve(fallback.length() + maxCopyDistance + std::max<unsigned int>(MINIMUM_HTTP_POST_PADDING, sizeof(std::string)));
  630|  14.3k|            fallback.append(data, maxCopyDistance);
  631|       |
  632|       |            // break here on break
  633|  14.3k|            std::pair<unsigned int, void *> consumed = fenceAndConsumePostPadded<true>(fallback.data(), (unsigned int) fallback.length(), user, reserved, &req, requestHandler, dataHandler);
  634|  14.3k|            if (consumed.second != user) {
  ------------------
  |  Branch (634:17): [True: 3.24k, False: 11.1k]
  ------------------
  635|  3.24k|                return consumed;
  636|  3.24k|            }
  637|       |
  638|  11.1k|            if (consumed.first) {
  ------------------
  |  Branch (638:17): [True: 2.55k, False: 8.55k]
  ------------------
  639|       |
  640|       |                /* This logic assumes that we consumed everything in fallback buffer.
  641|       |                 * This is critically important, as we will get an integer overflow in case
  642|       |                 * of "had" being larger than what we consumed, and that we would drop data */
  643|  2.55k|                fallback.clear();
  644|  2.55k|                data += consumed.first - had;
  645|  2.55k|                length -= consumed.first - had;
  646|       |
  647|  2.55k|                if (remainingStreamingBytes) {
  ------------------
  |  Branch (647:21): [True: 1.70k, False: 857]
  ------------------
  648|       |                    /* It's either chunked or with a content-length */
  649|  1.70k|                    if (isParsingChunkedEncoding(remainingStreamingBytes)) {
  ------------------
  |  Branch (649:25): [True: 648, False: 1.05k]
  ------------------
  650|    648|                        std::string_view dataToConsume(data, length);
  651|    648|                        for (auto chunk : uWS::ChunkIterator(&dataToConsume, &remainingStreamingBytes)) {
  ------------------
  |  Branch (651:41): [True: 420, False: 648]
  ------------------
  652|    420|                            dataHandler(user, chunk, chunk.length() == 0);
  653|    420|                        }
  654|    648|                        if (isParsingInvalidChunkedEncoding(remainingStreamingBytes)) {
  ------------------
  |  Branch (654:29): [True: 201, False: 447]
  ------------------
  655|    201|                            return {HTTP_ERROR_400_BAD_REQUEST, FULLPTR};
  656|    201|                        }
  657|    447|                        data = (char *) dataToConsume.data();
  658|    447|                        length = (unsigned int) dataToConsume.length();
  659|  1.05k|                    } else {
  660|       |                        // this is exactly the same as above!
  661|  1.05k|                        if (remainingStreamingBytes >= (unsigned int) length) {
  ------------------
  |  Branch (661:29): [True: 853, False: 199]
  ------------------
  662|    853|                            void *returnedUser = dataHandler(user, std::string_view(data, length), remainingStreamingBytes == (unsigned int) length);
  663|    853|                            remainingStreamingBytes -= length;
  664|    853|                            return {0, returnedUser};
  665|    853|                        } else {
  666|    199|                            void *returnedUser = dataHandler(user, std::string_view(data, remainingStreamingBytes), true);
  667|       |
  668|    199|                            data += (unsigned int) remainingStreamingBytes;
  669|    199|                            length -= (unsigned int) remainingStreamingBytes;
  670|       |
  671|    199|                            remainingStreamingBytes = 0;
  672|       |
  673|    199|                            if (returnedUser != user) {
  ------------------
  |  Branch (673:33): [True: 0, False: 199]
  ------------------
  674|      0|                                return {0, returnedUser};
  675|      0|                            }
  676|    199|                        }
  677|  1.05k|                    }
  678|  1.70k|                }
  679|       |
  680|  8.55k|            } else {
  681|  8.55k|                if (fallback.length() == MAX_FALLBACK_SIZE) {
  ------------------
  |  Branch (681:21): [True: 195, False: 8.35k]
  ------------------
  682|    195|                    return {HTTP_ERROR_431_REQUEST_HEADER_FIELDS_TOO_LARGE, FULLPTR};
  683|    195|                }
  684|  8.35k|                return {0, user};
  685|  8.55k|            }
  686|  11.1k|        }
  687|       |
  688|   367k|        std::pair<unsigned int, void *> consumed = fenceAndConsumePostPadded<false>(data, length, user, reserved, &req, requestHandler, dataHandler);
  689|   367k|        if (consumed.second != user) {
  ------------------
  |  Branch (689:13): [True: 321k, False: 46.4k]
  ------------------
  690|   321k|            return consumed;
  691|   321k|        }
  692|       |
  693|  46.4k|        data += consumed.first;
  694|  46.4k|        length -= consumed.first;
  695|       |
  696|  46.4k|        if (length) {
  ------------------
  |  Branch (696:13): [True: 9.54k, False: 36.8k]
  ------------------
  697|  9.54k|            if (length < MAX_FALLBACK_SIZE) {
  ------------------
  |  Branch (697:17): [True: 9.54k, False: 0]
  ------------------
  698|  9.54k|                fallback.append(data, length);
  699|  9.54k|            } else {
  700|      0|                return {HTTP_ERROR_431_REQUEST_HEADER_FIELDS_TOO_LARGE, FULLPTR};
  701|      0|            }
  702|  9.54k|        }
  703|       |
  704|       |        // added for now
  705|  46.4k|        return {0, user};
  706|  46.4k|    }
_ZN3uWS10HttpParser25fenceAndConsumePostPaddedILi1EEENSt3__14pairIjPvEEPcjS4_S4_PNS_11HttpRequestERN5ofats13any_invocableIFS4_S4_S8_EEERNSA_IFS4_S4_NS2_17basic_string_viewIcNS2_11char_traitsIcEEEEbEEE:
  448|  14.3k|    std::pair<unsigned int, void *> fenceAndConsumePostPadded(char *data, unsigned int length, void *user, void *reserved, HttpRequest *req, MoveOnlyFunction<void *(void *, HttpRequest *)> &requestHandler, MoveOnlyFunction<void *(void *, std::string_view, bool)> &dataHandler) {
  449|       |
  450|       |        /* How much data we CONSUMED (to throw away) */
  451|  14.3k|        unsigned int consumedTotal = 0;
  452|  14.3k|        unsigned int err = 0;
  453|       |
  454|       |        /* Fence two bytes past end of our buffer (buffer has post padded margins).
  455|       |         * This is to always catch scan for \r but not for \r\n. */
  456|  14.3k|        data[length] = '\r';
  457|  14.3k|        data[length + 1] = 'a'; /* Anything that is not \n, to trigger "invalid request" */
  458|       |
  459|  14.3k|        for (unsigned int consumed; length && (consumed = getHeaders(data, data + length, req->headers, reserved, err)); ) {
  ------------------
  |  Branch (459:37): [True: 14.3k, False: 0]
  |  Branch (459:47): [True: 5.80k, False: 8.55k]
  ------------------
  460|  5.80k|            data += consumed;
  461|  5.80k|            length -= consumed;
  462|  5.80k|            consumedTotal += consumed;
  463|       |
  464|       |            /* Even if we could parse it, check for length here as well */
  465|  5.80k|            if (consumed > MAX_FALLBACK_SIZE) {
  ------------------
  |  Branch (465:17): [True: 0, False: 5.80k]
  ------------------
  466|      0|                return {HTTP_ERROR_431_REQUEST_HEADER_FIELDS_TOO_LARGE, FULLPTR};
  467|      0|            }
  468|       |
  469|       |            /* Store HTTP version (ancient 1.0 or 1.1) */
  470|  5.80k|            req->ancientHttp = false;
  471|       |
  472|       |            /* Add all headers to bloom filter */
  473|  5.80k|            req->bf.reset();
  474|  23.9k|            for (HttpRequest::Header *h = req->headers; (++h)->key.length(); ) {
  ------------------
  |  Branch (474:57): [True: 18.1k, False: 5.80k]
  ------------------
  475|  18.1k|                req->bf.add(h->key);
  476|  18.1k|            }
  477|       |            
  478|       |            /* Break if no host header (but we can have empty string which is different from nullptr) */
  479|  5.80k|            if (!req->getHeader("host").data()) {
  ------------------
  |  Branch (479:17): [True: 457, False: 5.34k]
  ------------------
  480|    457|                return {HTTP_ERROR_400_BAD_REQUEST, FULLPTR};
  481|    457|            }
  482|       |
  483|       |            /* RFC 9112 6.3
  484|       |            * If a message is received with both a Transfer-Encoding and a Content-Length header field,
  485|       |            * the Transfer-Encoding overrides the Content-Length. Such a message might indicate an attempt
  486|       |            * to perform request smuggling (Section 11.2) or response splitting (Section 11.1) and
  487|       |            * ought to be handled as an error. */
  488|  5.34k|            std::string_view transferEncodingString = req->getHeader("transfer-encoding");
  489|  5.34k|            std::string_view contentLengthString = req->getHeader("content-length");
  490|  5.34k|            if (transferEncodingString.length() && contentLengthString.length()) {
  ------------------
  |  Branch (490:17): [True: 852, False: 4.49k]
  |  Branch (490:52): [True: 204, False: 648]
  ------------------
  491|       |                /* Returning fullptr is the same as calling the errorHandler */
  492|       |                /* We could be smart and set an error in the context along with this, to indicate what 
  493|       |                 * http error response we might want to return */
  494|    204|                return {HTTP_ERROR_400_BAD_REQUEST, FULLPTR};
  495|    204|            }
  496|       |
  497|       |            /* Parse query */
  498|  5.14k|            const char *querySeparatorPtr = (const char *) memchr(req->headers->value.data(), '?', req->headers->value.length());
  499|  5.14k|            req->querySeparator = (unsigned int) ((querySeparatorPtr ? querySeparatorPtr : req->headers->value.data() + req->headers->value.length()) - req->headers->value.data());
  ------------------
  |  Branch (499:52): [True: 389, False: 4.75k]
  ------------------
  500|       |
  501|       |            /* If returned socket is not what we put in we need
  502|       |             * to break here as we either have upgraded to
  503|       |             * WebSockets or otherwise closed the socket. */
  504|  5.14k|            void *returnedUser = requestHandler(user, req);
  505|  5.14k|            if (returnedUser != user) {
  ------------------
  |  Branch (505:17): [True: 2.12k, False: 3.01k]
  ------------------
  506|       |                /* We are upgraded to WebSocket or otherwise broken */
  507|  2.12k|                return {consumedTotal, returnedUser};
  508|  2.12k|            }
  509|       |
  510|       |            /* The rules at play here according to RFC 9112 for requests are essentially:
  511|       |             * If both content-length and transfer-encoding then invalid message; must break.
  512|       |             * If has transfer-encoding then must be chunked regardless of value.
  513|       |             * If content-length then fixed length even if 0.
  514|       |             * If none of the above then fixed length is 0. */
  515|       |
  516|       |            /* RFC 9112 6.3
  517|       |             * If a message is received with both a Transfer-Encoding and a Content-Length header field,
  518|       |             * the Transfer-Encoding overrides the Content-Length. */
  519|  3.01k|            if (transferEncodingString.length()) {
  ------------------
  |  Branch (519:17): [True: 648, False: 2.36k]
  ------------------
  520|       |
  521|       |                /* If a proxy sent us the transfer-encoding header that 100% means it must be chunked or else the proxy is
  522|       |                 * not RFC 9112 compliant. Therefore it is always better to assume this is the case, since that entirely eliminates 
  523|       |                 * all forms of transfer-encoding obfuscation tricks. We just rely on the header. */
  524|       |
  525|       |                /* RFC 9112 6.3
  526|       |                 * If a Transfer-Encoding header field is present in a request and the chunked transfer coding is not the
  527|       |                 * final encoding, the message body length cannot be determined reliably; the server MUST respond with the
  528|       |                 * 400 (Bad Request) status code and then close the connection. */
  529|       |
  530|       |                /* In this case we fail later by having the wrong interpretation (assuming chunked).
  531|       |                 * This could be made stricter but makes no difference either way, unless forwarding the identical message as a proxy. */
  532|       |
  533|    648|                remainingStreamingBytes = STATE_IS_CHUNKED;
  534|       |                /* If consume minimally, we do not want to consume anything but we want to mark this as being chunked */
  535|    648|                if (!CONSUME_MINIMALLY) {
  ------------------
  |  Branch (535:21): [Folded - Ignored]
  ------------------
  536|       |                    /* Go ahead and parse it (todo: better heuristics for emitting FIN to the app level) */
  537|      0|                    std::string_view dataToConsume(data, length);
  538|      0|                    for (auto chunk : uWS::ChunkIterator(&dataToConsume, &remainingStreamingBytes)) {
  ------------------
  |  Branch (538:37): [True: 0, False: 0]
  ------------------
  539|      0|                        dataHandler(user, chunk, chunk.length() == 0);
  540|      0|                    }
  541|      0|                    if (isParsingInvalidChunkedEncoding(remainingStreamingBytes)) {
  ------------------
  |  Branch (541:25): [True: 0, False: 0]
  ------------------
  542|      0|                        return {HTTP_ERROR_400_BAD_REQUEST, FULLPTR};
  543|      0|                    }
  544|      0|                    unsigned int consumed = (length - (unsigned int) dataToConsume.length());
  545|      0|                    data = (char *) dataToConsume.data();
  546|      0|                    length = (unsigned int) dataToConsume.length();
  547|      0|                    consumedTotal += consumed;
  548|      0|                }
  549|  2.36k|            } else if (contentLengthString.length()) {
  ------------------
  |  Branch (549:24): [True: 1.71k, False: 659]
  ------------------
  550|  1.71k|                remainingStreamingBytes = toUnsignedInteger(contentLengthString);
  551|  1.71k|                if (remainingStreamingBytes == UINT64_MAX) {
  ------------------
  |  Branch (551:21): [True: 460, False: 1.25k]
  ------------------
  552|       |                    /* Parser error */
  553|    460|                    return {HTTP_ERROR_400_BAD_REQUEST, FULLPTR};
  554|    460|                }
  555|       |
  556|  1.25k|                if (!CONSUME_MINIMALLY) {
  ------------------
  |  Branch (556:21): [Folded - Ignored]
  ------------------
  557|      0|                    unsigned int emittable = (unsigned int) std::min<uint64_t>(remainingStreamingBytes, length);
  558|      0|                    dataHandler(user, std::string_view(data, emittable), emittable == remainingStreamingBytes);
  559|      0|                    remainingStreamingBytes -= emittable;
  560|       |
  561|      0|                    data += emittable;
  562|      0|                    length -= emittable;
  563|      0|                    consumedTotal += emittable;
  564|      0|                }
  565|  1.25k|            } else {
  566|       |                /* If we came here without a body; emit an empty data chunk to signal no data */
  567|    659|                dataHandler(user, {}, true);
  568|    659|            }
  569|       |
  570|       |            /* Consume minimally should break as easrly as possible */
  571|  2.55k|            if (CONSUME_MINIMALLY) {
  ------------------
  |  Branch (571:17): [Folded - Ignored]
  ------------------
  572|  2.55k|                break;
  573|  2.55k|            }
  574|  2.55k|        }
  575|       |        /* Whenever we return FULLPTR, the interpretation of "consumed" should be the HttpError enum. */
  576|  11.1k|        if (err) {
  ------------------
  |  Branch (576:13): [True: 0, False: 11.1k]
  ------------------
  577|      0|            return {err, FULLPTR};
  578|      0|        }
  579|  11.1k|        return {consumedTotal, user};
  580|  11.1k|    }
_ZN3uWS10HttpParser10getHeadersEPcS1_PNS_11HttpRequest6HeaderEPvRj:
  337|   360k|    static unsigned int getHeaders(char *postPaddedBuffer, char *end, struct HttpRequest::Header *headers, void *reserved, unsigned int &err) {
  338|   360k|        char *preliminaryKey, *preliminaryValue, *start = postPaddedBuffer;
  339|       |
  340|       |        #ifdef UWS_WITH_PROXY
  341|       |            /* ProxyParser is passed as reserved parameter */
  342|       |            ProxyParser *pp = (ProxyParser *) reserved;
  343|       |
  344|       |            /* Parse PROXY protocol */
  345|       |            auto [done, offset] = pp->parse({postPaddedBuffer, (size_t) (end - postPaddedBuffer)});
  346|       |            if (!done) {
  347|       |                /* We do not reset the ProxyParser (on filure) since it is tied to this
  348|       |                * connection, which is really only supposed to ever get one PROXY frame
  349|       |                * anyways. We do however allow multiple PROXY frames to be sent (overwrites former). */
  350|       |                return 0;
  351|       |            } else {
  352|       |                /* We have consumed this data so skip it */
  353|       |                postPaddedBuffer += offset;
  354|       |            }
  355|       |        #else
  356|       |            /* This one is unused */
  357|   360k|            (void) reserved;
  358|   360k|            (void) end;
  359|   360k|        #endif
  360|       |
  361|       |        /* It is critical for fallback buffering logic that we only return with success
  362|       |         * if we managed to parse a complete HTTP request (minus data). Returning success
  363|       |         * for PROXY means we can end up succeeding, yet leaving bytes in the fallback buffer
  364|       |         * which is then removed, and our counters to flip due to overflow and we end up with a crash */
  365|       |
  366|       |        /* The request line is different from the field names / field values */
  367|   360k|        if (!(postPaddedBuffer = consumeRequestLine(postPaddedBuffer, headers[0]))) {
  ------------------
  |  Branch (367:13): [True: 280k, False: 79.8k]
  ------------------
  368|       |            /* Error - invalid request line */
  369|       |            /* Assuming it is 505 HTTP Version Not Supported */
  370|   280k|            err = HTTP_ERROR_505_HTTP_VERSION_NOT_SUPPORTED;
  371|   280k|            return 0;
  372|   280k|        }
  373|  79.8k|        headers++;
  374|       |
  375|   210k|        for (unsigned int i = 1; i < UWS_HTTP_MAX_HEADERS_COUNT - 1; i++) {
  ------------------
  |  |   53|   210k|#define UWS_HTTP_MAX_HEADERS_COUNT 100
  ------------------
  |  Branch (375:34): [True: 210k, False: 194]
  ------------------
  376|       |            /* Lower case and consume the field name */
  377|   210k|            preliminaryKey = postPaddedBuffer;
  378|   210k|            postPaddedBuffer = (char *) consumeFieldName(postPaddedBuffer);
  379|   210k|            headers->key = std::string_view(preliminaryKey, (size_t) (postPaddedBuffer - preliminaryKey));
  380|       |
  381|       |            /* We should not accept whitespace between key and colon, so colon must foloow immediately */
  382|   210k|            if (postPaddedBuffer[0] != ':') {
  ------------------
  |  Branch (382:17): [True: 8.19k, False: 201k]
  ------------------
  383|       |                /* Error: invalid chars in field name */
  384|  8.19k|                return 0;
  385|  8.19k|            }
  386|   201k|            postPaddedBuffer++;
  387|       |
  388|   201k|            preliminaryValue = postPaddedBuffer;
  389|       |            /* The goal of this call is to find next "\r\n", or any invalid field value chars, fast */
  390|   202k|            while (true) {
  ------------------
  |  Branch (390:20): [Folded - Ignored]
  ------------------
  391|   202k|                postPaddedBuffer = (char *) tryConsumeFieldValue(postPaddedBuffer);
  392|       |                /* If this is not CR then we caught some stinky invalid char on the way */
  393|   202k|                if (postPaddedBuffer[0] != '\r') {
  ------------------
  |  Branch (393:21): [True: 2.19k, False: 200k]
  ------------------
  394|       |                    /* If TAB then keep searching */
  395|  2.19k|                    if (postPaddedBuffer[0] == '\t') {
  ------------------
  |  Branch (395:25): [True: 799, False: 1.39k]
  ------------------
  396|    799|                        postPaddedBuffer++;
  397|    799|                        continue;
  398|    799|                    }
  399|       |                    /* Error - invalid chars in field value */
  400|  1.39k|                    return 0;
  401|  2.19k|                }
  402|   200k|                break;
  403|   202k|            }
  404|       |            /* We fence end[0] with \r, followed by end[1] being something that is "not \n", to signify "not found".
  405|       |                * This way we can have this one single check to see if we found \r\n WITHIN our allowed search space. */
  406|   200k|            if (postPaddedBuffer[1] == '\n') {
  ------------------
  |  Branch (406:17): [True: 193k, False: 6.72k]
  ------------------
  407|       |                /* Store this header, it is valid */
  408|   193k|                headers->value = std::string_view(preliminaryValue, (size_t) (postPaddedBuffer - preliminaryValue));
  409|   193k|                postPaddedBuffer += 2;
  410|       |
  411|       |                /* Trim trailing whitespace (SP, HTAB) */
  412|   237k|                while (headers->value.length() && headers->value.back() < 33) {
  ------------------
  |  Branch (412:24): [True: 148k, False: 88.3k]
  |  Branch (412:51): [True: 43.3k, False: 105k]
  ------------------
  413|  43.3k|                    headers->value.remove_suffix(1);
  414|  43.3k|                }
  415|       |
  416|       |                /* Trim initial whitespace (SP, HTAB) */
  417|   214k|                while (headers->value.length() && headers->value.front() < 33) {
  ------------------
  |  Branch (417:24): [True: 126k, False: 88.3k]
  |  Branch (417:51): [True: 20.6k, False: 105k]
  ------------------
  418|  20.6k|                    headers->value.remove_prefix(1);
  419|  20.6k|                }
  420|       |                
  421|   193k|                headers++;
  422|       |
  423|       |                /* We definitely have at least one header (or request line), so check if we are done */
  424|   193k|                if (*postPaddedBuffer == '\r') {
  ------------------
  |  Branch (424:21): [True: 63.3k, False: 130k]
  ------------------
  425|  63.3k|                    if (postPaddedBuffer[1] == '\n') {
  ------------------
  |  Branch (425:25): [True: 61.7k, False: 1.59k]
  ------------------
  426|       |                        /* This cann take the very last header space */
  427|  61.7k|                        headers->key = std::string_view(nullptr, 0);
  428|  61.7k|                        return (unsigned int) ((postPaddedBuffer + 2) - start);
  429|  61.7k|                    } else {
  430|       |                        /* \r\n\r plus non-\n letter is malformed request, or simply out of search space */
  431|  1.59k|                        return 0;
  432|  1.59k|                    }
  433|  63.3k|                }
  434|   193k|            } else {
  435|       |                /* We are either out of search space or this is a malformed request */
  436|  6.72k|                return 0;
  437|  6.72k|            }
  438|   200k|        }
  439|       |        /* We ran out of header space, too large request */
  440|    194|        return 0;
  441|  79.8k|    }
_ZN3uWS10HttpParser18consumeRequestLineEPcRNS_11HttpRequest6HeaderE:
  293|   360k|    static inline char *consumeRequestLine(char *data, HttpRequest::Header &header) {
  294|       |        /* Scan until single SP, assume next is / (origin request) */
  295|   360k|        char *start = data;
  296|       |        /* This catches the post padded CR and fails */
  297|   703k|        while (data[0] > 32) data++;
  ------------------
  |  Branch (297:16): [True: 343k, False: 360k]
  ------------------
  298|   360k|        if (data[0] == 32 && data[1] == '/') {
  ------------------
  |  Branch (298:13): [True: 85.5k, False: 274k]
  |  Branch (298:30): [True: 83.2k, False: 2.30k]
  ------------------
  299|  83.2k|            header.key = {start, (size_t) (data - start)};
  300|  83.2k|            data++;
  301|       |            /* Scan for less than 33 (catches post padded CR and fails) */
  302|  83.2k|            start = data;
  303|   114k|            for (; true; data += 8) {
  ------------------
  |  Branch (303:20): [Folded - Ignored]
  ------------------
  304|   114k|                uint64_t word;
  305|   114k|                memcpy(&word, data, sizeof(uint64_t));
  306|   114k|                if (hasLess(word, 33)) {
  ------------------
  |  Branch (306:21): [True: 83.2k, False: 31.6k]
  ------------------
  307|   334k|                    while (*(unsigned char *)data > 32) data++;
  ------------------
  |  Branch (307:28): [True: 250k, False: 83.2k]
  ------------------
  308|       |                    /* Now we stand on space */
  309|  83.2k|                    header.value = {start, (size_t) (data - start)};
  310|       |                    /* Check that the following is http 1.1 */
  311|  83.2k|                    if (memcmp(" HTTP/1.1\r\n", data, 11) == 0) {
  ------------------
  |  Branch (311:25): [True: 79.8k, False: 3.36k]
  ------------------
  312|  79.8k|                        return data + 11;
  313|  79.8k|                    }
  314|  3.36k|                    return nullptr;
  315|  83.2k|                }
  316|   114k|            }
  317|  83.2k|        }
  318|   277k|        return nullptr;
  319|   360k|    }
_ZN3uWS10HttpParser7hasLessEmm:
  220|   651k|    static inline uint64_t hasLess(uint64_t x, uint64_t n) {
  221|   651k|        return (((x)-~0ULL/255*(n))&~(x)&~0ULL/255*128);
  222|   651k|    }
_ZN3uWS10HttpParser16consumeFieldNameEPc:
  264|   210k|    static inline void *consumeFieldName(char *p) {
  265|       |        /* Best case fast path (particularly useful with clang) */
  266|   409k|        while (true) {
  ------------------
  |  Branch (266:16): [Folded - Ignored]
  ------------------
  267|   492k|            while ((*p >= 65) & (*p <= 90)) [[likely]] {
  ------------------
  |  Branch (267:20): [True: 82.2k, False: 409k]
  ------------------
  268|  82.2k|                *p |= 32;
  269|  82.2k|                p++;
  270|  82.2k|            }
  271|  1.88M|            while (((*p >= 97) & (*p <= 122))) [[likely]] {
  ------------------
  |  Branch (271:20): [True: 1.47M, False: 409k]
  ------------------
  272|  1.47M|                p++;
  273|  1.47M|            }
  274|   409k|            if (*p == ':') {
  ------------------
  |  Branch (274:17): [True: 200k, False: 209k]
  ------------------
  275|   200k|                return (void *)p;
  276|   200k|            }
  277|   209k|            if (*p == '-') {
  ------------------
  |  Branch (277:17): [True: 132k, False: 77.0k]
  ------------------
  278|   132k|                p++;
  279|   132k|            } else if (!((*p >= 65) & (*p <= 90))) {
  ------------------
  |  Branch (279:24): [True: 9.21k, False: 67.8k]
  ------------------
  280|       |                /* Exit fast path parsing */
  281|  9.21k|                break;
  282|  9.21k|            }
  283|   209k|        }
  284|       |
  285|       |        /* Generic */
  286|  67.0k|        while (isFieldNameByteFastLowercased(*(unsigned char *)p)) {
  ------------------
  |  Branch (286:16): [True: 57.8k, False: 9.21k]
  ------------------
  287|  57.8k|            p++;
  288|  57.8k|        }
  289|  9.21k|        return (void *)p;
  290|   210k|    }
_ZN3uWS10HttpParser29isFieldNameByteFastLowercasedERh:
  249|  67.0k|    static inline bool isFieldNameByteFastLowercased(unsigned char &in) {
  250|       |        /* Most common is lowercase alpha and hyphen */
  251|  67.0k|        if (((in >= 97) & (in <= 122)) | (in == '-')) [[likely]] {
  ------------------
  |  Branch (251:13): [True: 49.7k, False: 17.3k]
  ------------------
  252|  49.7k|            return true;
  253|       |        /* Second is upper case alpha */
  254|  49.7k|        } else if ((in >= 65) & (in <= 90)) [[unlikely]] {
  ------------------
  |  Branch (254:20): [True: 2.24k, False: 15.1k]
  ------------------
  255|  2.24k|            in |= 32;
  256|  2.24k|            return true;
  257|       |        /* These are rarely used but still valid */
  258|  15.1k|        } else if (isUnlikelyFieldNameByte(in)) [[unlikely]] {
  ------------------
  |  Branch (258:20): [True: 5.90k, False: 9.21k]
  ------------------
  259|  5.90k|            return true;
  260|  5.90k|        }
  261|  9.21k|        return false;
  262|  67.0k|    }
_ZN3uWS10HttpParser23isUnlikelyFieldNameByteEh:
  243|  15.1k|    {
  244|       |        /* Digits and 14 of the 15 non-alphanum characters (lacking hyphen) */
  245|  15.1k|        return ((c == '~') | (c == '|') | (c == '`') | (c == '_') | (c == '^') | (c == '.') | (c == '+')
  ------------------
  |  Branch (245:16): [True: 2.69k, False: 12.4k]
  ------------------
  246|  15.1k|            | (c == '*') | (c == '!')) || ((c >= 48) & (c <= 57)) || ((c <= 39) & (c >= 35));
  ------------------
  |  Branch (246:43): [True: 2.92k, False: 9.50k]
  |  Branch (246:70): [True: 285, False: 9.21k]
  ------------------
  247|  15.1k|    }
_ZN3uWS10HttpParser20tryConsumeFieldValueEPc:
  325|   202k|    static inline void *tryConsumeFieldValue(char *p) {
  326|   536k|        for (; true; p += 8) {
  ------------------
  |  Branch (326:16): [Folded - Ignored]
  ------------------
  327|   536k|            uint64_t word;
  328|   536k|            memcpy(&word, p, sizeof(uint64_t));
  329|   536k|            if (hasLess(word, 32)) {
  ------------------
  |  Branch (329:17): [True: 202k, False: 333k]
  ------------------
  330|   450k|                while (*(unsigned char *)p > 31) p++;
  ------------------
  |  Branch (330:24): [True: 247k, False: 202k]
  ------------------
  331|   202k|                return (void *)p;
  332|   202k|            }
  333|   536k|        }
  334|   202k|    }
_ZN3uWS11HttpRequest9getHeaderENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
  115|   497k|    std::string_view getHeader(std::string_view lowerCasedHeader) {
  116|   497k|        if (bf.mightHave(lowerCasedHeader)) {
  ------------------
  |  Branch (116:13): [True: 131k, False: 366k]
  ------------------
  117|   239k|            for (Header *h = headers; (++h)->key.length(); ) {
  ------------------
  |  Branch (117:39): [True: 238k, False: 409]
  ------------------
  118|   238k|                if (h->key.length() == lowerCasedHeader.length() && !strncmp(h->key.data(), lowerCasedHeader.data(), lowerCasedHeader.length())) {
  ------------------
  |  Branch (118:21): [True: 132k, False: 105k]
  |  Branch (118:69): [True: 130k, False: 1.96k]
  ------------------
  119|   130k|                    return h->value;
  120|   130k|                }
  121|   238k|            }
  122|   131k|        }
  123|   366k|        return std::string_view(nullptr, 0);
  124|   497k|    }
_ZN3uWS10HttpParser17toUnsignedIntegerENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
  203|  4.00k|    static uint64_t toUnsignedInteger(std::string_view str) {
  204|       |        /* We assume at least 64-bit integer giving us safely 999999999999999999 (18 number of 9s) */
  205|  4.00k|        if (str.length() > 18) {
  ------------------
  |  Branch (205:13): [True: 536, False: 3.47k]
  ------------------
  206|    536|            return UINT64_MAX;
  207|    536|        }
  208|       |
  209|  3.47k|        uint64_t unsignedIntegerValue = 0;
  210|  13.5k|        for (char c : str) {
  ------------------
  |  Branch (210:21): [True: 13.5k, False: 2.84k]
  ------------------
  211|       |            /* As long as the letter is 0-9 we cannot overflow. */
  212|  13.5k|            if (c < '0' || c > '9') {
  ------------------
  |  Branch (212:17): [True: 116, False: 13.4k]
  |  Branch (212:28): [True: 515, False: 12.9k]
  ------------------
  213|    631|                return UINT64_MAX;
  214|    631|            }
  215|  12.9k|            unsignedIntegerValue = unsignedIntegerValue * 10ull + ((unsigned int) c - (unsigned int) '0');
  216|  12.9k|        }
  217|  2.84k|        return unsignedIntegerValue;
  218|  3.47k|    }
_ZN3uWS10HttpParser25fenceAndConsumePostPaddedILi0EEENSt3__14pairIjPvEEPcjS4_S4_PNS_11HttpRequestERN5ofats13any_invocableIFS4_S4_S8_EEERNSA_IFS4_S4_NS2_17basic_string_viewIcNS2_11char_traitsIcEEEEbEEE:
  448|   367k|    std::pair<unsigned int, void *> fenceAndConsumePostPadded(char *data, unsigned int length, void *user, void *reserved, HttpRequest *req, MoveOnlyFunction<void *(void *, HttpRequest *)> &requestHandler, MoveOnlyFunction<void *(void *, std::string_view, bool)> &dataHandler) {
  449|       |
  450|       |        /* How much data we CONSUMED (to throw away) */
  451|   367k|        unsigned int consumedTotal = 0;
  452|   367k|        unsigned int err = 0;
  453|       |
  454|       |        /* Fence two bytes past end of our buffer (buffer has post padded margins).
  455|       |         * This is to always catch scan for \r but not for \r\n. */
  456|   367k|        data[length] = '\r';
  457|   367k|        data[length + 1] = 'a'; /* Anything that is not \n, to trigger "invalid request" */
  458|       |
  459|   382k|        for (unsigned int consumed; length && (consumed = getHeaders(data, data + length, req->headers, reserved, err)); ) {
  ------------------
  |  Branch (459:37): [True: 346k, False: 36.8k]
  |  Branch (459:47): [True: 55.9k, False: 290k]
  ------------------
  460|  55.9k|            data += consumed;
  461|  55.9k|            length -= consumed;
  462|  55.9k|            consumedTotal += consumed;
  463|       |
  464|       |            /* Even if we could parse it, check for length here as well */
  465|  55.9k|            if (consumed > MAX_FALLBACK_SIZE) {
  ------------------
  |  Branch (465:17): [True: 0, False: 55.9k]
  ------------------
  466|      0|                return {HTTP_ERROR_431_REQUEST_HEADER_FIELDS_TOO_LARGE, FULLPTR};
  467|      0|            }
  468|       |
  469|       |            /* Store HTTP version (ancient 1.0 or 1.1) */
  470|  55.9k|            req->ancientHttp = false;
  471|       |
  472|       |            /* Add all headers to bloom filter */
  473|  55.9k|            req->bf.reset();
  474|   181k|            for (HttpRequest::Header *h = req->headers; (++h)->key.length(); ) {
  ------------------
  |  Branch (474:57): [True: 125k, False: 55.9k]
  ------------------
  475|   125k|                req->bf.add(h->key);
  476|   125k|            }
  477|       |            
  478|       |            /* Break if no host header (but we can have empty string which is different from nullptr) */
  479|  55.9k|            if (!req->getHeader("host").data()) {
  ------------------
  |  Branch (479:17): [True: 453, False: 55.5k]
  ------------------
  480|    453|                return {HTTP_ERROR_400_BAD_REQUEST, FULLPTR};
  481|    453|            }
  482|       |
  483|       |            /* RFC 9112 6.3
  484|       |            * If a message is received with both a Transfer-Encoding and a Content-Length header field,
  485|       |            * the Transfer-Encoding overrides the Content-Length. Such a message might indicate an attempt
  486|       |            * to perform request smuggling (Section 11.2) or response splitting (Section 11.1) and
  487|       |            * ought to be handled as an error. */
  488|  55.5k|            std::string_view transferEncodingString = req->getHeader("transfer-encoding");
  489|  55.5k|            std::string_view contentLengthString = req->getHeader("content-length");
  490|  55.5k|            if (transferEncodingString.length() && contentLengthString.length()) {
  ------------------
  |  Branch (490:17): [True: 2.49k, False: 53.0k]
  |  Branch (490:52): [True: 213, False: 2.28k]
  ------------------
  491|       |                /* Returning fullptr is the same as calling the errorHandler */
  492|       |                /* We could be smart and set an error in the context along with this, to indicate what 
  493|       |                 * http error response we might want to return */
  494|    213|                return {HTTP_ERROR_400_BAD_REQUEST, FULLPTR};
  495|    213|            }
  496|       |
  497|       |            /* Parse query */
  498|  55.3k|            const char *querySeparatorPtr = (const char *) memchr(req->headers->value.data(), '?', req->headers->value.length());
  499|  55.3k|            req->querySeparator = (unsigned int) ((querySeparatorPtr ? querySeparatorPtr : req->headers->value.data() + req->headers->value.length()) - req->headers->value.data());
  ------------------
  |  Branch (499:52): [True: 9.05k, False: 46.2k]
  ------------------
  500|       |
  501|       |            /* If returned socket is not what we put in we need
  502|       |             * to break here as we either have upgraded to
  503|       |             * WebSockets or otherwise closed the socket. */
  504|  55.3k|            void *returnedUser = requestHandler(user, req);
  505|  55.3k|            if (returnedUser != user) {
  ------------------
  |  Branch (505:17): [True: 39.1k, False: 16.1k]
  ------------------
  506|       |                /* We are upgraded to WebSocket or otherwise broken */
  507|  39.1k|                return {consumedTotal, returnedUser};
  508|  39.1k|            }
  509|       |
  510|       |            /* The rules at play here according to RFC 9112 for requests are essentially:
  511|       |             * If both content-length and transfer-encoding then invalid message; must break.
  512|       |             * If has transfer-encoding then must be chunked regardless of value.
  513|       |             * If content-length then fixed length even if 0.
  514|       |             * If none of the above then fixed length is 0. */
  515|       |
  516|       |            /* RFC 9112 6.3
  517|       |             * If a message is received with both a Transfer-Encoding and a Content-Length header field,
  518|       |             * the Transfer-Encoding overrides the Content-Length. */
  519|  16.1k|            if (transferEncodingString.length()) {
  ------------------
  |  Branch (519:17): [True: 2.28k, False: 13.8k]
  ------------------
  520|       |
  521|       |                /* If a proxy sent us the transfer-encoding header that 100% means it must be chunked or else the proxy is
  522|       |                 * not RFC 9112 compliant. Therefore it is always better to assume this is the case, since that entirely eliminates 
  523|       |                 * all forms of transfer-encoding obfuscation tricks. We just rely on the header. */
  524|       |
  525|       |                /* RFC 9112 6.3
  526|       |                 * If a Transfer-Encoding header field is present in a request and the chunked transfer coding is not the
  527|       |                 * final encoding, the message body length cannot be determined reliably; the server MUST respond with the
  528|       |                 * 400 (Bad Request) status code and then close the connection. */
  529|       |
  530|       |                /* In this case we fail later by having the wrong interpretation (assuming chunked).
  531|       |                 * This could be made stricter but makes no difference either way, unless forwarding the identical message as a proxy. */
  532|       |
  533|  2.28k|                remainingStreamingBytes = STATE_IS_CHUNKED;
  534|       |                /* If consume minimally, we do not want to consume anything but we want to mark this as being chunked */
  535|  2.28k|                if (!CONSUME_MINIMALLY) {
  ------------------
  |  Branch (535:21): [Folded - Ignored]
  ------------------
  536|       |                    /* Go ahead and parse it (todo: better heuristics for emitting FIN to the app level) */
  537|  2.28k|                    std::string_view dataToConsume(data, length);
  538|  2.28k|                    for (auto chunk : uWS::ChunkIterator(&dataToConsume, &remainingStreamingBytes)) {
  ------------------
  |  Branch (538:37): [True: 1.87k, False: 2.28k]
  ------------------
  539|  1.87k|                        dataHandler(user, chunk, chunk.length() == 0);
  540|  1.87k|                    }
  541|  2.28k|                    if (isParsingInvalidChunkedEncoding(remainingStreamingBytes)) {
  ------------------
  |  Branch (541:25): [True: 430, False: 1.85k]
  ------------------
  542|    430|                        return {HTTP_ERROR_400_BAD_REQUEST, FULLPTR};
  543|    430|                    }
  544|  1.85k|                    unsigned int consumed = (length - (unsigned int) dataToConsume.length());
  545|  1.85k|                    data = (char *) dataToConsume.data();
  546|  1.85k|                    length = (unsigned int) dataToConsume.length();
  547|  1.85k|                    consumedTotal += consumed;
  548|  1.85k|                }
  549|  13.8k|            } else if (contentLengthString.length()) {
  ------------------
  |  Branch (549:24): [True: 2.29k, False: 11.5k]
  ------------------
  550|  2.29k|                remainingStreamingBytes = toUnsignedInteger(contentLengthString);
  551|  2.29k|                if (remainingStreamingBytes == UINT64_MAX) {
  ------------------
  |  Branch (551:21): [True: 707, False: 1.59k]
  ------------------
  552|       |                    /* Parser error */
  553|    707|                    return {HTTP_ERROR_400_BAD_REQUEST, FULLPTR};
  554|    707|                }
  555|       |
  556|  1.59k|                if (!CONSUME_MINIMALLY) {
  ------------------
  |  Branch (556:21): [Folded - Ignored]
  ------------------
  557|  1.59k|                    unsigned int emittable = (unsigned int) std::min<uint64_t>(remainingStreamingBytes, length);
  558|  1.59k|                    dataHandler(user, std::string_view(data, emittable), emittable == remainingStreamingBytes);
  559|  1.59k|                    remainingStreamingBytes -= emittable;
  560|       |
  561|  1.59k|                    data += emittable;
  562|  1.59k|                    length -= emittable;
  563|  1.59k|                    consumedTotal += emittable;
  564|  1.59k|                }
  565|  11.5k|            } else {
  566|       |                /* If we came here without a body; emit an empty data chunk to signal no data */
  567|  11.5k|                dataHandler(user, {}, true);
  568|  11.5k|            }
  569|       |
  570|       |            /* Consume minimally should break as easrly as possible */
  571|  14.9k|            if (CONSUME_MINIMALLY) {
  ------------------
  |  Branch (571:17): [Folded - Ignored]
  ------------------
  572|      0|                break;
  573|      0|            }
  574|  14.9k|        }
  575|       |        /* Whenever we return FULLPTR, the interpretation of "consumed" should be the HttpError enum. */
  576|   326k|        if (err) {
  ------------------
  |  Branch (576:13): [True: 280k, False: 46.4k]
  ------------------
  577|   280k|            return {err, FULLPTR};
  578|   280k|        }
  579|  46.4k|        return {consumedTotal, user};
  580|   326k|    }
_ZN3uWS11HttpRequest9isAncientEv:
   72|  60.2k|    bool isAncient() {
   73|  60.2k|        return ancientHttp;
   74|  60.2k|    }
_ZN3uWS11HttpRequest22getCaseSensitiveMethodEv:
  135|  60.2k|    std::string_view getCaseSensitiveMethod() {
  136|  60.2k|        return std::string_view(headers->key.data(), headers->key.length());
  137|  60.2k|    }
_ZN3uWS11HttpRequest6getUrlEv:
  126|  60.2k|    std::string_view getUrl() {
  127|  60.2k|        return std::string_view(headers->value.data(), querySeparator);
  128|  60.2k|    }
_ZN3uWS11HttpRequest8setYieldEb:
  111|  81.6k|    void setYield(bool yield) {
  112|  81.6k|        didYield = yield;
  113|  81.6k|    }
_ZN3uWS11HttpRequest13setParametersENSt3__14pairIiPNS1_17basic_string_viewIcNS1_11char_traitsIcEEEEEE:
  166|  70.9k|    void setParameters(std::pair<int, std::string_view *> parameters) {
  167|  70.9k|        currentParameters = parameters;
  168|  70.9k|    }
_ZN3uWS11HttpRequest19setParameterOffsetsEPNSt3__13mapINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEtNS1_4lessIvEENS6_INS1_4pairIKS8_tEEEEEE:
  170|  70.9k|    void setParameterOffsets(std::map<std::string, unsigned short, std::less<>> *offsets) {
  171|  70.9k|        currentParameterOffsets = offsets;
  172|  70.9k|    }
_ZN3uWS11HttpRequest8getYieldEv:
   76|  70.9k|    bool getYield() {
   77|  70.9k|        return didYield;
   78|  70.9k|    }
_ZN3uWS11HttpRequest8getQueryEv:
  149|  11.0k|    std::string_view getQuery() {
  150|  11.0k|        if (querySeparator < headers->value.length()) {
  ------------------
  |  Branch (150:13): [True: 3.82k, False: 7.24k]
  ------------------
  151|       |            /* Strip the initial ? */
  152|  3.82k|            return std::string_view(headers->value.data() + querySeparator + 1, headers->value.length() - querySeparator - 1);
  153|  7.24k|        } else {
  154|  7.24k|            return std::string_view(nullptr, 0);
  155|  7.24k|        }
  156|  11.0k|    }
_ZN3uWS11HttpRequest12getParameterEt:
  185|  6.06k|    std::string_view getParameter(unsigned short index) {
  186|  6.06k|        if (currentParameters.first < (int) index) {
  ------------------
  |  Branch (186:13): [True: 4.04k, False: 2.02k]
  ------------------
  187|  4.04k|            return {};
  188|  4.04k|        } else {
  189|  2.02k|            return currentParameters.second[index];
  190|  2.02k|        }
  191|  6.06k|    }
_ZN3uWS11HttpRequest8getQueryENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
  159|  2.02k|    std::string_view getQuery(std::string_view key) {
  160|       |        /* Raw querystring including initial '?' sign */
  161|  2.02k|        std::string_view queryString = std::string_view(headers->value.data() + querySeparator, headers->value.length() - querySeparator);
  162|       |
  163|  2.02k|        return getDecodedQueryValue(key, queryString);
  164|  2.02k|    }

_ZN3uWS12HttpResponseILb0EE12hasRespondedEv:
  490|  38.2k|    bool hasResponded() {
  491|  38.2k|        HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
  492|       |
  493|  38.2k|        return !(httpResponseData->state & HttpResponseData<SSL>::HTTP_RESPONSE_PENDING);
  494|  38.2k|    }
_ZN3uWS12HttpResponseILb0EE19getHttpResponseDataEv:
   52|   541k|    HttpResponseData<SSL> *getHttpResponseData() {
   53|   541k|        return (HttpResponseData<SSL> *) Super::getAsyncSocketData();
   54|   541k|    }
_ZN3uWS12HttpResponseILb0EE11writeStatusENSt3__117basic_string_viewIcNS2_11char_traitsIcEEEE:
  383|   352k|    HttpResponse *writeStatus(std::string_view status) {
  384|   352k|        HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
  385|       |
  386|       |        /* Do not allow writing more than one status */
  387|   352k|        if (httpResponseData->state & HttpResponseData<SSL>::HTTP_STATUS_CALLED) {
  ------------------
  |  Branch (387:13): [True: 293k, False: 58.1k]
  ------------------
  388|   293k|            return this;
  389|   293k|        }
  390|       |
  391|       |        /* Update status */
  392|  58.1k|        httpResponseData->state |= HttpResponseData<SSL>::HTTP_STATUS_CALLED;
  393|       |
  394|  58.1k|        Super::write("HTTP/1.1 ", 9);
  395|  58.1k|        Super::write(status.data(), (int) status.length());
  396|  58.1k|        Super::write("\r\n", 2);
  397|  58.1k|        return this;
  398|   352k|    }
_ZN3uWS12HttpResponseILb0EE3endENSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEb:
  432|  17.9k|    void end(std::string_view data = {}, bool closeConnection = false) {
  433|  17.9k|        internalEnd(data, data.length(), false, true, closeConnection);
  434|  17.9k|    }
_ZN3uWS12HttpResponseILb0EE11internalEndENSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEmbbb:
   92|  58.1k|    bool internalEnd(std::string_view data, uintmax_t totalSize, bool optional, bool allowContentLength = true, bool closeConnection = false) {
   93|       |        /* Write status if not already done */
   94|  58.1k|        writeStatus(HTTP_200_OK);
   95|       |
   96|       |        /* If no total size given then assume this chunk is everything */
   97|  58.1k|        if (!totalSize) {
  ------------------
  |  Branch (97:13): [True: 43.3k, False: 14.7k]
  ------------------
   98|  43.3k|            totalSize = data.length();
   99|  43.3k|        }
  100|       |
  101|  58.1k|        HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
  102|       |
  103|       |        /* In some cases, such as when refusing huge data we want to close the connection when drained */
  104|  58.1k|        if (closeConnection) {
  ------------------
  |  Branch (104:13): [True: 0, False: 58.1k]
  ------------------
  105|       |
  106|       |            /* HTTP 1.1 must send this back unless the client already sent it to us.
  107|       |             * It is a connection close when either of the two parties say so but the
  108|       |             * one party must tell the other one so.
  109|       |             *
  110|       |             * This check also serves to limit writing the header only once. */
  111|      0|            if ((httpResponseData->state & HttpResponseData<SSL>::HTTP_CONNECTION_CLOSE) == 0) {
  ------------------
  |  Branch (111:17): [True: 0, False: 0]
  ------------------
  112|      0|                writeHeader("Connection", "close");
  113|      0|            }
  114|       |
  115|      0|            httpResponseData->state |= HttpResponseData<SSL>::HTTP_CONNECTION_CLOSE;
  116|      0|        }
  117|       |
  118|  58.1k|        if (httpResponseData->state & HttpResponseData<SSL>::HTTP_WRITE_CALLED) {
  ------------------
  |  Branch (118:13): [True: 3.83k, False: 54.2k]
  ------------------
  119|       |
  120|       |            /* We do not have tryWrite-like functionalities, so ignore optional in this path */
  121|       |
  122|       |            /* Do not allow sending 0 chunk here */
  123|  3.83k|            if (data.length()) {
  ------------------
  |  Branch (123:17): [True: 617, False: 3.21k]
  ------------------
  124|    617|                Super::write("\r\n", 2);
  125|    617|                writeUnsignedHex((unsigned int) data.length());
  126|    617|                Super::write("\r\n", 2);
  127|       |
  128|       |                /* Ignoring optional for now */
  129|    617|                Super::write(data.data(), (int) data.length());
  130|    617|            }
  131|       |
  132|       |            /* Terminating 0 chunk */
  133|  3.83k|            Super::write("\r\n0\r\n\r\n", 7);
  134|       |
  135|  3.83k|            httpResponseData->markDone();
  136|       |
  137|       |            /* We need to check if we should close this socket here now */
  138|  3.83k|            if (!Super::isCorked()) {
  ------------------
  |  Branch (138:17): [True: 0, False: 3.83k]
  ------------------
  139|      0|                if (httpResponseData->state & HttpResponseData<SSL>::HTTP_CONNECTION_CLOSE) {
  ------------------
  |  Branch (139:21): [True: 0, False: 0]
  ------------------
  140|      0|                    if ((httpResponseData->state & HttpResponseData<SSL>::HTTP_RESPONSE_PENDING) == 0) {
  ------------------
  |  Branch (140:25): [True: 0, False: 0]
  ------------------
  141|      0|                        if (((AsyncSocket<SSL> *) this)->getBufferedAmount() == 0) {
  ------------------
  |  Branch (141:29): [True: 0, False: 0]
  ------------------
  142|      0|                            ((AsyncSocket<SSL> *) this)->shutdown();
  143|       |                            /* We need to force close after sending FIN since we want to hinder
  144|       |                                * clients from keeping to send their huge data */
  145|      0|                            ((AsyncSocket<SSL> *) this)->close();
  146|      0|                            return true;
  147|      0|                        }
  148|      0|                    }
  149|      0|                }
  150|      0|            }
  151|       |
  152|       |            /* tryEnd can never fail when in chunked mode, since we do not have tryWrite (yet), only write */
  153|  3.83k|            Super::timeout(HTTP_TIMEOUT_S);
  154|  3.83k|            return true;
  155|  54.2k|        } else {
  156|       |            /* Write content-length on first call */
  157|  54.2k|            if (!(httpResponseData->state & HttpResponseData<SSL>::HTTP_END_CALLED)) {
  ------------------
  |  Branch (157:17): [True: 54.2k, False: 0]
  ------------------
  158|       |                /* Write mark, this propagates to WebSockets too */
  159|  54.2k|                writeMark();
  160|       |
  161|       |                /* WebSocket upgrades does not allow content-length */
  162|  54.2k|                if (allowContentLength) {
  ------------------
  |  Branch (162:21): [True: 14.1k, False: 40.1k]
  ------------------
  163|       |                    /* Even zero is a valid content-length */
  164|  14.1k|                    Super::write("Content-Length: ", 16);
  165|  14.1k|                    writeUnsigned64(totalSize);
  166|  14.1k|                    Super::write("\r\n\r\n", 4);
  167|  40.1k|                } else {
  168|  40.1k|                    Super::write("\r\n", 2);
  169|  40.1k|                }
  170|       |
  171|       |                /* Mark end called */
  172|  54.2k|                httpResponseData->state |= HttpResponseData<SSL>::HTTP_END_CALLED;
  173|  54.2k|            }
  174|       |
  175|       |            /* Even if we supply no new data to write, its failed boolean is useful to know
  176|       |             * if it failed to drain any prior failed header writes */
  177|       |
  178|       |            /* Write as much as possible without causing backpressure */
  179|  54.2k|            size_t written = 0;
  180|  54.2k|            bool failed = false;
  181|  68.4k|            while (written < data.length() && !failed) {
  ------------------
  |  Branch (181:20): [True: 14.1k, False: 54.2k]
  |  Branch (181:47): [True: 14.1k, False: 0]
  ------------------
  182|       |                /* uSockets only deals with int sizes, so pass chunks of max signed int size */
  183|  14.1k|                auto writtenFailed = Super::write(data.data() + written, (int) std::min<size_t>(data.length() - written, INT_MAX), optional);
  184|       |
  185|  14.1k|                written += (size_t) writtenFailed.first;
  186|  14.1k|                failed = writtenFailed.second;
  187|  14.1k|            }
  188|       |
  189|  54.2k|            httpResponseData->offset += written;
  190|       |
  191|       |            /* Success is when we wrote the entire thing without any failures */
  192|  54.2k|            bool success = written == data.length() && !failed;
  ------------------
  |  Branch (192:28): [True: 54.2k, False: 0]
  |  Branch (192:56): [True: 53.8k, False: 482]
  ------------------
  193|       |
  194|       |            /* If we are now at the end, start a timeout. Also start a timeout if we failed. */
  195|  54.2k|            if (!success || httpResponseData->offset == totalSize) {
  ------------------
  |  Branch (195:17): [True: 482, False: 53.8k]
  |  Branch (195:29): [True: 53.8k, False: 0]
  ------------------
  196|  54.2k|                Super::timeout(HTTP_TIMEOUT_S);
  197|  54.2k|            }
  198|       |
  199|       |            /* Remove onAborted function if we reach the end */
  200|  54.2k|            if (httpResponseData->offset == totalSize) {
  ------------------
  |  Branch (200:17): [True: 54.2k, False: 0]
  ------------------
  201|  54.2k|                httpResponseData->markDone();
  202|       |
  203|       |                /* We need to check if we should close this socket here now */
  204|  54.2k|                if (!Super::isCorked()) {
  ------------------
  |  Branch (204:21): [True: 0, False: 54.2k]
  ------------------
  205|      0|                    if (httpResponseData->state & HttpResponseData<SSL>::HTTP_CONNECTION_CLOSE) {
  ------------------
  |  Branch (205:25): [True: 0, False: 0]
  ------------------
  206|      0|                        if ((httpResponseData->state & HttpResponseData<SSL>::HTTP_RESPONSE_PENDING) == 0) {
  ------------------
  |  Branch (206:29): [True: 0, False: 0]
  ------------------
  207|      0|                            if (((AsyncSocket<SSL> *) this)->getBufferedAmount() == 0) {
  ------------------
  |  Branch (207:33): [True: 0, False: 0]
  ------------------
  208|      0|                                ((AsyncSocket<SSL> *) this)->shutdown();
  209|       |                                /* We need to force close after sending FIN since we want to hinder
  210|       |                                * clients from keeping to send their huge data */
  211|      0|                                ((AsyncSocket<SSL> *) this)->close();
  212|      0|                            }
  213|      0|                        }
  214|      0|                    }
  215|      0|                }
  216|  54.2k|            }
  217|       |
  218|  54.2k|            return success;
  219|  54.2k|        }
  220|  58.1k|    }
_ZN3uWS12HttpResponseILb0EE11writeHeaderENSt3__117basic_string_viewIcNS2_11char_traitsIcEEEES6_:
  401|   244k|    HttpResponse *writeHeader(std::string_view key, std::string_view value) {
  402|   244k|        writeStatus(HTTP_200_OK);
  403|       |
  404|   244k|        Super::write(key.data(), (int) key.length());
  405|   244k|        Super::write(": ", 2);
  406|   244k|        Super::write(value.data(), (int) value.length());
  407|   244k|        Super::write("\r\n", 2);
  408|   244k|        return this;
  409|   244k|    }
_ZN3uWS12HttpResponseILb0EE16writeUnsignedHexEj:
   57|  5.15k|    void writeUnsignedHex(unsigned int value) {
   58|       |        /* Buf really only needs to be 8 long but building with
   59|       |         * -mavx2, GCC still wants to overstep it so made it 16 */
   60|  5.15k|        char buf[16];
   61|  5.15k|        int length = utils::u32toaHex(value, buf);
   62|       |
   63|       |        /* For now we do this copy */
   64|  5.15k|        Super::write(buf, length);
   65|  5.15k|    }
_ZN3uWS12HttpResponseILb0EE9writeMarkEv:
   77|  58.1k|    void writeMark() {
   78|       |        /* Date is always written */
   79|  58.1k|        writeHeader("Date", std::string_view(((LoopData *) us_loop_ext(us_socket_context_loop(SSL, (us_socket_context(SSL, (us_socket_t *) this)))))->date, 29));
   80|       |
   81|       |        /* You can disable this altogether */
   82|  58.1k|#ifndef UWS_HTTPRESPONSE_NO_WRITEMARK
   83|  58.1k|        if (!Super::getLoopData()->noMark) {
  ------------------
  |  Branch (83:13): [True: 58.1k, False: 0]
  ------------------
   84|       |            /* We only expose major version */
   85|  58.1k|            writeHeader("uWebSockets", "20");
   86|  58.1k|        }
   87|  58.1k|#endif
   88|  58.1k|    }
_ZN3uWS12HttpResponseILb0EE15writeUnsigned64Em:
   68|  14.1k|    void writeUnsigned64(uint64_t value) {
   69|  14.1k|        char buf[20];
   70|  14.1k|        int length = utils::u64toa(value, buf);
   71|       |
   72|       |        /* For now we do this copy */
   73|  14.1k|        Super::write(buf, length);
   74|  14.1k|    }
_ZN3uWS12HttpResponseILb0EE13writeContinueEv:
  377|    212|    HttpResponse *writeContinue() {
  378|    212|        Super::write("HTTP/1.1 100 Continue\r\n\r\n", 25);
  379|    212|        return this;
  380|    212|    }
EpollHelloWorld.cpp:_ZN3uWS12HttpResponseILb0EE7upgradeIZ4testvE13PerSocketDataEEvOT_NSt3__117basic_string_viewIcNS6_11char_traitsIcEEEESA_SA_P19us_socket_context_t:
  239|  40.1k|            struct us_socket_context_t *webSocketContext) {
  240|       |
  241|       |        /* Extract needed parameters from WebSocketContextData */
  242|  40.1k|        WebSocketContextData<SSL, UserData> *webSocketContextData = (WebSocketContextData<SSL, UserData> *) us_socket_context_ext(SSL, webSocketContext);
  243|       |
  244|       |        /* Note: OpenSSL can be used here to speed this up somewhat */
  245|  40.1k|        char secWebSocketAccept[29] = {};
  246|  40.1k|        WebSocketHandshake::generate(secWebSocketKey.data(), secWebSocketAccept);
  247|       |
  248|  40.1k|        writeStatus("101 Switching Protocols")
  249|  40.1k|            ->writeHeader("Upgrade", "websocket")
  250|  40.1k|            ->writeHeader("Connection", "Upgrade")
  251|  40.1k|            ->writeHeader("Sec-WebSocket-Accept", secWebSocketAccept);
  252|       |
  253|       |        /* Select first subprotocol if present */
  254|  40.1k|        if (secWebSocketProtocol.length()) {
  ------------------
  |  Branch (254:13): [True: 402, False: 39.7k]
  ------------------
  255|    402|            writeHeader("Sec-WebSocket-Protocol", secWebSocketProtocol.substr(0, secWebSocketProtocol.find(',')));
  256|    402|        }
  257|       |
  258|       |        /* Negotiate compression */
  259|  40.1k|        bool perMessageDeflate = false;
  260|  40.1k|        CompressOptions compressOptions = CompressOptions::DISABLED;
  261|  40.1k|        if (secWebSocketExtensions.length() && webSocketContextData->compression != DISABLED) {
  ------------------
  |  Branch (261:13): [True: 4.89k, False: 35.2k]
  |  Branch (261:48): [True: 4.69k, False: 194]
  ------------------
  262|       |
  263|       |            /* Make sure to map SHARED_DECOMPRESSOR to windowBits = 0, not 1  */
  264|  4.69k|            int wantedInflationWindow = 0;
  265|  4.69k|            if ((webSocketContextData->compression & CompressOptions::_DECOMPRESSOR_MASK) != CompressOptions::SHARED_DECOMPRESSOR) {
  ------------------
  |  Branch (265:17): [True: 4.69k, False: 0]
  ------------------
  266|  4.69k|                wantedInflationWindow = (webSocketContextData->compression & CompressOptions::_DECOMPRESSOR_MASK) >> 8;
  267|  4.69k|            }
  268|       |
  269|       |            /* Map from selected compressor (this automatically maps SHARED_COMPRESSOR to windowBits 0, not 1) */
  270|  4.69k|            int wantedCompressionWindow = (webSocketContextData->compression & CompressOptions::_COMPRESSOR_MASK) >> 4;
  271|       |
  272|  4.69k|            auto [negCompression, negCompressionWindow, negInflationWindow, negResponse] =
  273|  4.69k|            negotiateCompression(true, wantedCompressionWindow, wantedInflationWindow,
  274|  4.69k|                                        secWebSocketExtensions);
  275|       |
  276|  4.69k|            if (negCompression) {
  ------------------
  |  Branch (276:17): [True: 2.87k, False: 1.82k]
  ------------------
  277|  2.87k|                perMessageDeflate = true;
  278|       |
  279|       |                /* Map from negotiated windowBits to compressor and decompressor */
  280|  2.87k|                if (negCompressionWindow == 0) {
  ------------------
  |  Branch (280:21): [True: 2.87k, False: 0]
  ------------------
  281|  2.87k|                    compressOptions = CompressOptions::SHARED_COMPRESSOR;
  282|  2.87k|                } else {
  283|      0|                    compressOptions = (CompressOptions) ((uint32_t) (negCompressionWindow << 4)
  284|      0|                                                        | (uint32_t) (negCompressionWindow - 7));
  285|       |
  286|       |                    /* If we are dedicated and have the 3kb then correct any 4kb to 3kb,
  287|       |                     * (they both share the windowBits = 9) */
  288|      0|                    if (webSocketContextData->compression & DEDICATED_COMPRESSOR_3KB) {
  ------------------
  |  Branch (288:25): [True: 0, False: 0]
  ------------------
  289|      0|                        compressOptions = DEDICATED_COMPRESSOR_3KB;
  290|      0|                    }
  291|      0|                }
  292|       |
  293|       |                /* Here we modify the above compression with negotiated decompressor */
  294|  2.87k|                if (negInflationWindow == 0) {
  ------------------
  |  Branch (294:21): [True: 2.87k, False: 0]
  ------------------
  295|  2.87k|                    compressOptions = CompressOptions(compressOptions | CompressOptions::SHARED_DECOMPRESSOR);
  296|  2.87k|                } else {
  297|      0|                    compressOptions = CompressOptions(compressOptions | (negInflationWindow << 8));
  298|      0|                }
  299|       |
  300|  2.87k|                writeHeader("Sec-WebSocket-Extensions", negResponse);
  301|  2.87k|            }
  302|  4.69k|        }
  303|       |
  304|  40.1k|        internalEnd({nullptr, 0}, 0, false, false);
  305|       |
  306|       |        /* Grab the httpContext from res */
  307|  40.1k|        HttpContext<SSL> *httpContext = (HttpContext<SSL> *) us_socket_context(SSL, (struct us_socket_t *) this);
  308|       |
  309|       |        /* Move any backpressure out of HttpResponse */
  310|  40.1k|        BackPressure backpressure(std::move(((AsyncSocketData<SSL> *) getHttpResponseData())->buffer));
  311|       |
  312|       |        /* Destroy HttpResponseData */
  313|  40.1k|        getHttpResponseData()->~HttpResponseData();
  314|       |
  315|       |        /* Before we adopt and potentially change socket, check if we are corked */
  316|  40.1k|        bool wasCorked = Super::isCorked();
  317|       |
  318|       |        /* Adopting a socket invalidates it, do not rely on it directly to carry any data */
  319|  40.1k|        WebSocket<SSL, true, UserData> *webSocket = (WebSocket<SSL, true, UserData> *) us_socket_context_adopt_socket(SSL,
  320|  40.1k|                    (us_socket_context_t *) webSocketContext, (us_socket_t *) this, sizeof(WebSocketData) + sizeof(UserData));
  321|       |
  322|       |        /* For whatever reason we were corked, update cork to the new socket */
  323|  40.1k|        if (wasCorked) {
  ------------------
  |  Branch (323:13): [True: 40.1k, False: 0]
  ------------------
  324|  40.1k|            webSocket->AsyncSocket<SSL>::corkUnchecked();
  325|  40.1k|        }
  326|       |
  327|       |        /* Initialize websocket with any moved backpressure intact */
  328|  40.1k|        webSocket->init(perMessageDeflate, compressOptions, std::move(backpressure));
  329|       |
  330|       |        /* We should only mark this if inside the parser; if upgrading "async" we cannot set this */
  331|  40.1k|        HttpContextData<SSL> *httpContextData = httpContext->getSocketContextData();
  332|  40.1k|        if (httpContextData->isParsingHttp) {
  ------------------
  |  Branch (332:13): [True: 40.1k, False: 0]
  ------------------
  333|       |            /* We need to tell the Http parser that we changed socket */
  334|  40.1k|            httpContextData->upgradedWebSocket = webSocket;
  335|  40.1k|        }
  336|       |
  337|       |        /* Arm maxLifetime timeout */
  338|  40.1k|        us_socket_long_timeout(SSL, (us_socket_t *) webSocket, webSocketContextData->maxLifetime);
  339|       |
  340|       |        /* Arm idleTimeout */
  341|  40.1k|        us_socket_timeout(SSL, (us_socket_t *) webSocket, webSocketContextData->idleTimeoutComponents.first);
  342|       |
  343|       |        /* Move construct the UserData right before calling open handler */
  344|  40.1k|        new (webSocket->getUserData()) UserData(std::move(userData));
  345|       |
  346|       |        /* Emit open event and start the timeout */
  347|  40.1k|        if (webSocketContextData->openHandler) {
  ------------------
  |  Branch (347:13): [True: 39.0k, False: 1.08k]
  ------------------
  348|  39.0k|            webSocketContextData->openHandler(webSocket);
  349|  39.0k|        }
  350|  40.1k|    }
_ZN3uWS12HttpResponseILb0EE5writeENSt3__117basic_string_viewIcNS2_11char_traitsIcEEEE:
  443|  4.53k|    bool write(std::string_view data) {
  444|  4.53k|        writeStatus(HTTP_200_OK);
  445|       |
  446|       |        /* Do not allow sending 0 chunks, they mark end of response */
  447|  4.53k|        if (!data.length()) {
  ------------------
  |  Branch (447:13): [True: 0, False: 4.53k]
  ------------------
  448|       |            /* If you called us, then according to you it was fine to call us so it's fine to still call us */
  449|      0|            return true;
  450|      0|        }
  451|       |
  452|  4.53k|        HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
  453|       |
  454|  4.53k|        if (!(httpResponseData->state & HttpResponseData<SSL>::HTTP_WRITE_CALLED)) {
  ------------------
  |  Branch (454:13): [True: 3.83k, False: 699]
  ------------------
  455|       |            /* Write mark on first call to write */
  456|  3.83k|            writeMark();
  457|       |
  458|  3.83k|            writeHeader("Transfer-Encoding", "chunked");
  459|  3.83k|            httpResponseData->state |= HttpResponseData<SSL>::HTTP_WRITE_CALLED;
  460|  3.83k|        }
  461|       |
  462|  4.53k|        Super::write("\r\n", 2);
  463|  4.53k|        writeUnsignedHex((unsigned int) data.length());
  464|  4.53k|        Super::write("\r\n", 2);
  465|       |
  466|  4.53k|        auto [written, failed] = Super::write(data.data(), (int) data.length());
  467|  4.53k|        if (failed) {
  ------------------
  |  Branch (467:13): [True: 369, False: 4.16k]
  ------------------
  468|    369|            Super::timeout(HTTP_TIMEOUT_S);
  469|    369|        }
  470|       |
  471|       |        /* If we did not fail the write, accept more */
  472|  4.53k|        return !failed;
  473|  4.53k|    }
_ZN3uWS12HttpResponseILb0EE9onAbortedEON5ofats13any_invocableIFvvEEE:
  559|  4.29k|    HttpResponse *onAborted(MoveOnlyFunction<void()> &&handler) {
  560|  4.29k|        HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
  561|       |
  562|  4.29k|        httpResponseData->onAborted = std::move(handler);
  563|  4.29k|        return this;
  564|  4.29k|    }
_ZN3uWS12HttpResponseILb0EE6onDataEON5ofats13any_invocableIFvNSt3__117basic_string_viewIcNS4_11char_traitsIcEEEEbEEE:
  567|  4.29k|    void onData(MoveOnlyFunction<void(std::string_view, bool)> &&handler) {
  568|  4.29k|        HttpResponseData<SSL> *data = getHttpResponseData();
  569|  4.29k|        data->inStream = std::move(handler);
  570|       |
  571|       |        /* Always reset this counter here */
  572|  4.29k|        data->received_bytes_per_timeout = 0;
  573|  4.29k|    }
_ZN3uWS12HttpResponseILb0EE4corkEON5ofats13any_invocableIFvvEEE:
  497|  3.13k|    HttpResponse *cork(MoveOnlyFunction<void()> &&handler) {
  498|  3.13k|        if (!Super::isCorked() && Super::canCork()) {
  ------------------
  |  Branch (498:13): [True: 0, False: 3.13k]
  |  Branch (498:35): [True: 0, False: 0]
  ------------------
  499|      0|            LoopData *loopData = Super::getLoopData();
  500|      0|            Super::cork();
  501|      0|            handler();
  502|       |
  503|       |            /* The only way we could possibly have changed the corked socket during handler call, would be if 
  504|       |             * the HTTP socket was upgraded to WebSocket and caused a realloc. Because of this we cannot use "this"
  505|       |             * from here downwards. The corking is done with corkUnchecked() in upgrade. It steals cork. */
  506|      0|            auto *newCorkedSocket = loopData->corkedSocket;
  507|       |
  508|       |            /* If nobody is corked, it means most probably that large amounts of data has
  509|       |             * been written and the cork buffer has already been sent off and uncorked.
  510|       |             * We are done here, if that is the case. */
  511|      0|            if (!newCorkedSocket) {
  ------------------
  |  Branch (511:17): [True: 0, False: 0]
  ------------------
  512|      0|                return this;
  513|      0|            }
  514|       |
  515|       |            /* Timeout on uncork failure, since most writes will succeed while corked */
  516|      0|            auto [written, failed] = static_cast<Super *>(newCorkedSocket)->uncork();
  517|       |
  518|       |            /* If we are no longer an HTTP socket then early return the new "this".
  519|       |             * We don't want to even overwrite timeout as it is set in upgrade already. */
  520|      0|            if (this != newCorkedSocket) {
  ------------------
  |  Branch (520:17): [True: 0, False: 0]
  ------------------
  521|      0|                return static_cast<HttpResponse *>(newCorkedSocket);
  522|      0|            }
  523|       |
  524|      0|            if (failed) {
  ------------------
  |  Branch (524:17): [True: 0, False: 0]
  ------------------
  525|       |                /* For now we only have one single timeout so let's use it */
  526|       |                /* This behavior should equal the behavior in HttpContext when uncorking fails */
  527|      0|                Super::timeout(HTTP_TIMEOUT_S);
  528|      0|            }
  529|       |
  530|       |            /* If we have no backbuffer and we are connection close and we responded fully then close */
  531|      0|            HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
  532|      0|            if (httpResponseData->state & HttpResponseData<SSL>::HTTP_CONNECTION_CLOSE) {
  ------------------
  |  Branch (532:17): [True: 0, False: 0]
  ------------------
  533|      0|                if ((httpResponseData->state & HttpResponseData<SSL>::HTTP_RESPONSE_PENDING) == 0) {
  ------------------
  |  Branch (533:21): [True: 0, False: 0]
  ------------------
  534|      0|                    if (((AsyncSocket<SSL> *) this)->getBufferedAmount() == 0) {
  ------------------
  |  Branch (534:25): [True: 0, False: 0]
  ------------------
  535|      0|                        ((AsyncSocket<SSL> *) this)->shutdown();
  536|       |                        /* We need to force close after sending FIN since we want to hinder
  537|       |                        * clients from keeping to send their huge data */
  538|      0|                        ((AsyncSocket<SSL> *) this)->close();
  539|      0|                    }
  540|      0|                }
  541|      0|            }
  542|  3.13k|        } else {
  543|       |            /* We are already corked, or can't cork so let's just call the handler */
  544|  3.13k|            handler();
  545|  3.13k|        }
  546|       |
  547|  3.13k|        return this;
  548|  3.13k|    }

_ZN3uWS16HttpResponseDataILb0EE8markDoneEv:
   37|  58.1k|    void markDone() {
   38|  58.1k|        onAborted = nullptr;
   39|       |        /* Also remove onWritable so that we do not emit when draining behind the scenes. */
   40|  58.1k|        onWritable = nullptr;
   41|       |
   42|       |        /* We are done with this request */
   43|  58.1k|        state &= ~HttpResponseData<SSL>::HTTP_RESPONSE_PENDING;
   44|  58.1k|    }

_ZN3uWS10HttpRouterINS_15HttpContextDataILb0EE10RouterDataEEC2Ev:
  243|  6.41k|    HttpRouter() {
  244|       |        /* Always have ANY route */
  245|  6.41k|        getNode(&root, std::string(ANY_METHOD_TOKEN.data(), ANY_METHOD_TOKEN.length()), false);
  246|  6.41k|    }
_ZN3uWS10HttpRouterINS_15HttpContextDataILb0EE10RouterDataEE4NodeC2ENSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEE:
   63|  70.5k|        Node(std::string name) : name(name) {}
_ZN3uWS10HttpRouterINS_15HttpContextDataILb0EE10RouterDataEE7getNodeEPNS4_4NodeENSt3__112basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEb:
   81|  89.7k|    Node *getNode(Node *parent, std::string child, bool isHighPriority) {
   82|  89.7k|        for (std::unique_ptr<Node> &node : parent->children) {
  ------------------
  |  Branch (82:42): [True: 83.3k, False: 64.1k]
  ------------------
   83|  83.3k|            if (node->name == child && node->isHighPriority == isHighPriority) {
  ------------------
  |  Branch (83:17): [True: 32.0k, False: 51.3k]
  |  Branch (83:40): [True: 25.6k, False: 6.41k]
  ------------------
   84|  25.6k|                return node.get();
   85|  25.6k|            }
   86|  83.3k|        }
   87|       |
   88|       |        /* Insert sorted, but keep order if parent is root (we sort methods by priority elsewhere) */
   89|  64.1k|        std::unique_ptr<Node> newNode(new Node(child));
   90|  64.1k|        newNode->isHighPriority = isHighPriority;
   91|  64.1k|        return parent->children.emplace(std::upper_bound(parent->children.begin(), parent->children.end(), newNode, [parent, this](auto &a, auto &b) {
   92|       |
   93|  64.1k|            if (a->isHighPriority != b->isHighPriority) {
   94|  64.1k|                return a->isHighPriority;
   95|  64.1k|            }
   96|       |
   97|  64.1k|            return b->name.length() && (parent != &root) && (lexicalOrder(b->name) < lexicalOrder(a->name));
   98|  64.1k|        }), std::move(newNode))->get();
   99|  89.7k|    }
_ZZN3uWS10HttpRouterINS_15HttpContextDataILb0EE10RouterDataEE7getNodeEPNS4_4NodeENSt3__112basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEbENKUlRT_RT0_E_clIKNS7_10unique_ptrIS5_NS7_14default_deleteIS5_EEEESN_EEDaSF_SH_:
   91|  38.4k|        return parent->children.emplace(std::upper_bound(parent->children.begin(), parent->children.end(), newNode, [parent, this](auto &a, auto &b) {
   92|       |
   93|  38.4k|            if (a->isHighPriority != b->isHighPriority) {
  ------------------
  |  Branch (93:17): [True: 12.8k, False: 25.6k]
  ------------------
   94|  12.8k|                return a->isHighPriority;
   95|  12.8k|            }
   96|       |
   97|  25.6k|            return b->name.length() && (parent != &root) && (lexicalOrder(b->name) < lexicalOrder(a->name));
  ------------------
  |  Branch (97:20): [True: 25.6k, False: 0]
  |  Branch (97:40): [True: 12.8k, False: 12.8k]
  |  Branch (97:61): [True: 6.41k, False: 6.41k]
  ------------------
   98|  38.4k|        }), std::move(newNode))->get();
_ZN3uWS10HttpRouterINS_15HttpContextDataILb0EE10RouterDataEE12lexicalOrderERNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEE:
   67|  25.6k|    int lexicalOrder(std::string &name) {
   68|  25.6k|        if (!name.length()) {
  ------------------
  |  Branch (68:13): [True: 0, False: 25.6k]
  ------------------
   69|      0|            return 2;
   70|      0|        }
   71|  25.6k|        if (name[0] == ':') {
  ------------------
  |  Branch (71:13): [True: 6.41k, False: 19.2k]
  ------------------
   72|  6.41k|            return 1;
   73|  6.41k|        }
   74|  19.2k|        if (name[0] == '*') {
  ------------------
  |  Branch (74:13): [True: 12.8k, False: 6.41k]
  ------------------
   75|  12.8k|            return 0;
   76|  12.8k|        }
   77|  6.41k|        return 2;
   78|  19.2k|    }
_ZN3uWS10HttpRouterINS_15HttpContextDataILb0EE10RouterDataEE11getUserDataEv:
  252|   131k|    USERDATA &getUserData() {
  253|   131k|        return userData;
  254|   131k|    }
_ZN3uWS10HttpRouterINS_15HttpContextDataILb0EE10RouterDataEE5routeENSt3__117basic_string_viewIcNS5_11char_traitsIcEEEES9_:
  257|  60.2k|    bool route(std::string_view method, std::string_view url) {
  258|       |        /* Reset url parsing cache */
  259|  60.2k|        setUrl(url);
  260|  60.2k|        routeParameters.reset();
  261|       |
  262|       |        /* Begin by finding the method node */
  263|  76.7k|        for (auto &p : root.children) {
  ------------------
  |  Branch (263:22): [True: 76.7k, False: 6.06k]
  ------------------
  264|  76.7k|            if (p->name == method) {
  ------------------
  |  Branch (264:17): [True: 54.2k, False: 22.4k]
  ------------------
  265|       |                /* Then route the url */
  266|  54.2k|                if (executeHandlers(p.get(), 0, userData)) {
  ------------------
  |  Branch (266:21): [True: 54.2k, False: 0]
  ------------------
  267|  54.2k|                    return true;
  268|  54.2k|                } else {
  269|      0|                    break;
  270|      0|                }
  271|  54.2k|            }
  272|  76.7k|        }
  273|       |
  274|       |        /* Always test any route last */
  275|  6.06k|        return executeHandlers(root.children.back().get(), 0, userData);
  276|  60.2k|    }
_ZN3uWS10HttpRouterINS_15HttpContextDataILb0EE10RouterDataEE6setUrlENSt3__117basic_string_viewIcNS5_11char_traitsIcEEEE:
  124|   124k|    inline void setUrl(std::string_view url) {
  125|       |
  126|       |        /* Todo: URL may also start with "http://domain/" or "*", not only "/" */
  127|       |
  128|       |        /* We expect to stand on a slash */
  129|   124k|        currentUrl = url;
  130|   124k|        urlSegmentTop = -1;
  131|   124k|    }
_ZN3uWS10HttpRouterINS_15HttpContextDataILb0EE10RouterDataEE15RouteParameters5resetEv:
  108|  60.2k|        void reset() {
  109|  60.2k|            paramsTop = -1;
  110|  60.2k|        }
_ZN3uWS10HttpRouterINS_15HttpContextDataILb0EE10RouterDataEE15executeHandlersEPNS4_4NodeEiRS3_:
  168|  66.3k|    bool executeHandlers(Node *parent, int urlSegment, USERDATA &userData) {
  169|       |
  170|  66.3k|        auto [segment, isStop] = getUrlSegment(urlSegment);
  171|       |
  172|       |        /* If we are on STOP, return where we may stand */
  173|  66.3k|        if (isStop) {
  ------------------
  |  Branch (173:13): [True: 3.70k, False: 62.6k]
  ------------------
  174|       |            /* We have reached accross the entire URL with no stoppage, execute */
  175|  3.70k|            for (uint32_t handler : parent->handlers) {
  ------------------
  |  Branch (175:35): [True: 2.02k, False: 2.62k]
  ------------------
  176|  2.02k|                if (handlers[handler & HANDLER_MASK](this)) {
  ------------------
  |  Branch (176:21): [True: 1.08k, False: 938]
  ------------------
  177|  1.08k|                    return true;
  178|  1.08k|                }
  179|  2.02k|            }
  180|       |            /* We reached the end, so go back */
  181|  2.62k|            return false;
  182|  3.70k|        }
  183|       |
  184|   124k|        for (auto &p : parent->children) {
  ------------------
  |  Branch (184:22): [True: 124k, False: 364]
  ------------------
  185|   124k|            if (p->name.length() && p->name[0] == '*') {
  ------------------
  |  Branch (185:17): [True: 124k, False: 0]
  |  Branch (185:37): [True: 68.9k, False: 55.9k]
  ------------------
  186|       |                /* Wildcard match (can be seen as a shortcut) */
  187|  68.9k|                for (uint32_t handler : p->handlers) {
  ------------------
  |  Branch (187:39): [True: 68.9k, False: 9.75k]
  ------------------
  188|  68.9k|                    if (handlers[handler & HANDLER_MASK](this)) {
  ------------------
  |  Branch (188:25): [True: 59.1k, False: 9.75k]
  ------------------
  189|  59.1k|                        return true;
  190|  59.1k|                    }
  191|  68.9k|                }
  192|  68.9k|            } else if (p->name.length() && p->name[0] == ':' && segment.length()) {
  ------------------
  |  Branch (192:24): [True: 55.9k, False: 0]
  |  Branch (192:44): [True: 6.06k, False: 49.9k]
  |  Branch (192:65): [True: 3.70k, False: 2.36k]
  ------------------
  193|       |                /* Parameter match */
  194|  3.70k|                routeParameters.push(segment);
  195|  3.70k|                if (executeHandlers(p.get(), urlSegment + 1, userData)) {
  ------------------
  |  Branch (195:21): [True: 2.02k, False: 1.68k]
  ------------------
  196|  2.02k|                    return true;
  197|  2.02k|                }
  198|  1.68k|                routeParameters.pop();
  199|  52.2k|            } else if (p->name == segment) {
  ------------------
  |  Branch (199:24): [True: 2.38k, False: 49.8k]
  ------------------
  200|       |                /* Static match */
  201|  2.38k|                if (executeHandlers(p.get(), urlSegment + 1, userData)) {
  ------------------
  |  Branch (201:21): [True: 1.08k, False: 1.30k]
  ------------------
  202|  1.08k|                    return true;
  203|  1.08k|                }
  204|  2.38k|            }
  205|   124k|        }
  206|    364|        return false;
  207|  62.6k|    }
_ZN3uWS10HttpRouterINS_15HttpContextDataILb0EE10RouterDataEE13getUrlSegmentEi:
  134|   245k|    inline std::pair<std::string_view, bool> getUrlSegment(int urlSegment) {
  135|   245k|        if (urlSegment > urlSegmentTop) {
  ------------------
  |  Branch (135:13): [True: 175k, False: 70.5k]
  ------------------
  136|       |            /* Signal as STOP when we have no more URL or stack space */
  137|   175k|            if (!currentUrl.length() || urlSegment > int(MAX_URL_SEGMENTS - 1)) {
  ------------------
  |  Branch (137:17): [True: 42.1k, False: 133k]
  |  Branch (137:41): [True: 0, False: 133k]
  ------------------
  138|  42.1k|                return {{}, true};
  139|  42.1k|            }
  140|       |
  141|       |            /* We always stand on a slash here, so step over it */
  142|   133k|            currentUrl.remove_prefix(1);
  143|       |
  144|   133k|            auto segmentLength = currentUrl.find('/');
  145|   133k|            if (segmentLength == std::string::npos) {
  ------------------
  |  Branch (145:17): [True: 114k, False: 18.3k]
  ------------------
  146|   114k|                segmentLength = currentUrl.length();
  147|       |
  148|       |                /* Push to url segment vector */
  149|   114k|                urlSegmentVector[urlSegment] = currentUrl.substr(0, segmentLength);
  150|   114k|                urlSegmentTop++;
  151|       |
  152|       |                /* Update currentUrl */
  153|   114k|                currentUrl = currentUrl.substr(segmentLength);
  154|   114k|            } else {
  155|       |                /* Push to url segment vector */
  156|  18.3k|                urlSegmentVector[urlSegment] = currentUrl.substr(0, segmentLength);
  157|  18.3k|                urlSegmentTop++;
  158|       |
  159|       |                /* Update currentUrl */
  160|  18.3k|                currentUrl = currentUrl.substr(segmentLength);
  161|  18.3k|            }
  162|   133k|        }
  163|       |        /* In any case we return it */
  164|   203k|        return {urlSegmentVector[urlSegment], false};
  165|   245k|    }
_ZN3uWS10HttpRouterINS_15HttpContextDataILb0EE10RouterDataEE15RouteParameters4pushENSt3__117basic_string_viewIcNS6_11char_traitsIcEEEE:
  112|  3.70k|        void push(std::string_view param) {
  113|       |            /* We check these bounds indirectly via the urlSegments limit */
  114|  3.70k|            params[++paramsTop] = param;
  115|  3.70k|        }
_ZN3uWS10HttpRouterINS_15HttpContextDataILb0EE10RouterDataEE15RouteParameters3popEv:
  117|  1.68k|        void pop() {
  118|       |            /* Same here, we cannot pop outside */
  119|  1.68k|            paramsTop--;
  120|  1.68k|        }
_ZN3uWS10HttpRouterINS_15HttpContextDataILb0EE10RouterDataEE6removeENSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEESB_j:
  360|  38.4k|    void remove(std::string method, std::string pattern, uint32_t priority) {
  361|  38.4k|        uint32_t handler = findHandler(method, pattern, priority);
  362|  38.4k|        if (handler == UINT32_MAX) {
  ------------------
  |  Branch (362:13): [True: 38.4k, False: 0]
  ------------------
  363|       |            /* Not found or already removed, do nothing */
  364|  38.4k|            return;
  365|  38.4k|        }
  366|       |
  367|       |        /* Cull the entire tree */
  368|       |        /* For all nodes in depth first tree traveral;
  369|       |         * if node contains handler - remove the handler -
  370|       |         * if node holds no handlers after removal, remove the node and return */
  371|      0|        cullNode(nullptr, &root, handler);
  372|       |
  373|       |        /* Now remove the actual handler */
  374|      0|        handlers.erase(handlers.begin() + (handler & HANDLER_MASK));
  375|      0|    }
_ZN3uWS10HttpRouterINS_15HttpContextDataILb0EE10RouterDataEE11findHandlerENSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEESB_j:
  210|  38.4k|    uint32_t findHandler(std::string method, std::string pattern, uint32_t priority) {
  211|  57.7k|        for (std::unique_ptr<Node> &node : root.children) {
  ------------------
  |  Branch (211:42): [True: 57.7k, False: 12.8k]
  ------------------
  212|  57.7k|            if (method == node->name) {
  ------------------
  |  Branch (212:17): [True: 25.6k, False: 32.0k]
  ------------------
  213|  25.6k|                setUrl(pattern);
  214|  25.6k|                Node *n = node.get();
  215|  25.6k|                for (int i = 0; !getUrlSegment(i).second; i++) {
  ------------------
  |  Branch (215:33): [True: 25.6k, False: 0]
  ------------------
  216|       |                    /* Go to next segment or quit */
  217|  25.6k|                    std::string segment = std::string(getUrlSegment(i).first);
  218|  25.6k|                    Node *next = nullptr;
  219|  25.6k|                    for (std::unique_ptr<Node> &child : n->children) {
  ------------------
  |  Branch (219:55): [True: 25.6k, False: 25.6k]
  ------------------
  220|  25.6k|                        if (child->name == segment && child->isHighPriority == (priority == HIGH_PRIORITY)) {
  ------------------
  |  Branch (220:29): [True: 6.41k, False: 19.2k]
  |  Branch (220:55): [True: 0, False: 6.41k]
  ------------------
  221|      0|                            next = child.get();
  222|      0|                            break;
  223|      0|                        }
  224|  25.6k|                    }
  225|  25.6k|                    if (!next) {
  ------------------
  |  Branch (225:25): [True: 25.6k, False: 0]
  ------------------
  226|  25.6k|                        return UINT32_MAX;
  227|  25.6k|                    }
  228|      0|                    n = next;
  229|      0|                }
  230|       |                /* Seek for a priority match in the found node */
  231|      0|                for (unsigned int i = 0; i < n->handlers.size(); i++) {
  ------------------
  |  Branch (231:42): [True: 0, False: 0]
  ------------------
  232|      0|                    if ((n->handlers[i] & ~HANDLER_MASK) == priority) {
  ------------------
  |  Branch (232:25): [True: 0, False: 0]
  ------------------
  233|      0|                        return n->handlers[i];
  234|      0|                    }
  235|      0|                }
  236|      0|                return UINT32_MAX;
  237|      0|            }
  238|  57.7k|        }
  239|  12.8k|        return UINT32_MAX;
  240|  38.4k|    }
_ZN3uWS10HttpRouterINS_15HttpContextDataILb0EE10RouterDataEE3addENSt3__16vectorINS5_12basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEENSA_ISC_EEEESC_ON5ofats13any_invocableIFbPS4_EEEj:
  279|  38.4k|    void add(std::vector<std::string> methods, std::string pattern, MoveOnlyFunction<bool(HttpRouter *)> &&handler, uint32_t priority = MEDIUM_PRIORITY) {
  280|       |        /* First remove existing handler */
  281|  38.4k|        remove(methods[0], pattern, priority);
  282|       |        
  283|  38.4k|        for (std::string method : methods) {
  ------------------
  |  Branch (283:33): [True: 38.4k, False: 38.4k]
  ------------------
  284|       |            /* Lookup method */
  285|  38.4k|            Node *node = getNode(&root, method, false);
  286|       |            /* Iterate over all segments */
  287|  38.4k|            setUrl(pattern);
  288|  83.3k|            for (int i = 0; !getUrlSegment(i).second; i++) {
  ------------------
  |  Branch (288:29): [True: 44.8k, False: 38.4k]
  ------------------
  289|  44.8k|                std::string strippedSegment(getUrlSegment(i).first);
  290|  44.8k|                if (strippedSegment.length() && strippedSegment[0] == ':') {
  ------------------
  |  Branch (290:21): [True: 44.8k, False: 0]
  |  Branch (290:49): [True: 6.41k, False: 38.4k]
  ------------------
  291|       |                    /* Parameter routes must be named only : */
  292|  6.41k|                    strippedSegment = ":";
  293|  6.41k|                }
  294|  44.8k|                node = getNode(node, strippedSegment, priority == HIGH_PRIORITY);
  295|  44.8k|            }
  296|       |            /* Insert handler in order sorted by priority (most significant 1 byte) */
  297|  38.4k|            node->handlers.insert(std::upper_bound(node->handlers.begin(), node->handlers.end(), (uint32_t) (priority | handlers.size())), (uint32_t) (priority | handlers.size()));
  298|  38.4k|        }
  299|       |
  300|       |        /* Alloate this handler */
  301|  38.4k|        handlers.emplace_back(std::move(handler));
  302|       |
  303|       |        /* ANY method must be last, GET must be first */
  304|  38.4k|        std::sort(root.children.begin(), root.children.end(), [](const auto &a, const auto &b) {
  305|       |            /* Assuming the list of methods is unique, non-repeating */
  306|  38.4k|            if (a->name == "GET") {
  307|  38.4k|                return true;
  308|  38.4k|            } else if (b->name == "GET") {
  309|  38.4k|                return false;
  310|  38.4k|            } else if (a->name == ANY_METHOD_TOKEN) {
  311|  38.4k|                return false;
  312|  38.4k|            } else if (b->name == ANY_METHOD_TOKEN) {
  313|  38.4k|                return true;
  314|  38.4k|            } else {
  315|  38.4k|                return a->name < b->name;
  316|  38.4k|            }
  317|  38.4k|        });
  318|  38.4k|    }
_ZZN3uWS10HttpRouterINS_15HttpContextDataILb0EE10RouterDataEE3addENSt3__16vectorINS5_12basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEENSA_ISC_EEEESC_ON5ofats13any_invocableIFbPS4_EEEjENKUlRKT_RKT0_E_clINS5_10unique_ptrINS4_4NodeENS5_14default_deleteISU_EEEESX_EEDaSN_SQ_:
  304|  57.7k|        std::sort(root.children.begin(), root.children.end(), [](const auto &a, const auto &b) {
  305|       |            /* Assuming the list of methods is unique, non-repeating */
  306|  57.7k|            if (a->name == "GET") {
  ------------------
  |  Branch (306:17): [True: 6.41k, False: 51.3k]
  ------------------
  307|  6.41k|                return true;
  308|  51.3k|            } else if (b->name == "GET") {
  ------------------
  |  Branch (308:24): [True: 32.0k, False: 19.2k]
  ------------------
  309|  32.0k|                return false;
  310|  32.0k|            } else if (a->name == ANY_METHOD_TOKEN) {
  ------------------
  |  Branch (310:24): [True: 12.8k, False: 6.41k]
  ------------------
  311|  12.8k|                return false;
  312|  12.8k|            } else if (b->name == ANY_METHOD_TOKEN) {
  ------------------
  |  Branch (312:24): [True: 6.41k, False: 0]
  ------------------
  313|  6.41k|                return true;
  314|  6.41k|            } else {
  315|      0|                return a->name < b->name;
  316|      0|            }
  317|  57.7k|        });
_ZN3uWS10HttpRouterINS_15HttpContextDataILb0EE10RouterDataEE13getParametersEv:
  248|  70.9k|    std::pair<int, std::string_view *> getParameters() {
  249|  70.9k|        return {routeParameters.paramsTop, routeParameters.params};
  250|  70.9k|    }

_ZN3uWS4Loop3getEPv:
  111|  78.7k|    static Loop *get(void *existingNativeLoop = nullptr) {
  112|  78.7k|        if (!getLazyLoop().loop) {
  ------------------
  |  Branch (112:13): [True: 6.41k, False: 72.2k]
  ------------------
  113|       |            /* If we are given a native loop pointer we pass that to uSockets and let it deal with it */
  114|  6.41k|            if (existingNativeLoop) {
  ------------------
  |  Branch (114:17): [True: 0, False: 6.41k]
  ------------------
  115|       |                /* Todo: here we want to pass the pointer, not a boolean */
  116|      0|                getLazyLoop().loop = create(existingNativeLoop);
  117|       |                /* We cannot register automatic free here, must be manually done */
  118|  6.41k|            } else {
  119|  6.41k|                getLazyLoop().loop = create(nullptr);
  120|  6.41k|                getLazyLoop().cleanMe = true;
  121|  6.41k|            }
  122|  6.41k|        }
  123|       |
  124|  78.7k|        return getLazyLoop().loop;
  125|  78.7k|    }
_ZN3uWS4Loop11getLazyLoopEv:
  103|   176k|    static LoopCleaner &getLazyLoop() {
  104|   176k|        static thread_local LoopCleaner lazyLoop;
  105|   176k|        return lazyLoop;
  106|   176k|    }
_ZN3uWS4Loop11LoopCleanerD2Ev:
   94|      1|        ~LoopCleaner() {
   95|      1|            if(loop && cleanMe) {
  ------------------
  |  Branch (95:16): [True: 0, False: 1]
  |  Branch (95:24): [True: 0, False: 0]
  ------------------
   96|      0|                loop->free();
   97|      0|            }
   98|      1|        }
_ZN3uWS4Loop6createEPv:
   76|  6.41k|    static Loop *create(void *hint) {
   77|  6.41k|        Loop *loop = ((Loop *) us_create_loop(hint, wakeupCb, preCb, postCb, sizeof(LoopData)))->init();
   78|       |
   79|       |        /* We also need some timers (should live off the one 4 second timer rather) */
   80|  6.41k|        LoopData *loopData = (LoopData *) us_loop_ext((struct us_loop_t *) loop);
   81|  6.41k|        loopData->dateTimer = us_create_timer((struct us_loop_t *) loop, 1, sizeof(LoopData *));
   82|  6.41k|        memcpy(us_timer_ext(loopData->dateTimer), &loopData, sizeof(LoopData *));
   83|  6.41k|        us_timer_set(loopData->dateTimer, [](struct us_timer_t *t) {
   84|  6.41k|            LoopData *loopData;
   85|  6.41k|            memcpy(&loopData, us_timer_ext(t), sizeof(LoopData *));
   86|  6.41k|            loopData->updateDate();
   87|  6.41k|        }, 1000, 1000);
   88|       |
   89|  6.41k|        return loop;
   90|  6.41k|    }
_ZN3uWS4Loop8wakeupCbEP9us_loop_t:
   30|  1.26M|    static void wakeupCb(us_loop_t *loop) {
   31|  1.26M|        LoopData *loopData = (LoopData *) us_loop_ext(loop);
   32|       |
   33|       |        /* Swap current deferQueue */
   34|  1.26M|        loopData->deferMutex.lock();
   35|  1.26M|        int oldDeferQueue = loopData->currentDeferQueue;
   36|  1.26M|        loopData->currentDeferQueue = (loopData->currentDeferQueue + 1) % 2;
   37|  1.26M|        loopData->deferMutex.unlock();
   38|       |
   39|       |        /* Drain the queue */
   40|  1.26M|        for (auto &x : loopData->deferQueues[oldDeferQueue]) {
  ------------------
  |  Branch (40:22): [True: 6.59k, False: 1.26M]
  ------------------
   41|  6.59k|            x();
   42|  6.59k|        }
   43|  1.26M|        loopData->deferQueues[oldDeferQueue].clear();
   44|  1.26M|    }
_ZN3uWS4Loop5preCbEP9us_loop_t:
   46|  1.59M|    static void preCb(us_loop_t *loop) {
   47|  1.59M|        LoopData *loopData = (LoopData *) us_loop_ext(loop);
   48|       |
   49|  1.59M|        for (auto &p : loopData->preHandlers) {
  ------------------
  |  Branch (49:22): [True: 1.59M, False: 1.59M]
  ------------------
   50|  1.59M|            p.second((Loop *) loop);
   51|  1.59M|        }
   52|  1.59M|    }
_ZN3uWS4Loop6postCbEP9us_loop_t:
   54|  1.59M|    static void postCb(us_loop_t *loop) {
   55|  1.59M|        LoopData *loopData = (LoopData *) us_loop_ext(loop);
   56|       |
   57|  1.59M|        for (auto &p : loopData->postHandlers) {
  ------------------
  |  Branch (57:22): [True: 1.59M, False: 1.59M]
  ------------------
   58|  1.59M|            p.second((Loop *) loop);
   59|  1.59M|        }
   60|       |
   61|       |        /* After every event loop iteration, we must not hold the cork buffer */
   62|  1.59M|        if (loopData->corkedSocket) {
  ------------------
  |  Branch (62:13): [True: 0, False: 1.59M]
  ------------------
   63|      0|            std::cerr << "Error: Cork buffer must not be held across event loop iterations!" << std::endl;
   64|      0|            std::terminate();
   65|      0|        }
   66|  1.59M|    }
_ZN3uWS4Loop4initEv:
   71|  6.41k|    Loop *init() {
   72|  6.41k|        new (us_loop_ext((us_loop_t *) this)) LoopData;
   73|  6.41k|        return this;
   74|  6.41k|    }
_ZZN3uWS4Loop6createEPvENKUlP10us_timer_tE_clES3_:
   83|  1.25M|        us_timer_set(loopData->dateTimer, [](struct us_timer_t *t) {
   84|  1.25M|            LoopData *loopData;
   85|  1.25M|            memcpy(&loopData, us_timer_ext(t), sizeof(LoopData *));
   86|  1.25M|            loopData->updateDate();
   87|  1.25M|        }, 1000, 1000);
_ZN3uWS4Loop9setSilentEb:
  192|  6.41k|    void setSilent(bool silent) {
  193|  6.41k|        ((LoopData *) us_loop_ext((us_loop_t *) this))->noMark = silent;
  194|  6.41k|    }
_ZN3uWS4Loop4freeEv:
  128|  6.41k|    void free() {
  129|  6.41k|        LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this);
  130|       |
  131|       |        /* Stop and free dateTimer first */
  132|  6.41k|        us_timer_close(loopData->dateTimer);
  133|       |
  134|  6.41k|        loopData->~LoopData();
  135|       |        /* uSockets will track whether this loop is owned by us or a borrowed alien loop */
  136|  6.41k|        us_loop_free((us_loop_t *) this);
  137|       |
  138|       |        /* Reset lazyLoop */
  139|  6.41k|        getLazyLoop().loop = nullptr;
  140|  6.41k|    }
_ZN3uWS4Loop17removePostHandlerEPv:
  149|  6.41k|    void removePostHandler(void *key) {
  150|  6.41k|        LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this);
  151|       |
  152|  6.41k|        loopData->postHandlers.erase(key);
  153|  6.41k|    }
_ZN3uWS4Loop16removePreHandlerEPv:
  162|  6.41k|    void removePreHandler(void *key) {
  163|  6.41k|        LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this);
  164|       |
  165|  6.41k|        loopData->preHandlers.erase(key);
  166|  6.41k|    }
_ZN3uWS4Loop14addPostHandlerEPvON5ofats13any_invocableIFvPS0_EEE:
  142|  6.41k|    void addPostHandler(void *key, MoveOnlyFunction<void(Loop *)> &&handler) {
  143|  6.41k|        LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this);
  144|       |
  145|  6.41k|        loopData->postHandlers.emplace(key, std::move(handler));
  146|  6.41k|    }
_ZN3uWS4Loop13addPreHandlerEPvON5ofats13any_invocableIFvPS0_EEE:
  155|  6.41k|    void addPreHandler(void *key, MoveOnlyFunction<void(Loop *)> &&handler) {
  156|  6.41k|        LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this);
  157|       |
  158|  6.41k|        loopData->preHandlers.emplace(key, std::move(handler));
  159|  6.41k|    }
_ZN3uWS4Loop5deferEON5ofats13any_invocableIFvvEEE:
  169|  8.15k|    void defer(MoveOnlyFunction<void()> &&cb) {
  170|  8.15k|        LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this);
  171|       |
  172|       |        //if (std::thread::get_id() == ) // todo: add fast path for same thread id
  173|  8.15k|        loopData->deferMutex.lock();
  174|  8.15k|        loopData->deferQueues[loopData->currentDeferQueue].emplace_back(std::move(cb));
  175|  8.15k|        loopData->deferMutex.unlock();
  176|       |
  177|  8.15k|        us_wakeup_loop((us_loop_t *) this);
  178|  8.15k|    }
_ZN3uWS3runEv:
  198|  6.41k|inline void run() {
  199|  6.41k|    Loop::get()->run();
  200|  6.41k|}
_ZN3uWS4Loop3runEv:
  181|  6.41k|    void run() {
  182|  6.41k|        us_loop_run((us_loop_t *) this);
  183|  6.41k|    }

_ZN3uWS8LoopDataC2Ev:
   49|  6.41k|    LoopData() {
   50|  6.41k|        updateDate();
   51|  6.41k|    }
_ZN3uWS8LoopData10updateDateEv:
   63|  1.26M|    void updateDate() {
   64|  1.26M|        time_t now = time(0);
   65|  1.26M|        struct tm tstruct = {};
   66|       |#ifdef _WIN32
   67|       |        /* Micro, fucking soft never follows spec. */
   68|       |        gmtime_s(&tstruct, &now);
   69|       |#else
   70|  1.26M|        gmtime_r(&now, &tstruct);
   71|  1.26M|#endif
   72|  1.26M|        static const char wday_name[][4] = {
   73|  1.26M|            "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
   74|  1.26M|        };
   75|  1.26M|        static const char mon_name[][4] = {
   76|  1.26M|            "Jan", "Feb", "Mar", "Apr", "May", "Jun",
   77|  1.26M|            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
   78|  1.26M|        };
   79|  1.26M|        snprintf(date, 32, "%.3s, %.2u %.3s %.4u %.2u:%.2u:%.2u GMT",
   80|  1.26M|            wday_name[tstruct.tm_wday],
   81|  1.26M|            tstruct.tm_mday % 99,
   82|  1.26M|            mon_name[tstruct.tm_mon],
   83|  1.26M|            (1900 + tstruct.tm_year) % 9999,
   84|  1.26M|            tstruct.tm_hour % 99,
   85|  1.26M|            tstruct.tm_min % 99,
   86|  1.26M|            tstruct.tm_sec % 99);
   87|  1.26M|    }
_ZN3uWS8LoopDataD2Ev:
   53|  6.41k|    ~LoopData() {
   54|       |        /* If we have had App.ws called with compression we need to clear this */
   55|  6.41k|        if (zlibContext) {
  ------------------
  |  Branch (55:13): [True: 6.41k, False: 0]
  ------------------
   56|  6.41k|            delete zlibContext;
   57|  6.41k|            delete inflationStream;
   58|  6.41k|            delete deflationStream;
   59|  6.41k|        }
   60|  6.41k|        delete [] corkBuffer;
   61|  6.41k|    }

_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEP19us_socket_context_tEEC2EDn:
  187|  12.8k|  any_invocable_impl(std::nullptr_t) noexcept {}
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEC2EDn:
  187|  38.4k|  any_invocable_impl(std::nullptr_t) noexcept {}
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEENS2_6OpCodeEEEC2EDn:
  187|  44.8k|  any_invocable_impl(std::nullptr_t) noexcept {}
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEEC2EDn:
  187|  38.4k|  any_invocable_impl(std::nullptr_t) noexcept {}
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEiiEEC2EDn:
  187|  25.6k|  any_invocable_impl(std::nullptr_t) noexcept {}
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEEC2EDn:
  187|  19.2k|  any_invocable_impl(std::nullptr_t) noexcept {}
_ZN5ofats10any_detail18any_invocable_implIvLb0EJP18us_listen_socket_tEED2Ev:
  206|  6.41k|  ~any_invocable_impl() { destroy(); }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJP18us_listen_socket_tEE7destroyEv:
  239|  6.41k|  void destroy() noexcept {
  240|  6.41k|    if (handle_) {
  ------------------
  |  Branch (240:9): [True: 6.41k, False: 0]
  ------------------
  241|  6.41k|      handle_(action::destroy, &storage_, nullptr);
  242|  6.41k|      handle_ = nullptr;
  243|  6.41k|    }
  244|  6.41k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEED2Ev:
  206|  89.7k|  ~any_invocable_impl() { destroy(); }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE7destroyEv:
  239|  89.7k|  void destroy() noexcept {
  240|  89.7k|    if (handle_) {
  ------------------
  |  Branch (240:9): [True: 19.2k, False: 70.5k]
  ------------------
  241|  19.2k|      handle_(action::destroy, &storage_, nullptr);
  242|  19.2k|      handle_ = nullptr;
  243|  19.2k|    }
  244|  89.7k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEiiEED2Ev:
  206|  64.1k|  ~any_invocable_impl() { destroy(); }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEiiEE7destroyEv:
  239|  64.1k|  void destroy() noexcept {
  240|  64.1k|    if (handle_) {
  ------------------
  |  Branch (240:9): [True: 0, False: 64.1k]
  ------------------
  241|      0|      handle_(action::destroy, &storage_, nullptr);
  242|      0|      handle_ = nullptr;
  243|      0|    }
  244|  64.1k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEED2Ev:
  206|   128k|  ~any_invocable_impl() { destroy(); }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE7destroyEv:
  239|   128k|  void destroy() noexcept {
  240|   128k|    if (handle_) {
  ------------------
  |  Branch (240:9): [True: 12.8k, False: 115k]
  ------------------
  241|  12.8k|      handle_(action::destroy, &storage_, nullptr);
  242|  12.8k|      handle_ = nullptr;
  243|  12.8k|    }
  244|   128k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEED2Ev:
  206|   128k|  ~any_invocable_impl() { destroy(); }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEE7destroyEv:
  239|   128k|  void destroy() noexcept {
  240|   128k|    if (handle_) {
  ------------------
  |  Branch (240:9): [True: 12.8k, False: 115k]
  ------------------
  241|  12.8k|      handle_(action::destroy, &storage_, nullptr);
  242|  12.8k|      handle_ = nullptr;
  243|  12.8k|    }
  244|   128k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEENS2_6OpCodeEEED2Ev:
  206|   128k|  ~any_invocable_impl() { destroy(); }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEENS2_6OpCodeEEE7destroyEv:
  239|   128k|  void destroy() noexcept {
  240|   128k|    if (handle_) {
  ------------------
  |  Branch (240:9): [True: 6.41k, False: 121k]
  ------------------
  241|  6.41k|      handle_(action::destroy, &storage_, nullptr);
  242|  6.41k|      handle_ = nullptr;
  243|  6.41k|    }
  244|   128k|  }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEP19us_socket_context_tEED2Ev:
  206|  38.4k|  ~any_invocable_impl() { destroy(); }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEP19us_socket_context_tEE7destroyEv:
  239|  38.4k|  void destroy() noexcept {
  240|  38.4k|    if (handle_) {
  ------------------
  |  Branch (240:9): [True: 0, False: 38.4k]
  ------------------
  241|      0|      handle_(action::destroy, &storage_, nullptr);
  242|      0|      handle_ = nullptr;
  243|      0|    }
  244|  38.4k|  }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEED2Ev:
  206|   115k|  ~any_invocable_impl() { destroy(); }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE7destroyEv:
  239|   115k|  void destroy() noexcept {
  240|   115k|    if (handle_) {
  ------------------
  |  Branch (240:9): [True: 38.4k, False: 76.9k]
  ------------------
  241|  38.4k|      handle_(action::destroy, &storage_, nullptr);
  242|  38.4k|      handle_ = nullptr;
  243|  38.4k|    }
  244|   115k|  }
_ZN5ofats13any_invocableIFvvEEclEv:
  345|  23.7k|    R operator()(ArgTypes... args) cv ref noexcept(noex) {                     \
  346|  23.7k|      return base_type::call(std::forward<ArgTypes>(args)...);                 \
  347|  23.7k|    }                                                                          \
_ZN5ofats10any_detail18any_invocable_implIvLb0EJEE4callEv:
  246|  23.7k|  R call(ArgTypes... args) noexcept(is_noexcept) {
  247|  23.7k|    return call_(storage_, std::forward<ArgTypes>(args)...);
  248|  23.7k|  }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJEED2Ev:
  206|  1.86M|  ~any_invocable_impl() { destroy(); }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJEE7destroyEv:
  239|  1.86M|  void destroy() noexcept {
  240|  1.86M|    if (handle_) {
  ------------------
  |  Branch (240:9): [True: 28.4k, False: 1.83M]
  ------------------
  241|  28.4k|      handle_(action::destroy, &storage_, nullptr);
  242|  28.4k|      handle_ = nullptr;
  243|  28.4k|    }
  244|  1.86M|  }
_ZN5ofats13any_invocableIFvPN3uWS4LoopEEEclES3_:
  345|  3.19M|    R operator()(ArgTypes... args) cv ref noexcept(noex) {                     \
  346|  3.19M|      return base_type::call(std::forward<ArgTypes>(args)...);                 \
  347|  3.19M|    }                                                                          \
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS4LoopEEE4callES4_:
  246|  3.19M|  R call(ArgTypes... args) noexcept(is_noexcept) {
  247|  3.19M|    return call_(storage_, std::forward<ArgTypes>(args)...);
  248|  3.19M|  }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS4LoopEEED2Ev:
  206|  25.6k|  ~any_invocable_impl() { destroy(); }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS4LoopEEE7destroyEv:
  239|  25.6k|  void destroy() noexcept {
  240|  25.6k|    if (handle_) {
  ------------------
  |  Branch (240:9): [True: 12.8k, False: 12.8k]
  ------------------
  241|  12.8k|      handle_(action::destroy, &storage_, nullptr);
  242|  12.8k|      handle_ = nullptr;
  243|  12.8k|    }
  244|  25.6k|  }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPKcEEC2EDn:
  187|  6.41k|  any_invocable_impl(std::nullptr_t) noexcept {}
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPKcEED2Ev:
  206|  19.2k|  ~any_invocable_impl() { destroy(); }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPKcEE7destroyEv:
  239|  19.2k|  void destroy() noexcept {
  240|  19.2k|    if (handle_) {
  ------------------
  |  Branch (240:9): [True: 0, False: 19.2k]
  ------------------
  241|      0|      handle_(action::destroy, &storage_, nullptr);
  242|      0|      handle_ = nullptr;
  243|      0|    }
  244|  19.2k|  }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPKcEEC2Ev:
  186|  6.41k|  any_invocable_impl() noexcept = default;
_ZN5ofats10any_detail18any_invocable_implIbLb0EJPN3uWS10HttpRouterINS2_15HttpContextDataILb0EE10RouterDataEEEEED2Ev:
  206|   121k|  ~any_invocable_impl() { destroy(); }
_ZN5ofats10any_detail18any_invocable_implIbLb0EJPN3uWS10HttpRouterINS2_15HttpContextDataILb0EE10RouterDataEEEEE7destroyEv:
  239|   121k|  void destroy() noexcept {
  240|   121k|    if (handle_) {
  ------------------
  |  Branch (240:9): [True: 38.4k, False: 83.3k]
  ------------------
  241|  38.4k|      handle_(action::destroy, &storage_, nullptr);
  242|  38.4k|      handle_ = nullptr;
  243|  38.4k|    }
  244|   121k|  }
_ZN5ofats10any_detail18any_invocable_implIbLb0EJmEEC2Ev:
  186|  1.74M|  any_invocable_impl() noexcept = default;
_ZN5ofats10any_detail18any_invocable_implIvLb0EJEEC2Ev:
  186|  1.76M|  any_invocable_impl() noexcept = default;
_ZN5ofats10any_detail18any_invocable_implIvLb0EJNSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEbEEC2Ev:
  186|  1.74M|  any_invocable_impl() noexcept = default;
_ZNK5ofats10any_detail18any_invocable_implIvLb0EJEEcvbEv:
  228|  1.70M|  explicit operator bool() const noexcept { return handle_ != nullptr; }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJNSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEbEED2Ev:
  206|  1.75M|  ~any_invocable_impl() { destroy(); }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJNSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEbEE7destroyEv:
  239|  1.75M|  void destroy() noexcept {
  240|  1.75M|    if (handle_) {
  ------------------
  |  Branch (240:9): [True: 4.29k, False: 1.74M]
  ------------------
  241|  4.29k|      handle_(action::destroy, &storage_, nullptr);
  242|  4.29k|      handle_ = nullptr;
  243|  4.29k|    }
  244|  1.75M|  }
_ZN5ofats10any_detail18any_invocable_implIbLb0EJmEED2Ev:
  206|  1.79M|  ~any_invocable_impl() { destroy(); }
_ZN5ofats10any_detail18any_invocable_implIbLb0EJmEE7destroyEv:
  239|  1.79M|  void destroy() noexcept {
  240|  1.79M|    if (handle_) {
  ------------------
  |  Branch (240:9): [True: 0, False: 1.79M]
  ------------------
  241|      0|      handle_(action::destroy, &storage_, nullptr);
  242|      0|      handle_ = nullptr;
  243|      0|    }
  244|  1.79M|  }
_ZN5ofats13any_invocableIFPvS1_NSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEbEEclES1_S6_b:
  345|  49.5k|    R operator()(ArgTypes... args) cv ref noexcept(noex) {                     \
  346|  49.5k|      return base_type::call(std::forward<ArgTypes>(args)...);                 \
  347|  49.5k|    }                                                                          \
_ZN5ofats10any_detail18any_invocable_implIPvLb0EJS2_NSt3__117basic_string_viewIcNS3_11char_traitsIcEEEEbEE4callES2_S7_b:
  246|  49.5k|  R call(ArgTypes... args) noexcept(is_noexcept) {
  247|  49.5k|    return call_(storage_, std::forward<ArgTypes>(args)...);
  248|  49.5k|  }
_ZN5ofats13any_invocableIFPvS1_PN3uWS11HttpRequestEEEclES1_S4_:
  345|  60.4k|    R operator()(ArgTypes... args) cv ref noexcept(noex) {                     \
  346|  60.4k|      return base_type::call(std::forward<ArgTypes>(args)...);                 \
  347|  60.4k|    }                                                                          \
_ZN5ofats10any_detail18any_invocable_implIPvLb0EJS2_PN3uWS11HttpRequestEEE4callES2_S5_:
  246|  60.4k|  R call(ArgTypes... args) noexcept(is_noexcept) {
  247|  60.4k|    return call_(storage_, std::forward<ArgTypes>(args)...);
  248|  60.4k|  }
_ZN5ofats13any_invocableIFPvS1_PN3uWS11HttpRequestEEEC2IZZNS2_11HttpContextILb0EE4initEvENKUlP11us_socket_tPciE_clESB_SC_iEUlS1_S4_E_vEEOT_:
  303|   382k|    any_invocable(F&& f) {                                                     \
  304|   382k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|   382k|    }                                                                          \
_ZN5ofats10any_detail18any_invocable_implIPvLb0EJS2_PN3uWS11HttpRequestEEEC2Ev:
  186|   382k|  any_invocable_impl() noexcept = default;
_ZN5ofats10any_detail18any_invocable_implIPvLb0EJS2_PN3uWS11HttpRequestEEE6createIZZNS3_11HttpContextILb0EE4initEvENKUlP11us_socket_tPciE_clESB_SC_iEUlS2_S5_E_JSE_EEEvDpOT0_:
  232|   382k|  void create(Args&&... args) {
  233|   382k|    using hdl = handler<F>;
  234|   382k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|   382k|    handle_ = &hdl::handle;
  236|   382k|    call_ = &hdl::call;
  237|   382k|  }
_ZN5ofats10any_detail14handler_traitsIPvJS2_PN3uWS11HttpRequestEEE13small_handlerIZZNS3_11HttpContextILb0EE4initEvENKUlP11us_socket_tPciE_clESB_SC_iEUlS2_S5_E_E6createIJSE_EEEvRNS0_7storageEDpOT_:
  118|   382k|    static void create(storage& s, Args&&... args) {
  119|   382k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|   382k|    }
_ZN5ofats10any_detail14handler_traitsIPvJS2_PN3uWS11HttpRequestEEE12handler_baseINS6_13small_handlerIZZNS3_11HttpContextILb0EE4initEvENKUlP11us_socket_tPciE_clESC_SD_iEUlS2_S5_E_EEE6handleENS0_6actionEPNS0_7storageESK_:
  103|   382k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|   382k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 382k]
  ------------------
  105|   382k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 382k, False: 0]
  ------------------
  106|   382k|          Derived::destroy(*current);
  107|   382k|          break;
  108|      0|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 0, False: 382k]
  ------------------
  109|      0|          Derived::move(*current, *other);
  110|      0|          break;
  111|   382k|      }
  112|   382k|    }
_ZN5ofats10any_detail14handler_traitsIPvJS2_PN3uWS11HttpRequestEEE13small_handlerIZZNS3_11HttpContextILb0EE4initEvENKUlP11us_socket_tPciE_clESB_SC_iEUlS2_S5_E_E7destroyERNS0_7storageE:
  122|   382k|    static void destroy(storage& s) noexcept {
  123|   382k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|   382k|      value.~T();
  125|   382k|    }
_ZN5ofats10any_detail14handler_traitsIPvJS2_PN3uWS11HttpRequestEEE13small_handlerIZZNS3_11HttpContextILb0EE4initEvENKUlP11us_socket_tPciE_clESB_SC_iEUlS2_S5_E_E4callERNS0_7storageES2_S5_:
  132|  60.4k|    static R call(storage& s, ArgTypes... args) {
  133|  60.4k|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|  60.4k|                         std::forward<ArgTypes>(args)...);
  135|  60.4k|    }
_ZN5ofats13any_invocableIFbPN3uWS10HttpRouterINS1_15HttpContextDataILb0EE10RouterDataEEEEEclES7_:
  345|  70.9k|    R operator()(ArgTypes... args) cv ref noexcept(noex) {                     \
  346|  70.9k|      return base_type::call(std::forward<ArgTypes>(args)...);                 \
  347|  70.9k|    }                                                                          \
_ZN5ofats10any_detail18any_invocable_implIbLb0EJPN3uWS10HttpRouterINS2_15HttpContextDataILb0EE10RouterDataEEEEE4callES8_:
  246|  70.9k|  R call(ArgTypes... args) noexcept(is_noexcept) {
  247|  70.9k|    return call_(storage_, std::forward<ArgTypes>(args)...);
  248|  70.9k|  }
_ZNK5ofats10any_detail18any_invocable_implIvLb0EJNSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEbEEcvbEv:
  228|  53.8k|  explicit operator bool() const noexcept { return handle_ != nullptr; }
_ZN5ofats10any_detail18any_invocable_implIPvLb0EJS2_PN3uWS11HttpRequestEEED2Ev:
  206|   382k|  ~any_invocable_impl() { destroy(); }
_ZN5ofats10any_detail18any_invocable_implIPvLb0EJS2_PN3uWS11HttpRequestEEE7destroyEv:
  239|   382k|  void destroy() noexcept {
  240|   382k|    if (handle_) {
  ------------------
  |  Branch (240:9): [True: 382k, False: 0]
  ------------------
  241|   382k|      handle_(action::destroy, &storage_, nullptr);
  242|   382k|      handle_ = nullptr;
  243|   382k|    }
  244|   382k|  }
_ZN5ofats13any_invocableIFPvS1_NSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEbEEC2IZZN3uWS11HttpContextILb0EE4initEvENKUlP11us_socket_tPciE_clESE_SF_iEUlS1_S6_bE_vEEOT_:
  303|   382k|    any_invocable(F&& f) {                                                     \
  304|   382k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|   382k|    }                                                                          \
_ZN5ofats10any_detail18any_invocable_implIPvLb0EJS2_NSt3__117basic_string_viewIcNS3_11char_traitsIcEEEEbEEC2Ev:
  186|   382k|  any_invocable_impl() noexcept = default;
_ZN5ofats10any_detail18any_invocable_implIPvLb0EJS2_NSt3__117basic_string_viewIcNS3_11char_traitsIcEEEEbEE6createIZZN3uWS11HttpContextILb0EE4initEvENKUlP11us_socket_tPciE_clESE_SF_iEUlS2_S7_bE_JSH_EEEvDpOT0_:
  232|   382k|  void create(Args&&... args) {
  233|   382k|    using hdl = handler<F>;
  234|   382k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|   382k|    handle_ = &hdl::handle;
  236|   382k|    call_ = &hdl::call;
  237|   382k|  }
_ZN5ofats10any_detail14handler_traitsIPvJS2_NSt3__117basic_string_viewIcNS3_11char_traitsIcEEEEbEE13small_handlerIZZN3uWS11HttpContextILb0EE4initEvENKUlP11us_socket_tPciE_clESE_SF_iEUlS2_S7_bE_E6createIJSH_EEEvRNS0_7storageEDpOT_:
  118|   382k|    static void create(storage& s, Args&&... args) {
  119|   382k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|   382k|    }
_ZN5ofats10any_detail14handler_traitsIPvJS2_NSt3__117basic_string_viewIcNS3_11char_traitsIcEEEEbEE12handler_baseINS8_13small_handlerIZZN3uWS11HttpContextILb0EE4initEvENKUlP11us_socket_tPciE_clESF_SG_iEUlS2_S7_bE_EEE6handleENS0_6actionEPNS0_7storageESN_:
  103|   382k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|   382k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 382k]
  ------------------
  105|   382k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 382k, False: 0]
  ------------------
  106|   382k|          Derived::destroy(*current);
  107|   382k|          break;
  108|      0|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 0, False: 382k]
  ------------------
  109|      0|          Derived::move(*current, *other);
  110|      0|          break;
  111|   382k|      }
  112|   382k|    }
_ZN5ofats10any_detail14handler_traitsIPvJS2_NSt3__117basic_string_viewIcNS3_11char_traitsIcEEEEbEE13small_handlerIZZN3uWS11HttpContextILb0EE4initEvENKUlP11us_socket_tPciE_clESE_SF_iEUlS2_S7_bE_E7destroyERNS0_7storageE:
  122|   382k|    static void destroy(storage& s) noexcept {
  123|   382k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|   382k|      value.~T();
  125|   382k|    }
_ZN5ofats10any_detail14handler_traitsIPvJS2_NSt3__117basic_string_viewIcNS3_11char_traitsIcEEEEbEE13small_handlerIZZN3uWS11HttpContextILb0EE4initEvENKUlP11us_socket_tPciE_clESE_SF_iEUlS2_S7_bE_E4callERNS0_7storageES2_S7_b:
  132|  49.5k|    static R call(storage& s, ArgTypes... args) {
  133|  49.5k|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|  49.5k|                         std::forward<ArgTypes>(args)...);
  135|  49.5k|    }
_ZN5ofats13any_invocableIFvNSt3__117basic_string_viewIcNS1_11char_traitsIcEEEEbEEclES5_b:
  345|  34.9k|    R operator()(ArgTypes... args) cv ref noexcept(noex) {                     \
  346|  34.9k|      return base_type::call(std::forward<ArgTypes>(args)...);                 \
  347|  34.9k|    }                                                                          \
_ZN5ofats10any_detail18any_invocable_implIvLb0EJNSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEbEE4callES6_b:
  246|  34.9k|  R call(ArgTypes... args) noexcept(is_noexcept) {
  247|  34.9k|    return call_(storage_, std::forward<ArgTypes>(args)...);
  248|  34.9k|  }
_ZN5ofats13any_invocableIFvNSt3__117basic_string_viewIcNS1_11char_traitsIcEEEEbEEaSIDnDnEENS1_9enable_ifIXaantsr3stdE9is_same_vIT0_S7_Esr3stdE23is_move_constructible_vISA_EERS7_E4typeEOT_:
  335|  3.13k|    operator=(F&& f) {                                                         \
  336|  3.13k|      any_invocable{std::forward<F>(f)}.swap(*this);                           \
  337|  3.13k|      return *this;                                                            \
  338|  3.13k|    }                                                                          \
_ZN5ofats10any_detail18any_invocable_implIvLb0EJNSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEbEEC2EDn:
  187|  3.13k|  any_invocable_impl(std::nullptr_t) noexcept {}
_ZN5ofats10any_detail18any_invocable_implIvLb0EJNSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEbEE4swapERS7_:
  208|  11.7k|  void swap(any_invocable_impl& rhs) noexcept {
  209|  11.7k|    if (handle_) {
  ------------------
  |  Branch (209:9): [True: 4.29k, False: 7.43k]
  ------------------
  210|  4.29k|      if (rhs.handle_) {
  ------------------
  |  Branch (210:11): [True: 0, False: 4.29k]
  ------------------
  211|      0|        storage tmp;
  212|      0|        handle_(action::move, &tmp, &storage_);
  213|      0|        rhs.handle_(action::move, &storage_, &rhs.storage_);
  214|      0|        handle_(action::move, &rhs.storage_, &tmp);
  215|      0|        std::swap(handle_, rhs.handle_);
  216|      0|        std::swap(call_, rhs.call_);
  217|  4.29k|      } else {
  218|  4.29k|        rhs.swap(*this);
  219|  4.29k|      }
  220|  7.43k|    } else if (rhs.handle_) {
  ------------------
  |  Branch (220:16): [True: 7.43k, False: 0]
  ------------------
  221|  7.43k|      rhs.handle_(action::move, &storage_, &rhs.storage_);
  222|  7.43k|      handle_ = rhs.handle_;
  223|  7.43k|      call_ = rhs.call_;
  224|  7.43k|      rhs.handle_ = nullptr;
  225|  7.43k|    }
  226|  11.7k|  }
_ZN5ofats10any_detail18any_invocable_implIPvLb0EJS2_NSt3__117basic_string_viewIcNS3_11char_traitsIcEEEEbEED2Ev:
  206|   382k|  ~any_invocable_impl() { destroy(); }
_ZN5ofats10any_detail18any_invocable_implIPvLb0EJS2_NSt3__117basic_string_viewIcNS3_11char_traitsIcEEEEbEE7destroyEv:
  239|   382k|  void destroy() noexcept {
  240|   382k|    if (handle_) {
  ------------------
  |  Branch (240:9): [True: 382k, False: 0]
  ------------------
  241|   382k|      handle_(action::destroy, &storage_, nullptr);
  242|   382k|      handle_ = nullptr;
  243|   382k|    }
  244|   382k|  }
_ZNK5ofats10any_detail18any_invocable_implIbLb0EJmEEcvbEv:
  228|  2.65k|  explicit operator bool() const noexcept { return handle_ != nullptr; }
_ZN5ofats10any_detail18any_invocable_implIbLb0EJmEE4swapERS2_:
  208|  58.1k|  void swap(any_invocable_impl& rhs) noexcept {
  209|  58.1k|    if (handle_) {
  ------------------
  |  Branch (209:9): [True: 0, False: 58.1k]
  ------------------
  210|      0|      if (rhs.handle_) {
  ------------------
  |  Branch (210:11): [True: 0, False: 0]
  ------------------
  211|      0|        storage tmp;
  212|      0|        handle_(action::move, &tmp, &storage_);
  213|      0|        rhs.handle_(action::move, &storage_, &rhs.storage_);
  214|      0|        handle_(action::move, &rhs.storage_, &tmp);
  215|      0|        std::swap(handle_, rhs.handle_);
  216|      0|        std::swap(call_, rhs.call_);
  217|      0|      } else {
  218|      0|        rhs.swap(*this);
  219|      0|      }
  220|  58.1k|    } else if (rhs.handle_) {
  ------------------
  |  Branch (220:16): [True: 0, False: 58.1k]
  ------------------
  221|      0|      rhs.handle_(action::move, &storage_, &rhs.storage_);
  222|      0|      handle_ = rhs.handle_;
  223|      0|      call_ = rhs.call_;
  224|      0|      rhs.handle_ = nullptr;
  225|      0|    }
  226|  58.1k|  }
_ZN5ofats13any_invocableIFvPN3uWS12HttpResponseILb0EEEPNS1_11HttpRequestEEEC2IZNS1_12TemplatedAppILb0EEC1ENS1_20SocketContextOptionsEEUlPT_PT0_E_vEEOSD_:
  303|  6.41k|    any_invocable(F&& f) {                                                     \
  304|  6.41k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  6.41k|    }                                                                          \
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEEC2Ev:
  186|  38.4k|  any_invocable_impl() noexcept = default;
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE6createIZNS2_12TemplatedAppILb0EEC1ENS2_20SocketContextOptionsEEUlPT_PT0_E_JSH_EEEvDpOT0_:
  232|  6.41k|  void create(Args&&... args) {
  233|  6.41k|    using hdl = handler<F>;
  234|  6.41k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  6.41k|    handle_ = &hdl::handle;
  236|  6.41k|    call_ = &hdl::call;
  237|  6.41k|  }
_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13small_handlerIZNS2_12TemplatedAppILb0EEC1ENS2_20SocketContextOptionsEEUlPT_PT0_E_E6createIJSH_EEEvRNS0_7storageEDpOT_:
  118|  19.2k|    static void create(storage& s, Args&&... args) {
  119|  19.2k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|  19.2k|    }
_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE12handler_baseINS8_13small_handlerIZNS2_12TemplatedAppILb0EEC1ENS2_20SocketContextOptionsEEUlPT_PT0_E_EEE6handleENS0_6actionEPNS0_7storageESN_:
  103|  19.2k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  19.2k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 19.2k]
  ------------------
  105|  6.41k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 6.41k, False: 12.8k]
  ------------------
  106|  6.41k|          Derived::destroy(*current);
  107|  6.41k|          break;
  108|  12.8k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 12.8k, False: 6.41k]
  ------------------
  109|  12.8k|          Derived::move(*current, *other);
  110|  12.8k|          break;
  111|  19.2k|      }
  112|  19.2k|    }
_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13small_handlerIZNS2_12TemplatedAppILb0EEC1ENS2_20SocketContextOptionsEEUlPT_PT0_E_E7destroyERNS0_7storageE:
  122|  19.2k|    static void destroy(storage& s) noexcept {
  123|  19.2k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|  19.2k|      value.~T();
  125|  19.2k|    }
_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13small_handlerIZNS2_12TemplatedAppILb0EEC1ENS2_20SocketContextOptionsEEUlPT_PT0_E_E4moveERNS0_7storageESK_:
  127|  12.8k|    static void move(storage& dst, storage& src) noexcept {
  128|  12.8k|      create(dst, std::move(*static_cast<T*>(static_cast<void*>(&src.buf_))));
  129|  12.8k|      destroy(src);
  130|  12.8k|    }
_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13small_handlerIZNS2_12TemplatedAppILb0EEC1ENS2_20SocketContextOptionsEEUlPT_PT0_E_E4callERNS0_7storageES5_S7_:
  132|  4.04k|    static R call(storage& s, ArgTypes... args) {
  133|  4.04k|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|  4.04k|                         std::forward<ArgTypes>(args)...);
  135|  4.04k|    }
_ZN5ofats13any_invocableIFvvEEaSIDnDnEENSt3__19enable_ifIXaantsr3stdE9is_same_vIT0_S2_Esr3stdE23is_move_constructible_vIS6_EERS2_E4typeEOT_:
  335|  58.1k|    operator=(F&& f) {                                                         \
  336|  58.1k|      any_invocable{std::forward<F>(f)}.swap(*this);                           \
  337|  58.1k|      return *this;                                                            \
  338|  58.1k|    }                                                                          \
_ZN5ofats10any_detail18any_invocable_implIvLb0EJEEC2EDn:
  187|  58.1k|  any_invocable_impl(std::nullptr_t) noexcept {}
_ZN5ofats10any_detail18any_invocable_implIvLb0EJEE4swapERS2_:
  208|  66.7k|  void swap(any_invocable_impl& rhs) noexcept {
  209|  66.7k|    if (handle_) {
  ------------------
  |  Branch (209:9): [True: 4.29k, False: 62.4k]
  ------------------
  210|  4.29k|      if (rhs.handle_) {
  ------------------
  |  Branch (210:11): [True: 0, False: 4.29k]
  ------------------
  211|      0|        storage tmp;
  212|      0|        handle_(action::move, &tmp, &storage_);
  213|      0|        rhs.handle_(action::move, &storage_, &rhs.storage_);
  214|      0|        handle_(action::move, &rhs.storage_, &tmp);
  215|      0|        std::swap(handle_, rhs.handle_);
  216|      0|        std::swap(call_, rhs.call_);
  217|  4.29k|      } else {
  218|  4.29k|        rhs.swap(*this);
  219|  4.29k|      }
  220|  62.4k|    } else if (rhs.handle_) {
  ------------------
  |  Branch (220:16): [True: 7.43k, False: 54.9k]
  ------------------
  221|  7.43k|      rhs.handle_(action::move, &storage_, &rhs.storage_);
  222|  7.43k|      handle_ = rhs.handle_;
  223|  7.43k|      call_ = rhs.call_;
  224|  7.43k|      rhs.handle_ = nullptr;
  225|  7.43k|    }
  226|  66.7k|  }
_ZN5ofats13any_invocableIFbmEEaSIDnDnEENSt3__19enable_ifIXaantsr3stdE9is_same_vIT0_S2_Esr3stdE23is_move_constructible_vIS6_EERS2_E4typeEOT_:
  335|  58.1k|    operator=(F&& f) {                                                         \
  336|  58.1k|      any_invocable{std::forward<F>(f)}.swap(*this);                           \
  337|  58.1k|      return *this;                                                            \
  338|  58.1k|    }                                                                          \
_ZN5ofats10any_detail18any_invocable_implIbLb0EJmEEC2EDn:
  187|  58.1k|  any_invocable_impl(std::nullptr_t) noexcept {}
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS4LoopEEEC2EOS5_:
  188|  12.8k|  any_invocable_impl(any_invocable_impl&& rhs) noexcept {
  189|  12.8k|    if (rhs.handle_) {
  ------------------
  |  Branch (189:9): [True: 12.8k, False: 0]
  ------------------
  190|  12.8k|      handle_ = rhs.handle_;
  191|  12.8k|      handle_(action::move, &storage_, &rhs.storage_);
  192|  12.8k|      call_ = rhs.call_;
  193|  12.8k|      rhs.handle_ = nullptr;
  194|  12.8k|    }
  195|  12.8k|  }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvPN3uWS4LoopEEEC2IZNS1_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS8_NSt3__112basic_stringIcNSC_11char_traitsIcEENSC_9allocatorIcEEEEONS8_17WebSocketBehaviorIT_EEEUlS3_E_vEEOSK_:
  303|  6.41k|    any_invocable(F&& f) {                                                     \
  304|  6.41k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  6.41k|    }                                                                          \
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS4LoopEEEC2Ev:
  186|  12.8k|  any_invocable_impl() noexcept = default;
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS4LoopEEE6createIZNS2_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS8_NSt3__112basic_stringIcNSC_11char_traitsIcEENSC_9allocatorIcEEEEONS8_17WebSocketBehaviorIT_EEEUlS4_E_JSN_EEEvDpOT0_:
  232|  6.41k|  void create(Args&&... args) {
  233|  6.41k|    using hdl = handler<F>;
  234|  6.41k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  6.41k|    handle_ = &hdl::handle;
  236|  6.41k|    call_ = &hdl::call;
  237|  6.41k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS4LoopEEE13small_handlerIZNS2_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS8_NSt3__112basic_stringIcNSC_11char_traitsIcEENSC_9allocatorIcEEEEONS8_17WebSocketBehaviorIT_EEEUlS4_E_E6createIJSN_EEEvRNS0_7storageEDpOT_:
  118|  12.8k|    static void create(storage& s, Args&&... args) {
  119|  12.8k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|  12.8k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS4LoopEEE12handler_baseINS5_13small_handlerIZNS2_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS9_NSt3__112basic_stringIcNSD_11char_traitsIcEENSD_9allocatorIcEEEEONS9_17WebSocketBehaviorIT_EEEUlS4_E_EEE6handleENS0_6actionEPNS0_7storageEST_:
  103|  12.8k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  12.8k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 12.8k]
  ------------------
  105|  6.41k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 6.41k, False: 6.41k]
  ------------------
  106|  6.41k|          Derived::destroy(*current);
  107|  6.41k|          break;
  108|  6.41k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 6.41k, False: 6.41k]
  ------------------
  109|  6.41k|          Derived::move(*current, *other);
  110|  6.41k|          break;
  111|  12.8k|      }
  112|  12.8k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS4LoopEEE13small_handlerIZNS2_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS8_NSt3__112basic_stringIcNSC_11char_traitsIcEENSC_9allocatorIcEEEEONS8_17WebSocketBehaviorIT_EEEUlS4_E_E7destroyERNS0_7storageE:
  122|  12.8k|    static void destroy(storage& s) noexcept {
  123|  12.8k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|  12.8k|      value.~T();
  125|  12.8k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS4LoopEEE13small_handlerIZNS2_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS8_NSt3__112basic_stringIcNSC_11char_traitsIcEENSC_9allocatorIcEEEEONS8_17WebSocketBehaviorIT_EEEUlS4_E_E4moveERNS0_7storageESQ_:
  127|  6.41k|    static void move(storage& dst, storage& src) noexcept {
  128|  6.41k|      create(dst, std::move(*static_cast<T*>(static_cast<void*>(&src.buf_))));
  129|  6.41k|      destroy(src);
  130|  6.41k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS4LoopEEE13small_handlerIZNS2_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS8_NSt3__112basic_stringIcNSC_11char_traitsIcEENSC_9allocatorIcEEEEONS8_17WebSocketBehaviorIT_EEEUlS4_E_E4callERNS0_7storageES4_:
  132|  1.59M|    static R call(storage& s, ArgTypes... args) {
  133|  1.59M|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|  1.59M|                         std::forward<ArgTypes>(args)...);
  135|  1.59M|    }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvPN3uWS4LoopEEEC2IZNS1_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS8_NSt3__112basic_stringIcNSC_11char_traitsIcEENSC_9allocatorIcEEEEONS8_17WebSocketBehaviorIT_EEEUlS3_E0_vEEOSK_:
  303|  6.41k|    any_invocable(F&& f) {                                                     \
  304|  6.41k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  6.41k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS4LoopEEE6createIZNS2_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS8_NSt3__112basic_stringIcNSC_11char_traitsIcEENSC_9allocatorIcEEEEONS8_17WebSocketBehaviorIT_EEEUlS4_E0_JSN_EEEvDpOT0_:
  232|  6.41k|  void create(Args&&... args) {
  233|  6.41k|    using hdl = handler<F>;
  234|  6.41k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  6.41k|    handle_ = &hdl::handle;
  236|  6.41k|    call_ = &hdl::call;
  237|  6.41k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS4LoopEEE13small_handlerIZNS2_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS8_NSt3__112basic_stringIcNSC_11char_traitsIcEENSC_9allocatorIcEEEEONS8_17WebSocketBehaviorIT_EEEUlS4_E0_E6createIJSN_EEEvRNS0_7storageEDpOT_:
  118|  12.8k|    static void create(storage& s, Args&&... args) {
  119|  12.8k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|  12.8k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS4LoopEEE12handler_baseINS5_13small_handlerIZNS2_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS9_NSt3__112basic_stringIcNSD_11char_traitsIcEENSD_9allocatorIcEEEEONS9_17WebSocketBehaviorIT_EEEUlS4_E0_EEE6handleENS0_6actionEPNS0_7storageEST_:
  103|  12.8k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  12.8k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 12.8k]
  ------------------
  105|  6.41k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 6.41k, False: 6.41k]
  ------------------
  106|  6.41k|          Derived::destroy(*current);
  107|  6.41k|          break;
  108|  6.41k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 6.41k, False: 6.41k]
  ------------------
  109|  6.41k|          Derived::move(*current, *other);
  110|  6.41k|          break;
  111|  12.8k|      }
  112|  12.8k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS4LoopEEE13small_handlerIZNS2_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS8_NSt3__112basic_stringIcNSC_11char_traitsIcEENSC_9allocatorIcEEEEONS8_17WebSocketBehaviorIT_EEEUlS4_E0_E7destroyERNS0_7storageE:
  122|  12.8k|    static void destroy(storage& s) noexcept {
  123|  12.8k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|  12.8k|      value.~T();
  125|  12.8k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS4LoopEEE13small_handlerIZNS2_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS8_NSt3__112basic_stringIcNSC_11char_traitsIcEENSC_9allocatorIcEEEEONS8_17WebSocketBehaviorIT_EEEUlS4_E0_E4moveERNS0_7storageESQ_:
  127|  6.41k|    static void move(storage& dst, storage& src) noexcept {
  128|  6.41k|      create(dst, std::move(*static_cast<T*>(static_cast<void*>(&src.buf_))));
  129|  6.41k|      destroy(src);
  130|  6.41k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS4LoopEEE13small_handlerIZNS2_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS8_NSt3__112basic_stringIcNSC_11char_traitsIcEENSC_9allocatorIcEEEEONS8_17WebSocketBehaviorIT_EEEUlS4_E0_E4callERNS0_7storageES4_:
  132|  1.59M|    static R call(storage& s, ArgTypes... args) {
  133|  1.59M|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|  1.59M|                         std::forward<ArgTypes>(args)...);
  135|  1.59M|    }
EpollHelloWorld.cpp:_ZNK5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEEcvbEv:
  228|  80.3k|  explicit operator bool() const noexcept { return handle_ != nullptr; }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS6_11char_traitsIcEEEEEEclES5_iSA_:
  345|  79.2k|    R operator()(ArgTypes... args) cv ref noexcept(noex) {                     \
  346|  79.2k|      return base_type::call(std::forward<ArgTypes>(args)...);                 \
  347|  79.2k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE4callES6_iSB_:
  246|  79.2k|  R call(ArgTypes... args) noexcept(is_noexcept) {
  247|  79.2k|    return call_(storage_, std::forward<ArgTypes>(args)...);
  248|  79.2k|  }
EpollHelloWorld.cpp:_ZNK5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEENS2_6OpCodeEEEcvbEv:
  228|  12.6k|  explicit operator bool() const noexcept { return handle_ != nullptr; }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS6_11char_traitsIcEEEENS1_6OpCodeEEEclES5_SA_SB_:
  345|  10.0k|    R operator()(ArgTypes... args) cv ref noexcept(noex) {                     \
  346|  10.0k|      return base_type::call(std::forward<ArgTypes>(args)...);                 \
  347|  10.0k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEENS2_6OpCodeEEE4callES6_SB_SC_:
  246|  10.0k|  R call(ArgTypes... args) noexcept(is_noexcept) {
  247|  10.0k|    return call_(storage_, std::forward<ArgTypes>(args)...);
  248|  10.0k|  }
EpollHelloWorld.cpp:_ZNK5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEEcvbEv:
  228|  8.71k|  explicit operator bool() const noexcept { return handle_ != nullptr; }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS6_11char_traitsIcEEEEEEclES5_SA_:
  345|  7.63k|    R operator()(ArgTypes... args) cv ref noexcept(noex) {                     \
  346|  7.63k|      return base_type::call(std::forward<ArgTypes>(args)...);                 \
  347|  7.63k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE4callES6_SB_:
  246|  7.63k|  R call(ArgTypes... args) noexcept(is_noexcept) {
  247|  7.63k|    return call_(storage_, std::forward<ArgTypes>(args)...);
  248|  7.63k|  }
EpollHelloWorld.cpp:_ZNK5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEcvbEv:
  228|  45.4k|  explicit operator bool() const noexcept { return handle_ != nullptr; }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEclES5_:
  345|  44.1k|    R operator()(ArgTypes... args) cv ref noexcept(noex) {                     \
  346|  44.1k|      return base_type::call(std::forward<ArgTypes>(args)...);                 \
  347|  44.1k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEE4callES6_:
  246|  44.1k|  R call(ArgTypes... args) noexcept(is_noexcept) {
  247|  44.1k|    return call_(storage_, std::forward<ArgTypes>(args)...);
  248|  44.1k|  }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJEEC2EOS2_:
  188|  37.8k|  any_invocable_impl(any_invocable_impl&& rhs) noexcept {
  189|  37.8k|    if (rhs.handle_) {
  ------------------
  |  Branch (189:9): [True: 37.8k, False: 0]
  ------------------
  190|  37.8k|      handle_ = rhs.handle_;
  191|  37.8k|      handle_(action::move, &storage_, &rhs.storage_);
  192|  37.8k|      call_ = rhs.call_;
  193|  37.8k|      rhs.handle_ = nullptr;
  194|  37.8k|    }
  195|  37.8k|  }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvvEEC2IZN3uWS12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS6_NSt3__112basic_stringIcNSA_11char_traitsIcEENSA_9allocatorIcEEEEONS6_17WebSocketBehaviorIT_EEEUlvE_vEEOSI_:
  303|  12.8k|    any_invocable(F&& f) {                                                     \
  304|  12.8k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  12.8k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJEE6createIZN3uWS12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS6_NSt3__112basic_stringIcNSA_11char_traitsIcEENSA_9allocatorIcEEEEONS6_17WebSocketBehaviorIT_EEEUlvE_JSL_EEEvDpOT0_:
  232|  12.8k|  void create(Args&&... args) {
  233|  12.8k|    using hdl = handler<F>;
  234|  12.8k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  12.8k|    handle_ = &hdl::handle;
  236|  12.8k|    call_ = &hdl::call;
  237|  12.8k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE13small_handlerIZN3uWS12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS6_NSt3__112basic_stringIcNSA_11char_traitsIcEENSA_9allocatorIcEEEEONS6_17WebSocketBehaviorIT_EEEUlvE_E6createIJSL_EEEvRNS0_7storageEDpOT_:
  118|  32.0k|    static void create(storage& s, Args&&... args) {
  119|  32.0k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|  32.0k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE12handler_baseINS2_13small_handlerIZN3uWS12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS7_NSt3__112basic_stringIcNSB_11char_traitsIcEENSB_9allocatorIcEEEEONS7_17WebSocketBehaviorIT_EEEUlvE_EEE6handleENS0_6actionEPNS0_7storageESR_:
  103|  32.0k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  32.0k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 32.0k]
  ------------------
  105|  12.8k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 12.8k, False: 19.2k]
  ------------------
  106|  12.8k|          Derived::destroy(*current);
  107|  12.8k|          break;
  108|  19.2k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 19.2k, False: 12.8k]
  ------------------
  109|  19.2k|          Derived::move(*current, *other);
  110|  19.2k|          break;
  111|  32.0k|      }
  112|  32.0k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE13small_handlerIZN3uWS12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS6_NSt3__112basic_stringIcNSA_11char_traitsIcEENSA_9allocatorIcEEEEONS6_17WebSocketBehaviorIT_EEEUlvE_E7destroyERNS0_7storageE:
  122|  32.0k|    static void destroy(storage& s) noexcept {
  123|  32.0k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|  32.0k|      value.~T();
  125|  32.0k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE13small_handlerIZN3uWS12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS6_NSt3__112basic_stringIcNSA_11char_traitsIcEENSA_9allocatorIcEEEEONS6_17WebSocketBehaviorIT_EEEUlvE_E4moveERNS0_7storageESO_:
  127|  19.2k|    static void move(storage& dst, storage& src) noexcept {
  128|  19.2k|      create(dst, std::move(*static_cast<T*>(static_cast<void*>(&src.buf_))));
  129|  19.2k|      destroy(src);
  130|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE13small_handlerIZN3uWS12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOS6_NSt3__112basic_stringIcNSA_11char_traitsIcEENSA_9allocatorIcEEEEONS6_17WebSocketBehaviorIT_EEEUlvE_E4callERNS0_7storageE:
  132|  12.8k|    static R call(storage& s, ArgTypes... args) {
  133|  12.8k|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|  12.8k|                         std::forward<ArgTypes>(args)...);
  135|  12.8k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEaSEOS7_:
  197|  25.6k|  any_invocable_impl& operator=(any_invocable_impl&& rhs) noexcept {
  198|  25.6k|    any_invocable_impl{std::move(rhs)}.swap(*this);
  199|  25.6k|    return *this;
  200|  25.6k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEC2EOS7_:
  188|  76.9k|  any_invocable_impl(any_invocable_impl&& rhs) noexcept {
  189|  76.9k|    if (rhs.handle_) {
  ------------------
  |  Branch (189:9): [True: 12.8k, False: 64.1k]
  ------------------
  190|  12.8k|      handle_ = rhs.handle_;
  191|  12.8k|      handle_(action::move, &storage_, &rhs.storage_);
  192|  12.8k|      call_ = rhs.call_;
  193|  12.8k|      rhs.handle_ = nullptr;
  194|  12.8k|    }
  195|  76.9k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEE4swapERS7_:
  208|  38.4k|  void swap(any_invocable_impl& rhs) noexcept {
  209|  38.4k|    if (handle_) {
  ------------------
  |  Branch (209:9): [True: 12.8k, False: 25.6k]
  ------------------
  210|  12.8k|      if (rhs.handle_) {
  ------------------
  |  Branch (210:11): [True: 0, False: 12.8k]
  ------------------
  211|      0|        storage tmp;
  212|      0|        handle_(action::move, &tmp, &storage_);
  213|      0|        rhs.handle_(action::move, &storage_, &rhs.storage_);
  214|      0|        handle_(action::move, &rhs.storage_, &tmp);
  215|      0|        std::swap(handle_, rhs.handle_);
  216|      0|        std::swap(call_, rhs.call_);
  217|  12.8k|      } else {
  218|  12.8k|        rhs.swap(*this);
  219|  12.8k|      }
  220|  25.6k|    } else if (rhs.handle_) {
  ------------------
  |  Branch (220:16): [True: 12.8k, False: 12.8k]
  ------------------
  221|  12.8k|      rhs.handle_(action::move, &storage_, &rhs.storage_);
  222|  12.8k|      handle_ = rhs.handle_;
  223|  12.8k|      call_ = rhs.call_;
  224|  12.8k|      rhs.handle_ = nullptr;
  225|  12.8k|    }
  226|  38.4k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEENS2_6OpCodeEEEaSEOSD_:
  197|  25.6k|  any_invocable_impl& operator=(any_invocable_impl&& rhs) noexcept {
  198|  25.6k|    any_invocable_impl{std::move(rhs)}.swap(*this);
  199|  25.6k|    return *this;
  200|  25.6k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEENS2_6OpCodeEEEC2EOSD_:
  188|  76.9k|  any_invocable_impl(any_invocable_impl&& rhs) noexcept {
  189|  76.9k|    if (rhs.handle_) {
  ------------------
  |  Branch (189:9): [True: 6.41k, False: 70.5k]
  ------------------
  190|  6.41k|      handle_ = rhs.handle_;
  191|  6.41k|      handle_(action::move, &storage_, &rhs.storage_);
  192|  6.41k|      call_ = rhs.call_;
  193|  6.41k|      rhs.handle_ = nullptr;
  194|  6.41k|    }
  195|  76.9k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEENS2_6OpCodeEEE4swapERSD_:
  208|  32.0k|  void swap(any_invocable_impl& rhs) noexcept {
  209|  32.0k|    if (handle_) {
  ------------------
  |  Branch (209:9): [True: 6.41k, False: 25.6k]
  ------------------
  210|  6.41k|      if (rhs.handle_) {
  ------------------
  |  Branch (210:11): [True: 0, False: 6.41k]
  ------------------
  211|      0|        storage tmp;
  212|      0|        handle_(action::move, &tmp, &storage_);
  213|      0|        rhs.handle_(action::move, &storage_, &rhs.storage_);
  214|      0|        handle_(action::move, &rhs.storage_, &tmp);
  215|      0|        std::swap(handle_, rhs.handle_);
  216|      0|        std::swap(call_, rhs.call_);
  217|  6.41k|      } else {
  218|  6.41k|        rhs.swap(*this);
  219|  6.41k|      }
  220|  25.6k|    } else if (rhs.handle_) {
  ------------------
  |  Branch (220:16): [True: 6.41k, False: 19.2k]
  ------------------
  221|  6.41k|      rhs.handle_(action::move, &storage_, &rhs.storage_);
  222|  6.41k|      handle_ = rhs.handle_;
  223|  6.41k|      call_ = rhs.call_;
  224|  6.41k|      rhs.handle_ = nullptr;
  225|  6.41k|    }
  226|  32.0k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEiiEEaSEOSC_:
  197|  12.8k|  any_invocable_impl& operator=(any_invocable_impl&& rhs) noexcept {
  198|  12.8k|    any_invocable_impl{std::move(rhs)}.swap(*this);
  199|  12.8k|    return *this;
  200|  12.8k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEiiEEC2EOSC_:
  188|  38.4k|  any_invocable_impl(any_invocable_impl&& rhs) noexcept {
  189|  38.4k|    if (rhs.handle_) {
  ------------------
  |  Branch (189:9): [True: 0, False: 38.4k]
  ------------------
  190|      0|      handle_ = rhs.handle_;
  191|      0|      handle_(action::move, &storage_, &rhs.storage_);
  192|      0|      call_ = rhs.call_;
  193|      0|      rhs.handle_ = nullptr;
  194|      0|    }
  195|  38.4k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEiiEE4swapERSC_:
  208|  12.8k|  void swap(any_invocable_impl& rhs) noexcept {
  209|  12.8k|    if (handle_) {
  ------------------
  |  Branch (209:9): [True: 0, False: 12.8k]
  ------------------
  210|      0|      if (rhs.handle_) {
  ------------------
  |  Branch (210:11): [True: 0, False: 0]
  ------------------
  211|      0|        storage tmp;
  212|      0|        handle_(action::move, &tmp, &storage_);
  213|      0|        rhs.handle_(action::move, &storage_, &rhs.storage_);
  214|      0|        handle_(action::move, &rhs.storage_, &tmp);
  215|      0|        std::swap(handle_, rhs.handle_);
  216|      0|        std::swap(call_, rhs.call_);
  217|      0|      } else {
  218|      0|        rhs.swap(*this);
  219|      0|      }
  220|  12.8k|    } else if (rhs.handle_) {
  ------------------
  |  Branch (220:16): [True: 0, False: 12.8k]
  ------------------
  221|      0|      rhs.handle_(action::move, &storage_, &rhs.storage_);
  222|      0|      handle_ = rhs.handle_;
  223|      0|      call_ = rhs.call_;
  224|      0|      rhs.handle_ = nullptr;
  225|      0|    }
  226|  12.8k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEEC2EOSC_:
  188|  51.3k|  any_invocable_impl(any_invocable_impl&& rhs) noexcept {
  189|  51.3k|    if (rhs.handle_) {
  ------------------
  |  Branch (189:9): [True: 12.8k, False: 38.4k]
  ------------------
  190|  12.8k|      handle_ = rhs.handle_;
  191|  12.8k|      handle_(action::move, &storage_, &rhs.storage_);
  192|  12.8k|      call_ = rhs.call_;
  193|  12.8k|      rhs.handle_ = nullptr;
  194|  12.8k|    }
  195|  51.3k|  }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS6_11char_traitsIcEEEEEEaSIZNS1_12TemplatedAppILb0EE2wsIS3_EEOSF_NS6_12basic_stringIcS9_NS6_9allocatorIcEEEEONSF_17WebSocketBehaviorIT_EEEUlS5_iSA_E_SQ_EENS6_9enable_ifIXaantsr3stdE9is_same_vIT0_SC_Esr3stdE23is_move_constructible_vISS_EERSC_E4typeEOSN_:
  335|  12.8k|    operator=(F&& f) {                                                         \
  336|  12.8k|      any_invocable{std::forward<F>(f)}.swap(*this);                           \
  337|  12.8k|      return *this;                                                            \
  338|  12.8k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS6_11char_traitsIcEEEEEEC2IZNS1_12TemplatedAppILb0EE2wsIS3_EEOSF_NS6_12basic_stringIcS9_NS6_9allocatorIcEEEEONSF_17WebSocketBehaviorIT_EEEUlS5_iSA_E_vEEOSN_:
  303|  12.8k|    any_invocable(F&& f) {                                                     \
  304|  12.8k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  12.8k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEEC2Ev:
  186|  19.2k|  any_invocable_impl() noexcept = default;
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE6createIZNS2_12TemplatedAppILb0EE2wsIS4_EEOSF_NS7_12basic_stringIcSA_NS7_9allocatorIcEEEEONSF_17WebSocketBehaviorIT_EEEUlS6_iSB_E_JSQ_EEEvDpOT0_:
  232|  12.8k|  void create(Args&&... args) {
  233|  12.8k|    using hdl = handler<F>;
  234|  12.8k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  12.8k|    handle_ = &hdl::handle;
  236|  12.8k|    call_ = &hdl::call;
  237|  12.8k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE13large_handlerIZNS2_12TemplatedAppILb0EE2wsIS4_EEOSF_NS7_12basic_stringIcSA_NS7_9allocatorIcEEEEONSF_17WebSocketBehaviorIT_EEEUlS6_iSB_E_E6createIJSQ_EEEvRNS0_7storageEDpOT_:
  141|  12.8k|    static void create(storage& s, Args&&... args) {
  142|  12.8k|      s.ptr_ = new T(std::forward<Args>(args)...);
  143|  12.8k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE12handler_baseINSC_13large_handlerIZNS2_12TemplatedAppILb0EE2wsIS4_EEOSG_NS7_12basic_stringIcSA_NS7_9allocatorIcEEEEONSG_17WebSocketBehaviorIT_EEEUlS6_iSB_E_EEE6handleENS0_6actionEPNS0_7storageESW_:
  103|  25.6k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  25.6k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 25.6k]
  ------------------
  105|  12.8k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 12.8k, False: 12.8k]
  ------------------
  106|  12.8k|          Derived::destroy(*current);
  107|  12.8k|          break;
  108|  12.8k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 12.8k, False: 12.8k]
  ------------------
  109|  12.8k|          Derived::move(*current, *other);
  110|  12.8k|          break;
  111|  25.6k|      }
  112|  25.6k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE13large_handlerIZNS2_12TemplatedAppILb0EE2wsIS4_EEOSF_NS7_12basic_stringIcSA_NS7_9allocatorIcEEEEONSF_17WebSocketBehaviorIT_EEEUlS6_iSB_E_E7destroyERNS0_7storageE:
  145|  12.8k|    static void destroy(storage& s) noexcept { delete static_cast<T*>(s.ptr_); }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE13large_handlerIZNS2_12TemplatedAppILb0EE2wsIS4_EEOSF_NS7_12basic_stringIcSA_NS7_9allocatorIcEEEEONSF_17WebSocketBehaviorIT_EEEUlS6_iSB_E_E4moveERNS0_7storageEST_:
  147|  12.8k|    static void move(storage& dst, storage& src) noexcept {
  148|  12.8k|      dst.ptr_ = src.ptr_;
  149|  12.8k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE13large_handlerIZNS2_12TemplatedAppILb0EE2wsIS4_EEOSF_NS7_12basic_stringIcSA_NS7_9allocatorIcEEEEONSF_17WebSocketBehaviorIT_EEEUlS6_iSB_E_E4callERNS0_7storageES6_iSB_:
  151|  40.1k|    static R call(storage& s, ArgTypes... args) {
  152|  40.1k|      return std::invoke(*static_cast<T*>(s.ptr_),
  153|  40.1k|                         std::forward<ArgTypes>(args)...);
  154|  40.1k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE4swapERSC_:
  208|  25.6k|  void swap(any_invocable_impl& rhs) noexcept {
  209|  25.6k|    if (handle_) {
  ------------------
  |  Branch (209:9): [True: 12.8k, False: 12.8k]
  ------------------
  210|  12.8k|      if (rhs.handle_) {
  ------------------
  |  Branch (210:11): [True: 0, False: 12.8k]
  ------------------
  211|      0|        storage tmp;
  212|      0|        handle_(action::move, &tmp, &storage_);
  213|      0|        rhs.handle_(action::move, &storage_, &rhs.storage_);
  214|      0|        handle_(action::move, &rhs.storage_, &tmp);
  215|      0|        std::swap(handle_, rhs.handle_);
  216|      0|        std::swap(call_, rhs.call_);
  217|  12.8k|      } else {
  218|  12.8k|        rhs.swap(*this);
  219|  12.8k|      }
  220|  12.8k|    } else if (rhs.handle_) {
  ------------------
  |  Branch (220:16): [True: 12.8k, False: 0]
  ------------------
  221|  12.8k|      rhs.handle_(action::move, &storage_, &rhs.storage_);
  222|  12.8k|      handle_ = rhs.handle_;
  223|  12.8k|      call_ = rhs.call_;
  224|  12.8k|      rhs.handle_ = nullptr;
  225|  12.8k|    }
  226|  25.6k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEEaSEOSC_:
  197|  25.6k|  any_invocable_impl& operator=(any_invocable_impl&& rhs) noexcept {
  198|  25.6k|    any_invocable_impl{std::move(rhs)}.swap(*this);
  199|  25.6k|    return *this;
  200|  25.6k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEEC2EOSC_:
  188|  76.9k|  any_invocable_impl(any_invocable_impl&& rhs) noexcept {
  189|  76.9k|    if (rhs.handle_) {
  ------------------
  |  Branch (189:9): [True: 12.8k, False: 64.1k]
  ------------------
  190|  12.8k|      handle_ = rhs.handle_;
  191|  12.8k|      handle_(action::move, &storage_, &rhs.storage_);
  192|  12.8k|      call_ = rhs.call_;
  193|  12.8k|      rhs.handle_ = nullptr;
  194|  12.8k|    }
  195|  76.9k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE4swapERSC_:
  208|  38.4k|  void swap(any_invocable_impl& rhs) noexcept {
  209|  38.4k|    if (handle_) {
  ------------------
  |  Branch (209:9): [True: 12.8k, False: 25.6k]
  ------------------
  210|  12.8k|      if (rhs.handle_) {
  ------------------
  |  Branch (210:11): [True: 0, False: 12.8k]
  ------------------
  211|      0|        storage tmp;
  212|      0|        handle_(action::move, &tmp, &storage_);
  213|      0|        rhs.handle_(action::move, &storage_, &rhs.storage_);
  214|      0|        handle_(action::move, &rhs.storage_, &tmp);
  215|      0|        std::swap(handle_, rhs.handle_);
  216|      0|        std::swap(call_, rhs.call_);
  217|  12.8k|      } else {
  218|  12.8k|        rhs.swap(*this);
  219|  12.8k|      }
  220|  25.6k|    } else if (rhs.handle_) {
  ------------------
  |  Branch (220:16): [True: 12.8k, False: 12.8k]
  ------------------
  221|  12.8k|      rhs.handle_(action::move, &storage_, &rhs.storage_);
  222|  12.8k|      handle_ = rhs.handle_;
  223|  12.8k|      call_ = rhs.call_;
  224|  12.8k|      rhs.handle_ = nullptr;
  225|  12.8k|    }
  226|  38.4k|  }
_ZNK5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEEcvbEv:
  228|  38.4k|  explicit operator bool() const noexcept { return handle_ != nullptr; }
_ZN5ofats10any_detail18any_invocable_implIbLb0EJPN3uWS10HttpRouterINS2_15HttpContextDataILb0EE10RouterDataEEEEEC2EOS9_:
  188|  83.3k|  any_invocable_impl(any_invocable_impl&& rhs) noexcept {
  189|  83.3k|    if (rhs.handle_) {
  ------------------
  |  Branch (189:9): [True: 83.3k, False: 0]
  ------------------
  190|  83.3k|      handle_ = rhs.handle_;
  191|  83.3k|      handle_(action::move, &storage_, &rhs.storage_);
  192|  83.3k|      call_ = rhs.call_;
  193|  83.3k|      rhs.handle_ = nullptr;
  194|  83.3k|    }
  195|  83.3k|  }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEEC2EOS8_:
  188|  76.9k|  any_invocable_impl(any_invocable_impl&& rhs) noexcept {
  189|  76.9k|    if (rhs.handle_) {
  ------------------
  |  Branch (189:9): [True: 76.9k, False: 0]
  ------------------
  190|  76.9k|      handle_ = rhs.handle_;
  191|  76.9k|      handle_(action::move, &storage_, &rhs.storage_);
  192|  76.9k|      call_ = rhs.call_;
  193|  76.9k|      rhs.handle_ = nullptr;
  194|  76.9k|    }
  195|  76.9k|  }
_ZN5ofats13any_invocableIFbPN3uWS10HttpRouterINS1_15HttpContextDataILb0EE10RouterDataEEEEEC2IZNS1_11HttpContextILb0EE6onHttpENSt3__112basic_stringIcNSD_11char_traitsIcEENSD_9allocatorIcEEEESJ_ONS0_IFvPNS1_12HttpResponseILb0EEEPNS1_11HttpRequestEEEEbEUlPT_E_vEEOSS_:
  303|  38.4k|    any_invocable(F&& f) {                                                     \
  304|  38.4k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  38.4k|    }                                                                          \
_ZN5ofats10any_detail18any_invocable_implIbLb0EJPN3uWS10HttpRouterINS2_15HttpContextDataILb0EE10RouterDataEEEEEC2Ev:
  186|  38.4k|  any_invocable_impl() noexcept = default;
_ZN5ofats10any_detail18any_invocable_implIbLb0EJPN3uWS10HttpRouterINS2_15HttpContextDataILb0EE10RouterDataEEEEE6createIZNS2_11HttpContextILb0EE6onHttpENSt3__112basic_stringIcNSD_11char_traitsIcEENSD_9allocatorIcEEEESJ_ONS_13any_invocableIFvPNS2_12HttpResponseILb0EEEPNS2_11HttpRequestEEEEbEUlPT_E_JSV_EEEvDpOT0_:
  232|  38.4k|  void create(Args&&... args) {
  233|  38.4k|    using hdl = handler<F>;
  234|  38.4k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  38.4k|    handle_ = &hdl::handle;
  236|  38.4k|    call_ = &hdl::call;
  237|  38.4k|  }
_ZN5ofats10any_detail14handler_traitsIbJPN3uWS10HttpRouterINS2_15HttpContextDataILb0EE10RouterDataEEEEE13large_handlerIZNS2_11HttpContextILb0EE6onHttpENSt3__112basic_stringIcNSD_11char_traitsIcEENSD_9allocatorIcEEEESJ_ONS_13any_invocableIFvPNS2_12HttpResponseILb0EEEPNS2_11HttpRequestEEEEbEUlPT_E_E6createIJSV_EEEvRNS0_7storageEDpOT_:
  141|  38.4k|    static void create(storage& s, Args&&... args) {
  142|  38.4k|      s.ptr_ = new T(std::forward<Args>(args)...);
  143|  38.4k|    }
_ZN5ofats10any_detail14handler_traitsIbJPN3uWS10HttpRouterINS2_15HttpContextDataILb0EE10RouterDataEEEEE12handler_baseINS9_13large_handlerIZNS2_11HttpContextILb0EE6onHttpENSt3__112basic_stringIcNSE_11char_traitsIcEENSE_9allocatorIcEEEESK_ONS_13any_invocableIFvPNS2_12HttpResponseILb0EEEPNS2_11HttpRequestEEEEbEUlPT_E_EEE6handleENS0_6actionEPNS0_7storageES11_:
  103|   121k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|   121k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 121k]
  ------------------
  105|  38.4k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 38.4k, False: 83.3k]
  ------------------
  106|  38.4k|          Derived::destroy(*current);
  107|  38.4k|          break;
  108|  83.3k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 83.3k, False: 38.4k]
  ------------------
  109|  83.3k|          Derived::move(*current, *other);
  110|  83.3k|          break;
  111|   121k|      }
  112|   121k|    }
_ZN5ofats10any_detail14handler_traitsIbJPN3uWS10HttpRouterINS2_15HttpContextDataILb0EE10RouterDataEEEEE13large_handlerIZNS2_11HttpContextILb0EE6onHttpENSt3__112basic_stringIcNSD_11char_traitsIcEENSD_9allocatorIcEEEESJ_ONS_13any_invocableIFvPNS2_12HttpResponseILb0EEEPNS2_11HttpRequestEEEEbEUlPT_E_E7destroyERNS0_7storageE:
  145|  38.4k|    static void destroy(storage& s) noexcept { delete static_cast<T*>(s.ptr_); }
_ZN5ofats10any_detail14handler_traitsIbJPN3uWS10HttpRouterINS2_15HttpContextDataILb0EE10RouterDataEEEEE13large_handlerIZNS2_11HttpContextILb0EE6onHttpENSt3__112basic_stringIcNSD_11char_traitsIcEENSD_9allocatorIcEEEESJ_ONS_13any_invocableIFvPNS2_12HttpResponseILb0EEEPNS2_11HttpRequestEEEEbEUlPT_E_E4moveERNS0_7storageESY_:
  147|  83.3k|    static void move(storage& dst, storage& src) noexcept {
  148|  83.3k|      dst.ptr_ = src.ptr_;
  149|  83.3k|    }
_ZN5ofats10any_detail14handler_traitsIbJPN3uWS10HttpRouterINS2_15HttpContextDataILb0EE10RouterDataEEEEE13large_handlerIZNS2_11HttpContextILb0EE6onHttpENSt3__112basic_stringIcNSD_11char_traitsIcEENSD_9allocatorIcEEEESJ_ONS_13any_invocableIFvPNS2_12HttpResponseILb0EEEPNS2_11HttpRequestEEEEbEUlPT_E_E4callERNS0_7storageES8_:
  151|  70.9k|    static R call(storage& s, ArgTypes... args) {
  152|  70.9k|      return std::invoke(*static_cast<T*>(s.ptr_),
  153|  70.9k|                         std::forward<ArgTypes>(args)...);
  154|  70.9k|    }
_ZN5ofats13any_invocableIFvPN3uWS12HttpResponseILb0EEEPNS1_11HttpRequestEEEclES4_S6_:
  345|  70.9k|    R operator()(ArgTypes... args) cv ref noexcept(noex) {                     \
  346|  70.9k|      return base_type::call(std::forward<ArgTypes>(args)...);                 \
  347|  70.9k|    }                                                                          \
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE4callES5_S7_:
  246|  70.9k|  R call(ArgTypes... args) noexcept(is_noexcept) {
  247|  70.9k|    return call_(storage_, std::forward<ArgTypes>(args)...);
  248|  70.9k|  }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEP19us_socket_context_tEEC2EOSA_:
  188|  25.6k|  any_invocable_impl(any_invocable_impl&& rhs) noexcept {
  189|  25.6k|    if (rhs.handle_) {
  ------------------
  |  Branch (189:9): [True: 0, False: 25.6k]
  ------------------
  190|      0|      handle_ = rhs.handle_;
  191|      0|      handle_(action::move, &storage_, &rhs.storage_);
  192|      0|      call_ = rhs.call_;
  193|      0|      rhs.handle_ = nullptr;
  194|      0|    }
  195|  25.6k|  }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvPN3uWS12HttpResponseILb0EEEPNS1_11HttpRequestEEEC2IZNS1_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOSB_NSt3__112basic_stringIcNSF_11char_traitsIcEENSF_9allocatorIcEEEEONSB_17WebSocketBehaviorIT_EEEUlPSN_PT0_E_vEEOSN_:
  303|  12.8k|    any_invocable(F&& f) {                                                     \
  304|  12.8k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  12.8k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE6createIZNS2_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOSB_NSt3__112basic_stringIcNSF_11char_traitsIcEENSF_9allocatorIcEEEEONSB_17WebSocketBehaviorIT_EEEUlPSN_PT0_E_JST_EEEvDpOT0_:
  232|  12.8k|  void create(Args&&... args) {
  233|  12.8k|    using hdl = handler<F>;
  234|  12.8k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  12.8k|    handle_ = &hdl::handle;
  236|  12.8k|    call_ = &hdl::call;
  237|  12.8k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13large_handlerIZNS2_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOSB_NSt3__112basic_stringIcNSF_11char_traitsIcEENSF_9allocatorIcEEEEONSB_17WebSocketBehaviorIT_EEEUlPSN_PT0_E_E6createIJST_EEEvRNS0_7storageEDpOT_:
  141|  12.8k|    static void create(storage& s, Args&&... args) {
  142|  12.8k|      s.ptr_ = new T(std::forward<Args>(args)...);
  143|  12.8k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE12handler_baseINS8_13large_handlerIZNS2_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOSC_NSt3__112basic_stringIcNSG_11char_traitsIcEENSG_9allocatorIcEEEEONSC_17WebSocketBehaviorIT_EEEUlPSO_PT0_E_EEE6handleENS0_6actionEPNS0_7storageESZ_:
  103|  38.4k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  38.4k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 38.4k]
  ------------------
  105|  12.8k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 12.8k, False: 25.6k]
  ------------------
  106|  12.8k|          Derived::destroy(*current);
  107|  12.8k|          break;
  108|  25.6k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 25.6k, False: 12.8k]
  ------------------
  109|  25.6k|          Derived::move(*current, *other);
  110|  25.6k|          break;
  111|  38.4k|      }
  112|  38.4k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13large_handlerIZNS2_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOSB_NSt3__112basic_stringIcNSF_11char_traitsIcEENSF_9allocatorIcEEEEONSB_17WebSocketBehaviorIT_EEEUlPSN_PT0_E_E7destroyERNS0_7storageE:
  145|  12.8k|    static void destroy(storage& s) noexcept { delete static_cast<T*>(s.ptr_); }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13large_handlerIZNS2_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOSB_NSt3__112basic_stringIcNSF_11char_traitsIcEENSF_9allocatorIcEEEEONSB_17WebSocketBehaviorIT_EEEUlPSN_PT0_E_E4moveERNS0_7storageESW_:
  147|  25.6k|    static void move(storage& dst, storage& src) noexcept {
  148|  25.6k|      dst.ptr_ = src.ptr_;
  149|  25.6k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13large_handlerIZNS2_12TemplatedAppILb0EE2wsIZ4testvE13PerSocketDataEEOSB_NSt3__112basic_stringIcNSF_11char_traitsIcEENSF_9allocatorIcEEEEONSB_17WebSocketBehaviorIT_EEEUlPSN_PT0_E_E4callERNS0_7storageES5_S7_:
  151|  50.8k|    static R call(storage& s, ArgTypes... args) {
  152|  50.8k|      return std::invoke(*static_cast<T*>(s.ptr_),
  153|  50.8k|                         std::forward<ArgTypes>(args)...);
  154|  50.8k|    }
_ZNK5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEP19us_socket_context_tEEcvbEv:
  228|  40.1k|  explicit operator bool() const noexcept { return handle_ != nullptr; }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvPN3uWS12HttpResponseILb0EEEPNS1_11HttpRequestEEEC2IZ4testvE3$_0vEEOT_:
  303|  6.41k|    any_invocable(F&& f) {                                                     \
  304|  6.41k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  6.41k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE6createIZ4testvE3$_0JSA_EEEvDpOT0_:
  232|  6.41k|  void create(Args&&... args) {
  233|  6.41k|    using hdl = handler<F>;
  234|  6.41k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  6.41k|    handle_ = &hdl::handle;
  236|  6.41k|    call_ = &hdl::call;
  237|  6.41k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13small_handlerIZ4testvE3$_0E6createIJSA_EEEvRNS0_7storageEDpOT_:
  118|  19.2k|    static void create(storage& s, Args&&... args) {
  119|  19.2k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE12handler_baseINS8_13small_handlerIZ4testvE3$_0EEE6handleENS0_6actionEPNS0_7storageESG_:
  103|  19.2k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  19.2k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 19.2k]
  ------------------
  105|  6.41k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 6.41k, False: 12.8k]
  ------------------
  106|  6.41k|          Derived::destroy(*current);
  107|  6.41k|          break;
  108|  12.8k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 12.8k, False: 6.41k]
  ------------------
  109|  12.8k|          Derived::move(*current, *other);
  110|  12.8k|          break;
  111|  19.2k|      }
  112|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13small_handlerIZ4testvE3$_0E7destroyERNS0_7storageE:
  122|  19.2k|    static void destroy(storage& s) noexcept {
  123|  19.2k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|  19.2k|      value.~T();
  125|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13small_handlerIZ4testvE3$_0E4moveERNS0_7storageESD_:
  127|  12.8k|    static void move(storage& dst, storage& src) noexcept {
  128|  12.8k|      create(dst, std::move(*static_cast<T*>(static_cast<void*>(&src.buf_))));
  129|  12.8k|      destroy(src);
  130|  12.8k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13small_handlerIZ4testvE3$_0E4callERNS0_7storageES5_S7_:
  132|  9.75k|    static R call(storage& s, ArgTypes... args) {
  133|  9.75k|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|  9.75k|                         std::forward<ArgTypes>(args)...);
  135|  9.75k|    }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvPN3uWS12HttpResponseILb0EEEPNS1_11HttpRequestEEEC2IZ4testvE3$_1vEEOT_:
  303|  6.41k|    any_invocable(F&& f) {                                                     \
  304|  6.41k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  6.41k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE6createIZ4testvE3$_1JSA_EEEvDpOT0_:
  232|  6.41k|  void create(Args&&... args) {
  233|  6.41k|    using hdl = handler<F>;
  234|  6.41k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  6.41k|    handle_ = &hdl::handle;
  236|  6.41k|    call_ = &hdl::call;
  237|  6.41k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13small_handlerIZ4testvE3$_1E6createIJSA_EEEvRNS0_7storageEDpOT_:
  118|  19.2k|    static void create(storage& s, Args&&... args) {
  119|  19.2k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE12handler_baseINS8_13small_handlerIZ4testvE3$_1EEE6handleENS0_6actionEPNS0_7storageESG_:
  103|  19.2k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  19.2k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 19.2k]
  ------------------
  105|  6.41k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 6.41k, False: 12.8k]
  ------------------
  106|  6.41k|          Derived::destroy(*current);
  107|  6.41k|          break;
  108|  12.8k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 12.8k, False: 6.41k]
  ------------------
  109|  12.8k|          Derived::move(*current, *other);
  110|  12.8k|          break;
  111|  19.2k|      }
  112|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13small_handlerIZ4testvE3$_1E7destroyERNS0_7storageE:
  122|  19.2k|    static void destroy(storage& s) noexcept {
  123|  19.2k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|  19.2k|      value.~T();
  125|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13small_handlerIZ4testvE3$_1E4moveERNS0_7storageESD_:
  127|  12.8k|    static void move(storage& dst, storage& src) noexcept {
  128|  12.8k|      create(dst, std::move(*static_cast<T*>(static_cast<void*>(&src.buf_))));
  129|  12.8k|      destroy(src);
  130|  12.8k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13small_handlerIZ4testvE3$_1E4callERNS0_7storageES5_S7_:
  132|  4.29k|    static R call(storage& s, ArgTypes... args) {
  133|  4.29k|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|  4.29k|                         std::forward<ArgTypes>(args)...);
  135|  4.29k|    }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJEEaSEOS2_:
  197|  4.29k|  any_invocable_impl& operator=(any_invocable_impl&& rhs) noexcept {
  198|  4.29k|    any_invocable_impl{std::move(rhs)}.swap(*this);
  199|  4.29k|    return *this;
  200|  4.29k|  }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvvEEC2IZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS6_11HttpRequestEEEDaPT_PT0_EUlvE_vEEOSA_:
  303|  4.29k|    any_invocable(F&& f) {                                                     \
  304|  4.29k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  4.29k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJEE6createIZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS6_11HttpRequestEEEDaPT_PT0_EUlvE_JSE_EEEvDpOT0_:
  232|  4.29k|  void create(Args&&... args) {
  233|  4.29k|    using hdl = handler<F>;
  234|  4.29k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  4.29k|    handle_ = &hdl::handle;
  236|  4.29k|    call_ = &hdl::call;
  237|  4.29k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE13small_handlerIZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS6_11HttpRequestEEEDaPT_PT0_EUlvE_E6createIJSE_EEEvRNS0_7storageEDpOT_:
  118|  16.0k|    static void create(storage& s, Args&&... args) {
  119|  16.0k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|  16.0k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE12handler_baseINS2_13small_handlerIZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS7_11HttpRequestEEEDaPT_PT0_EUlvE_EEE6handleENS0_6actionEPNS0_7storageESK_:
  103|  16.0k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  16.0k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 16.0k]
  ------------------
  105|  4.29k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 4.29k, False: 11.7k]
  ------------------
  106|  4.29k|          Derived::destroy(*current);
  107|  4.29k|          break;
  108|  11.7k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 11.7k, False: 4.29k]
  ------------------
  109|  11.7k|          Derived::move(*current, *other);
  110|  11.7k|          break;
  111|  16.0k|      }
  112|  16.0k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE13small_handlerIZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS6_11HttpRequestEEEDaPT_PT0_EUlvE_E7destroyERNS0_7storageE:
  122|  16.0k|    static void destroy(storage& s) noexcept {
  123|  16.0k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|  16.0k|      value.~T();
  125|  16.0k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE13small_handlerIZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS6_11HttpRequestEEEDaPT_PT0_EUlvE_E4moveERNS0_7storageESH_:
  127|  11.7k|    static void move(storage& dst, storage& src) noexcept {
  128|  11.7k|      create(dst, std::move(*static_cast<T*>(static_cast<void*>(&src.buf_))));
  129|  11.7k|      destroy(src);
  130|  11.7k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE13small_handlerIZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS6_11HttpRequestEEEDaPT_PT0_EUlvE_E4callERNS0_7storageE:
  132|  1.16k|    static R call(storage& s, ArgTypes... args) {
  133|  1.16k|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|  1.16k|                         std::forward<ArgTypes>(args)...);
  135|  1.16k|    }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvvEEC2IZZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS6_11HttpRequestEEEDaPT_PT0_ENKUlvE_clEvEUlvE_vEEOSA_:
  303|  1.16k|    any_invocable(F&& f) {                                                     \
  304|  1.16k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  1.16k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJEE6createIZZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS6_11HttpRequestEEEDaPT_PT0_ENKUlvE_clEvEUlvE_JSF_EEEvDpOT0_:
  232|  1.16k|  void create(Args&&... args) {
  233|  1.16k|    using hdl = handler<F>;
  234|  1.16k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  1.16k|    handle_ = &hdl::handle;
  236|  1.16k|    call_ = &hdl::call;
  237|  1.16k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE13small_handlerIZZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS6_11HttpRequestEEEDaPT_PT0_ENKUlvE_clEvEUlvE_E6createIJSF_EEEvRNS0_7storageEDpOT_:
  118|  2.35k|    static void create(storage& s, Args&&... args) {
  119|  2.35k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|  2.35k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE12handler_baseINS2_13small_handlerIZZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS7_11HttpRequestEEEDaPT_PT0_ENKUlvE_clEvEUlvE_EEE6handleENS0_6actionEPNS0_7storageESL_:
  103|  2.35k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  2.35k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 2.35k]
  ------------------
  105|  1.16k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 1.16k, False: 1.19k]
  ------------------
  106|  1.16k|          Derived::destroy(*current);
  107|  1.16k|          break;
  108|  1.19k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 1.19k, False: 1.16k]
  ------------------
  109|  1.19k|          Derived::move(*current, *other);
  110|  1.19k|          break;
  111|  2.35k|      }
  112|  2.35k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE13small_handlerIZZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS6_11HttpRequestEEEDaPT_PT0_ENKUlvE_clEvEUlvE_E7destroyERNS0_7storageE:
  122|  2.35k|    static void destroy(storage& s) noexcept {
  123|  2.35k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|  2.35k|      value.~T();
  125|  2.35k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE13small_handlerIZZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS6_11HttpRequestEEEDaPT_PT0_ENKUlvE_clEvEUlvE_E4moveERNS0_7storageESI_:
  127|  1.19k|    static void move(storage& dst, storage& src) noexcept {
  128|  1.19k|      create(dst, std::move(*static_cast<T*>(static_cast<void*>(&src.buf_))));
  129|  1.19k|      destroy(src);
  130|  1.19k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE13small_handlerIZZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS6_11HttpRequestEEEDaPT_PT0_ENKUlvE_clEvEUlvE_E4callERNS0_7storageE:
  132|  1.08k|    static R call(storage& s, ArgTypes... args) {
  133|  1.08k|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|  1.08k|                         std::forward<ArgTypes>(args)...);
  135|  1.08k|    }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJNSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEbEEaSEOS7_:
  197|  4.29k|  any_invocable_impl& operator=(any_invocable_impl&& rhs) noexcept {
  198|  4.29k|    any_invocable_impl{std::move(rhs)}.swap(*this);
  199|  4.29k|    return *this;
  200|  4.29k|  }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJNSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEbEEC2EOS7_:
  188|  4.29k|  any_invocable_impl(any_invocable_impl&& rhs) noexcept {
  189|  4.29k|    if (rhs.handle_) {
  ------------------
  |  Branch (189:9): [True: 4.29k, False: 0]
  ------------------
  190|  4.29k|      handle_ = rhs.handle_;
  191|  4.29k|      handle_(action::move, &storage_, &rhs.storage_);
  192|  4.29k|      call_ = rhs.call_;
  193|  4.29k|      rhs.handle_ = nullptr;
  194|  4.29k|    }
  195|  4.29k|  }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvNSt3__117basic_string_viewIcNS1_11char_traitsIcEEEEbEEC2IZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENSB_11HttpRequestEEEDaPT_PT0_EUlS5_bE_vEEOSF_:
  303|  4.29k|    any_invocable(F&& f) {                                                     \
  304|  4.29k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  4.29k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJNSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEbEE6createIZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENSB_11HttpRequestEEEDaPT_PT0_EUlS6_bE_JSJ_EEEvDpOT0_:
  232|  4.29k|  void create(Args&&... args) {
  233|  4.29k|    using hdl = handler<F>;
  234|  4.29k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  4.29k|    handle_ = &hdl::handle;
  236|  4.29k|    call_ = &hdl::call;
  237|  4.29k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJNSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEbEE13small_handlerIZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENSB_11HttpRequestEEEDaPT_PT0_EUlS6_bE_E6createIJSJ_EEEvRNS0_7storageEDpOT_:
  118|  16.0k|    static void create(storage& s, Args&&... args) {
  119|  16.0k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|  16.0k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJNSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEbEE12handler_baseINS7_13small_handlerIZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENSC_11HttpRequestEEEDaPT_PT0_EUlS6_bE_EEE6handleENS0_6actionEPNS0_7storageESP_:
  103|  16.0k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  16.0k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 16.0k]
  ------------------
  105|  4.29k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 4.29k, False: 11.7k]
  ------------------
  106|  4.29k|          Derived::destroy(*current);
  107|  4.29k|          break;
  108|  11.7k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 11.7k, False: 4.29k]
  ------------------
  109|  11.7k|          Derived::move(*current, *other);
  110|  11.7k|          break;
  111|  16.0k|      }
  112|  16.0k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJNSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEbEE13small_handlerIZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENSB_11HttpRequestEEEDaPT_PT0_EUlS6_bE_E7destroyERNS0_7storageE:
  122|  16.0k|    static void destroy(storage& s) noexcept {
  123|  16.0k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|  16.0k|      value.~T();
  125|  16.0k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJNSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEbEE13small_handlerIZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENSB_11HttpRequestEEEDaPT_PT0_EUlS6_bE_E4moveERNS0_7storageESM_:
  127|  11.7k|    static void move(storage& dst, storage& src) noexcept {
  128|  11.7k|      create(dst, std::move(*static_cast<T*>(static_cast<void*>(&src.buf_))));
  129|  11.7k|      destroy(src);
  130|  11.7k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJNSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEbEE13small_handlerIZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENSB_11HttpRequestEEEDaPT_PT0_EUlS6_bE_E4callERNS0_7storageES6_b:
  132|  34.9k|    static R call(storage& s, ArgTypes... args) {
  133|  34.9k|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|  34.9k|                         std::forward<ArgTypes>(args)...);
  135|  34.9k|    }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvvEEC2IZZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS6_11HttpRequestEEEDaPT_PT0_ENKUlNSt3__117basic_string_viewIcNSE_11char_traitsIcEEEEbE_clESI_bEUlvE_vEEOSA_:
  303|  3.13k|    any_invocable(F&& f) {                                                     \
  304|  3.13k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  3.13k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJEE6createIZZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS6_11HttpRequestEEEDaPT_PT0_ENKUlNSt3__117basic_string_viewIcNSE_11char_traitsIcEEEEbE_clESI_bEUlvE_JSK_EEEvDpOT0_:
  232|  3.13k|  void create(Args&&... args) {
  233|  3.13k|    using hdl = handler<F>;
  234|  3.13k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  3.13k|    handle_ = &hdl::handle;
  236|  3.13k|    call_ = &hdl::call;
  237|  3.13k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE13large_handlerIZZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS6_11HttpRequestEEEDaPT_PT0_ENKUlNSt3__117basic_string_viewIcNSE_11char_traitsIcEEEEbE_clESI_bEUlvE_E6createIJSK_EEEvRNS0_7storageEDpOT_:
  141|  3.13k|    static void create(storage& s, Args&&... args) {
  142|  3.13k|      s.ptr_ = new T(std::forward<Args>(args)...);
  143|  3.13k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE12handler_baseINS2_13large_handlerIZZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS7_11HttpRequestEEEDaPT_PT0_ENKUlNSt3__117basic_string_viewIcNSF_11char_traitsIcEEEEbE_clESJ_bEUlvE_EEE6handleENS0_6actionEPNS0_7storageESQ_:
  103|  3.13k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  3.13k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 3.13k]
  ------------------
  105|  3.13k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 3.13k, False: 0]
  ------------------
  106|  3.13k|          Derived::destroy(*current);
  107|  3.13k|          break;
  108|      0|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 0, False: 3.13k]
  ------------------
  109|      0|          Derived::move(*current, *other);
  110|      0|          break;
  111|  3.13k|      }
  112|  3.13k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE13large_handlerIZZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS6_11HttpRequestEEEDaPT_PT0_ENKUlNSt3__117basic_string_viewIcNSE_11char_traitsIcEEEEbE_clESI_bEUlvE_E7destroyERNS0_7storageE:
  145|  3.13k|    static void destroy(storage& s) noexcept { delete static_cast<T*>(s.ptr_); }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE13large_handlerIZZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS6_11HttpRequestEEEDaPT_PT0_ENKUlNSt3__117basic_string_viewIcNSE_11char_traitsIcEEEEbE_clESI_bEUlvE_E4callERNS0_7storageE:
  151|  3.13k|    static R call(storage& s, ArgTypes... args) {
  152|  3.13k|      return std::invoke(*static_cast<T*>(s.ptr_),
  153|  3.13k|                         std::forward<ArgTypes>(args)...);
  154|  3.13k|    }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvPN3uWS12HttpResponseILb0EEEPNS1_11HttpRequestEEEC2IZ4testvE3$_2vEEOT_:
  303|  6.41k|    any_invocable(F&& f) {                                                     \
  304|  6.41k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  6.41k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE6createIZ4testvE3$_2JSA_EEEvDpOT0_:
  232|  6.41k|  void create(Args&&... args) {
  233|  6.41k|    using hdl = handler<F>;
  234|  6.41k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  6.41k|    handle_ = &hdl::handle;
  236|  6.41k|    call_ = &hdl::call;
  237|  6.41k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13small_handlerIZ4testvE3$_2E6createIJSA_EEEvRNS0_7storageEDpOT_:
  118|  19.2k|    static void create(storage& s, Args&&... args) {
  119|  19.2k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE12handler_baseINS8_13small_handlerIZ4testvE3$_2EEE6handleENS0_6actionEPNS0_7storageESG_:
  103|  19.2k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  19.2k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 19.2k]
  ------------------
  105|  6.41k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 6.41k, False: 12.8k]
  ------------------
  106|  6.41k|          Derived::destroy(*current);
  107|  6.41k|          break;
  108|  12.8k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 12.8k, False: 6.41k]
  ------------------
  109|  12.8k|          Derived::move(*current, *other);
  110|  12.8k|          break;
  111|  19.2k|      }
  112|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13small_handlerIZ4testvE3$_2E7destroyERNS0_7storageE:
  122|  19.2k|    static void destroy(storage& s) noexcept {
  123|  19.2k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|  19.2k|      value.~T();
  125|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13small_handlerIZ4testvE3$_2E4moveERNS0_7storageESD_:
  127|  12.8k|    static void move(storage& dst, storage& src) noexcept {
  128|  12.8k|      create(dst, std::move(*static_cast<T*>(static_cast<void*>(&src.buf_))));
  129|  12.8k|      destroy(src);
  130|  12.8k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS12HttpResponseILb0EEEPNS2_11HttpRequestEEE13small_handlerIZ4testvE3$_2E4callERNS0_7storageES5_S7_:
  132|  2.02k|    static R call(storage& s, ArgTypes... args) {
  133|  2.02k|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|  2.02k|                         std::forward<ArgTypes>(args)...);
  135|  2.02k|    }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEC2IZ4testvE3$_3vEEOT_:
  303|  6.41k|    any_invocable(F&& f) {                                                     \
  304|  6.41k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  6.41k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEC2Ev:
  186|  12.8k|  any_invocable_impl() noexcept = default;
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEE6createIZ4testvE3$_3JS9_EEEvDpOT0_:
  232|  6.41k|  void create(Args&&... args) {
  233|  6.41k|    using hdl = handler<F>;
  234|  6.41k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  6.41k|    handle_ = &hdl::handle;
  236|  6.41k|    call_ = &hdl::call;
  237|  6.41k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEE13small_handlerIZ4testvE3$_3E6createIJS9_EEEvRNS0_7storageEDpOT_:
  118|  19.2k|    static void create(storage& s, Args&&... args) {
  119|  19.2k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEE12handler_baseINS7_13small_handlerIZ4testvE3$_3EEE6handleENS0_6actionEPNS0_7storageESF_:
  103|  19.2k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  19.2k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 19.2k]
  ------------------
  105|  6.41k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 6.41k, False: 12.8k]
  ------------------
  106|  6.41k|          Derived::destroy(*current);
  107|  6.41k|          break;
  108|  12.8k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 12.8k, False: 6.41k]
  ------------------
  109|  12.8k|          Derived::move(*current, *other);
  110|  12.8k|          break;
  111|  19.2k|      }
  112|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEE13small_handlerIZ4testvE3$_3E7destroyERNS0_7storageE:
  122|  19.2k|    static void destroy(storage& s) noexcept {
  123|  19.2k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|  19.2k|      value.~T();
  125|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEE13small_handlerIZ4testvE3$_3E4moveERNS0_7storageESC_:
  127|  12.8k|    static void move(storage& dst, storage& src) noexcept {
  128|  12.8k|      create(dst, std::move(*static_cast<T*>(static_cast<void*>(&src.buf_))));
  129|  12.8k|      destroy(src);
  130|  12.8k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEE13small_handlerIZ4testvE3$_3E4callERNS0_7storageES6_:
  132|  39.0k|    static R call(storage& s, ArgTypes... args) {
  133|  39.0k|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|  39.0k|                         std::forward<ArgTypes>(args)...);
  135|  39.0k|    }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS6_11char_traitsIcEEEENS1_6OpCodeEEEC2IZ4testvE3$_4vEEOT_:
  303|  6.41k|    any_invocable(F&& f) {                                                     \
  304|  6.41k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  6.41k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEENS2_6OpCodeEEEC2Ev:
  186|  6.41k|  any_invocable_impl() noexcept = default;
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEENS2_6OpCodeEEE6createIZ4testvE3$_4JSF_EEEvDpOT0_:
  232|  6.41k|  void create(Args&&... args) {
  233|  6.41k|    using hdl = handler<F>;
  234|  6.41k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  6.41k|    handle_ = &hdl::handle;
  236|  6.41k|    call_ = &hdl::call;
  237|  6.41k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEENS2_6OpCodeEEE13small_handlerIZ4testvE3$_4E6createIJSF_EEEvRNS0_7storageEDpOT_:
  118|  19.2k|    static void create(storage& s, Args&&... args) {
  119|  19.2k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEENS2_6OpCodeEEE12handler_baseINSD_13small_handlerIZ4testvE3$_4EEE6handleENS0_6actionEPNS0_7storageESL_:
  103|  19.2k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  19.2k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 19.2k]
  ------------------
  105|  6.41k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 6.41k, False: 12.8k]
  ------------------
  106|  6.41k|          Derived::destroy(*current);
  107|  6.41k|          break;
  108|  12.8k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 12.8k, False: 6.41k]
  ------------------
  109|  12.8k|          Derived::move(*current, *other);
  110|  12.8k|          break;
  111|  19.2k|      }
  112|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEENS2_6OpCodeEEE13small_handlerIZ4testvE3$_4E7destroyERNS0_7storageE:
  122|  19.2k|    static void destroy(storage& s) noexcept {
  123|  19.2k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|  19.2k|      value.~T();
  125|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEENS2_6OpCodeEEE13small_handlerIZ4testvE3$_4E4moveERNS0_7storageESI_:
  127|  12.8k|    static void move(storage& dst, storage& src) noexcept {
  128|  12.8k|      create(dst, std::move(*static_cast<T*>(static_cast<void*>(&src.buf_))));
  129|  12.8k|      destroy(src);
  130|  12.8k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEENS2_6OpCodeEEE13small_handlerIZ4testvE3$_4E4callERNS0_7storageES6_SB_SC_:
  132|  10.0k|    static R call(storage& s, ArgTypes... args) {
  133|  10.0k|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|  10.0k|                         std::forward<ArgTypes>(args)...);
  135|  10.0k|    }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEC2IZ4testvE3$_5vEEOT_:
  303|  6.41k|    any_invocable(F&& f) {                                                     \
  304|  6.41k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  6.41k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEE6createIZ4testvE3$_5JS9_EEEvDpOT0_:
  232|  6.41k|  void create(Args&&... args) {
  233|  6.41k|    using hdl = handler<F>;
  234|  6.41k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  6.41k|    handle_ = &hdl::handle;
  236|  6.41k|    call_ = &hdl::call;
  237|  6.41k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEE13small_handlerIZ4testvE3$_5E6createIJS9_EEEvRNS0_7storageEDpOT_:
  118|  19.2k|    static void create(storage& s, Args&&... args) {
  119|  19.2k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEE12handler_baseINS7_13small_handlerIZ4testvE3$_5EEE6handleENS0_6actionEPNS0_7storageESF_:
  103|  19.2k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  19.2k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 19.2k]
  ------------------
  105|  6.41k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 6.41k, False: 12.8k]
  ------------------
  106|  6.41k|          Derived::destroy(*current);
  107|  6.41k|          break;
  108|  12.8k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 12.8k, False: 6.41k]
  ------------------
  109|  12.8k|          Derived::move(*current, *other);
  110|  12.8k|          break;
  111|  19.2k|      }
  112|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEE13small_handlerIZ4testvE3$_5E7destroyERNS0_7storageE:
  122|  19.2k|    static void destroy(storage& s) noexcept {
  123|  19.2k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|  19.2k|      value.~T();
  125|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEE13small_handlerIZ4testvE3$_5E4moveERNS0_7storageESC_:
  127|  12.8k|    static void move(storage& dst, storage& src) noexcept {
  128|  12.8k|      create(dst, std::move(*static_cast<T*>(static_cast<void*>(&src.buf_))));
  129|  12.8k|      destroy(src);
  130|  12.8k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEE13small_handlerIZ4testvE3$_5E4callERNS0_7storageES6_:
  132|  5.04k|    static R call(storage& s, ArgTypes... args) {
  133|  5.04k|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|  5.04k|                         std::forward<ArgTypes>(args)...);
  135|  5.04k|    }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS6_11char_traitsIcEEEEEEC2IZ4testvE3$_6vEEOT_:
  303|  6.41k|    any_invocable(F&& f) {                                                     \
  304|  6.41k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  6.41k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEEC2Ev:
  186|  12.8k|  any_invocable_impl() noexcept = default;
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE6createIZ4testvE3$_6JSE_EEEvDpOT0_:
  232|  6.41k|  void create(Args&&... args) {
  233|  6.41k|    using hdl = handler<F>;
  234|  6.41k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  6.41k|    handle_ = &hdl::handle;
  236|  6.41k|    call_ = &hdl::call;
  237|  6.41k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE13small_handlerIZ4testvE3$_6E6createIJSE_EEEvRNS0_7storageEDpOT_:
  118|  19.2k|    static void create(storage& s, Args&&... args) {
  119|  19.2k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE12handler_baseINSC_13small_handlerIZ4testvE3$_6EEE6handleENS0_6actionEPNS0_7storageESK_:
  103|  19.2k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  19.2k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 19.2k]
  ------------------
  105|  6.41k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 6.41k, False: 12.8k]
  ------------------
  106|  6.41k|          Derived::destroy(*current);
  107|  6.41k|          break;
  108|  12.8k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 12.8k, False: 6.41k]
  ------------------
  109|  12.8k|          Derived::move(*current, *other);
  110|  12.8k|          break;
  111|  19.2k|      }
  112|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE13small_handlerIZ4testvE3$_6E7destroyERNS0_7storageE:
  122|  19.2k|    static void destroy(storage& s) noexcept {
  123|  19.2k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|  19.2k|      value.~T();
  125|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE13small_handlerIZ4testvE3$_6E4moveERNS0_7storageESH_:
  127|  12.8k|    static void move(storage& dst, storage& src) noexcept {
  128|  12.8k|      create(dst, std::move(*static_cast<T*>(static_cast<void*>(&src.buf_))));
  129|  12.8k|      destroy(src);
  130|  12.8k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE13small_handlerIZ4testvE3$_6E4callERNS0_7storageES6_SB_:
  132|  6.99k|    static R call(storage& s, ArgTypes... args) {
  133|  6.99k|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|  6.99k|                         std::forward<ArgTypes>(args)...);
  135|  6.99k|    }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvvEEC2IZZ4testvENK3$_6clIN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEDaPT_NSt3__117basic_string_viewIcNSC_11char_traitsIcEEEEEUlvE_vEEOSA_:
  303|  6.99k|    any_invocable(F&& f) {                                                     \
  304|  6.99k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  6.99k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJEE6createIZZ4testvENK3$_6clIN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEDaPT_NSt3__117basic_string_viewIcNSC_11char_traitsIcEEEEEUlvE_JSH_EEEvDpOT0_:
  232|  6.99k|  void create(Args&&... args) {
  233|  6.99k|    using hdl = handler<F>;
  234|  6.99k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  6.99k|    handle_ = &hdl::handle;
  236|  6.99k|    call_ = &hdl::call;
  237|  6.99k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE13small_handlerIZZ4testvENK3$_6clIN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEDaPT_NSt3__117basic_string_viewIcNSC_11char_traitsIcEEEEEUlvE_E6createIJSH_EEEvRNS0_7storageEDpOT_:
  118|  20.1k|    static void create(storage& s, Args&&... args) {
  119|  20.1k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|  20.1k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE12handler_baseINS2_13small_handlerIZZ4testvENK3$_6clIN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEDaPT_NSt3__117basic_string_viewIcNSD_11char_traitsIcEEEEEUlvE_EEE6handleENS0_6actionEPNS0_7storageESN_:
  103|  20.1k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  20.1k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 20.1k]
  ------------------
  105|  6.99k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 6.99k, False: 13.1k]
  ------------------
  106|  6.99k|          Derived::destroy(*current);
  107|  6.99k|          break;
  108|  13.1k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 13.1k, False: 6.99k]
  ------------------
  109|  13.1k|          Derived::move(*current, *other);
  110|  13.1k|          break;
  111|  20.1k|      }
  112|  20.1k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE13small_handlerIZZ4testvENK3$_6clIN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEDaPT_NSt3__117basic_string_viewIcNSC_11char_traitsIcEEEEEUlvE_E7destroyERNS0_7storageE:
  122|  20.1k|    static void destroy(storage& s) noexcept {
  123|  20.1k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|  20.1k|      value.~T();
  125|  20.1k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE13small_handlerIZZ4testvENK3$_6clIN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEDaPT_NSt3__117basic_string_viewIcNSC_11char_traitsIcEEEEEUlvE_E4moveERNS0_7storageESK_:
  127|  13.1k|    static void move(storage& dst, storage& src) noexcept {
  128|  13.1k|      create(dst, std::move(*static_cast<T*>(static_cast<void*>(&src.buf_))));
  129|  13.1k|      destroy(src);
  130|  13.1k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJEE13small_handlerIZZ4testvENK3$_6clIN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEDaPT_NSt3__117basic_string_viewIcNSC_11char_traitsIcEEEEEUlvE_E4callERNS0_7storageE:
  132|  5.51k|    static R call(storage& s, ArgTypes... args) {
  133|  5.51k|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|  5.51k|                         std::forward<ArgTypes>(args)...);
  135|  5.51k|    }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS6_11char_traitsIcEEEEEEC2IZ4testvE3$_7vEEOT_:
  303|  6.41k|    any_invocable(F&& f) {                                                     \
  304|  6.41k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  6.41k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE6createIZ4testvE3$_7JSE_EEEvDpOT0_:
  232|  6.41k|  void create(Args&&... args) {
  233|  6.41k|    using hdl = handler<F>;
  234|  6.41k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  6.41k|    handle_ = &hdl::handle;
  236|  6.41k|    call_ = &hdl::call;
  237|  6.41k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE13small_handlerIZ4testvE3$_7E6createIJSE_EEEvRNS0_7storageEDpOT_:
  118|  19.2k|    static void create(storage& s, Args&&... args) {
  119|  19.2k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE12handler_baseINSC_13small_handlerIZ4testvE3$_7EEE6handleENS0_6actionEPNS0_7storageESK_:
  103|  19.2k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  19.2k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 19.2k]
  ------------------
  105|  6.41k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 6.41k, False: 12.8k]
  ------------------
  106|  6.41k|          Derived::destroy(*current);
  107|  6.41k|          break;
  108|  12.8k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 12.8k, False: 6.41k]
  ------------------
  109|  12.8k|          Derived::move(*current, *other);
  110|  12.8k|          break;
  111|  19.2k|      }
  112|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE13small_handlerIZ4testvE3$_7E7destroyERNS0_7storageE:
  122|  19.2k|    static void destroy(storage& s) noexcept {
  123|  19.2k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|  19.2k|      value.~T();
  125|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE13small_handlerIZ4testvE3$_7E4moveERNS0_7storageESH_:
  127|  12.8k|    static void move(storage& dst, storage& src) noexcept {
  128|  12.8k|      create(dst, std::move(*static_cast<T*>(static_cast<void*>(&src.buf_))));
  129|  12.8k|      destroy(src);
  130|  12.8k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE13small_handlerIZ4testvE3$_7E4callERNS0_7storageES6_SB_:
  132|    647|    static R call(storage& s, ArgTypes... args) {
  133|    647|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|    647|                         std::forward<ArgTypes>(args)...);
  135|    647|    }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS6_11char_traitsIcEEEEEEC2IZ4testvE3$_8vEEOT_:
  303|  6.41k|    any_invocable(F&& f) {                                                     \
  304|  6.41k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  6.41k|    }                                                                          \
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE6createIZ4testvE3$_8JSE_EEEvDpOT0_:
  232|  6.41k|  void create(Args&&... args) {
  233|  6.41k|    using hdl = handler<F>;
  234|  6.41k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  6.41k|    handle_ = &hdl::handle;
  236|  6.41k|    call_ = &hdl::call;
  237|  6.41k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE13small_handlerIZ4testvE3$_8E6createIJSE_EEEvRNS0_7storageEDpOT_:
  118|  19.2k|    static void create(storage& s, Args&&... args) {
  119|  19.2k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE12handler_baseINSC_13small_handlerIZ4testvE3$_8EEE6handleENS0_6actionEPNS0_7storageESK_:
  103|  19.2k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  19.2k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 19.2k]
  ------------------
  105|  6.41k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 6.41k, False: 12.8k]
  ------------------
  106|  6.41k|          Derived::destroy(*current);
  107|  6.41k|          break;
  108|  12.8k|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 12.8k, False: 6.41k]
  ------------------
  109|  12.8k|          Derived::move(*current, *other);
  110|  12.8k|          break;
  111|  19.2k|      }
  112|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE13small_handlerIZ4testvE3$_8E7destroyERNS0_7storageE:
  122|  19.2k|    static void destroy(storage& s) noexcept {
  123|  19.2k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|  19.2k|      value.~T();
  125|  19.2k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE13small_handlerIZ4testvE3$_8E4moveERNS0_7storageESH_:
  127|  12.8k|    static void move(storage& dst, storage& src) noexcept {
  128|  12.8k|      create(dst, std::move(*static_cast<T*>(static_cast<void*>(&src.buf_))));
  129|  12.8k|      destroy(src);
  130|  12.8k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJPN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEiNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEEE13small_handlerIZ4testvE3$_8E4callERNS0_7storageES6_iSB_:
  132|  39.0k|    static R call(storage& s, ArgTypes... args) {
  133|  39.0k|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|  39.0k|                         std::forward<ArgTypes>(args)...);
  135|  39.0k|    }
_ZN5ofats13any_invocableIFvP18us_listen_socket_tEEclES2_:
  345|  6.41k|    R operator()(ArgTypes... args) cv ref noexcept(noex) {                     \
  346|  6.41k|      return base_type::call(std::forward<ArgTypes>(args)...);                 \
  347|  6.41k|    }                                                                          \
_ZN5ofats10any_detail18any_invocable_implIvLb0EJP18us_listen_socket_tEE4callES3_:
  246|  6.41k|  R call(ArgTypes... args) noexcept(is_noexcept) {
  247|  6.41k|    return call_(storage_, std::forward<ArgTypes>(args)...);
  248|  6.41k|  }
EpollHelloWorld.cpp:_ZN5ofats13any_invocableIFvP18us_listen_socket_tEEC2IZ4testvE3$_9vEEOT_:
  303|  6.41k|    any_invocable(F&& f) {                                                     \
  304|  6.41k|      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \
  305|  6.41k|    }                                                                          \
_ZN5ofats10any_detail18any_invocable_implIvLb0EJP18us_listen_socket_tEEC2Ev:
  186|  6.41k|  any_invocable_impl() noexcept = default;
EpollHelloWorld.cpp:_ZN5ofats10any_detail18any_invocable_implIvLb0EJP18us_listen_socket_tEE6createIZ4testvE3$_9JS6_EEEvDpOT0_:
  232|  6.41k|  void create(Args&&... args) {
  233|  6.41k|    using hdl = handler<F>;
  234|  6.41k|    hdl::create(storage_, std::forward<Args>(args)...);
  235|  6.41k|    handle_ = &hdl::handle;
  236|  6.41k|    call_ = &hdl::call;
  237|  6.41k|  }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJP18us_listen_socket_tEE13small_handlerIZ4testvE3$_9E6createIJS6_EEEvRNS0_7storageEDpOT_:
  118|  6.41k|    static void create(storage& s, Args&&... args) {
  119|  6.41k|      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);
  120|  6.41k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJP18us_listen_socket_tEE12handler_baseINS4_13small_handlerIZ4testvE3$_9EEE6handleENS0_6actionEPNS0_7storageESC_:
  103|  6.41k|    static void handle(action act, storage* current, storage* other = nullptr) {
  104|  6.41k|      switch (act) {
  ------------------
  |  Branch (104:15): [True: 0, False: 6.41k]
  ------------------
  105|  6.41k|        case (action::destroy):
  ------------------
  |  Branch (105:9): [True: 6.41k, False: 0]
  ------------------
  106|  6.41k|          Derived::destroy(*current);
  107|  6.41k|          break;
  108|      0|        case (action::move):
  ------------------
  |  Branch (108:9): [True: 0, False: 6.41k]
  ------------------
  109|      0|          Derived::move(*current, *other);
  110|      0|          break;
  111|  6.41k|      }
  112|  6.41k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJP18us_listen_socket_tEE13small_handlerIZ4testvE3$_9E7destroyERNS0_7storageE:
  122|  6.41k|    static void destroy(storage& s) noexcept {
  123|  6.41k|      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));
  124|  6.41k|      value.~T();
  125|  6.41k|    }
EpollHelloWorld.cpp:_ZN5ofats10any_detail14handler_traitsIvJP18us_listen_socket_tEE13small_handlerIZ4testvE3$_9E4callERNS0_7storageES3_:
  132|  6.41k|    static R call(storage& s, ArgTypes... args) {
  133|  6.41k|      return std::invoke(*static_cast<T*>(static_cast<void*>(&s.buf_)),
  134|  6.41k|                         std::forward<ArgTypes>(args)...);
  135|  6.41k|    }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPKcEEaSEOS4_:
  197|  6.41k|  any_invocable_impl& operator=(any_invocable_impl&& rhs) noexcept {
  198|  6.41k|    any_invocable_impl{std::move(rhs)}.swap(*this);
  199|  6.41k|    return *this;
  200|  6.41k|  }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPKcEEC2EOS4_:
  188|  6.41k|  any_invocable_impl(any_invocable_impl&& rhs) noexcept {
  189|  6.41k|    if (rhs.handle_) {
  ------------------
  |  Branch (189:9): [True: 0, False: 6.41k]
  ------------------
  190|      0|      handle_ = rhs.handle_;
  191|      0|      handle_(action::move, &storage_, &rhs.storage_);
  192|      0|      call_ = rhs.call_;
  193|      0|      rhs.handle_ = nullptr;
  194|      0|    }
  195|  6.41k|  }
_ZN5ofats10any_detail18any_invocable_implIvLb0EJPKcEE4swapERS4_:
  208|  6.41k|  void swap(any_invocable_impl& rhs) noexcept {
  209|  6.41k|    if (handle_) {
  ------------------
  |  Branch (209:9): [True: 0, False: 6.41k]
  ------------------
  210|      0|      if (rhs.handle_) {
  ------------------
  |  Branch (210:11): [True: 0, False: 0]
  ------------------
  211|      0|        storage tmp;
  212|      0|        handle_(action::move, &tmp, &storage_);
  213|      0|        rhs.handle_(action::move, &storage_, &rhs.storage_);
  214|      0|        handle_(action::move, &rhs.storage_, &tmp);
  215|      0|        std::swap(handle_, rhs.handle_);
  216|      0|        std::swap(call_, rhs.call_);
  217|      0|      } else {
  218|      0|        rhs.swap(*this);
  219|      0|      }
  220|  6.41k|    } else if (rhs.handle_) {
  ------------------
  |  Branch (220:16): [True: 0, False: 6.41k]
  ------------------
  221|      0|      rhs.handle_(action::move, &storage_, &rhs.storage_);
  222|      0|      handle_ = rhs.handle_;
  223|      0|      call_ = rhs.call_;
  224|      0|      rhs.handle_ = nullptr;
  225|      0|    }
  226|  6.41k|  }

_ZN3uWS15DeflationStream7deflateEPNS_11ZlibContextENSt3__117basic_string_viewIcNS3_11char_traitsIcEEEEb:
   90|  2.84k|    std::string_view deflate(ZlibContext * /*zlibContext*/, std::string_view raw, bool /*reset*/) {
   91|  2.84k|        return raw;
   92|  2.84k|    }
_ZN3uWS15InflationStream7inflateEPNS_11ZlibContextENSt3__117basic_string_viewIcNS3_11char_traitsIcEEEEmb:
   83|  1.40k|    std::optional<std::string_view> inflate(ZlibContext * /*zlibContext*/, std::string_view compressed, size_t maxPayloadLength, bool /*reset*/) {
   84|  1.40k|        return compressed.substr(0, std::min(maxPayloadLength, compressed.length()));
   85|  1.40k|    }
_ZN3uWS15InflationStreamC2ENS_15CompressOptionsE:
   86|  6.41k|    InflationStream(CompressOptions /*compressOptions*/) {
   87|  6.41k|    }
_ZN3uWS15DeflationStreamC2ENS_15CompressOptionsE:
   93|  6.41k|    DeflationStream(CompressOptions /*compressOptions*/) {
   94|  6.41k|    }

EpollHelloWorld.cpp:_ZN3uWSL20getDecodedQueryValueENSt3__117basic_string_viewIcNS0_11char_traitsIcEEEES4_:
   28|  2.02k|    static inline std::string_view getDecodedQueryValue(std::string_view key, std::string_view rawQuery) {
   29|       |
   30|       |        /* Can't have a value without a key */
   31|  2.02k|        if (!key.length()) {
  ------------------
  |  Branch (31:13): [True: 0, False: 2.02k]
  ------------------
   32|      0|            return {};
   33|      0|        }
   34|       |
   35|       |        /* Start with the whole querystring including initial '?' */
   36|  2.02k|        std::string_view queryString = rawQuery;
   37|       |
   38|       |        /* List of key, value could be cached for repeated fetches similar to how headers are, todo! */
   39|  3.71k|        while (queryString.length()) {
  ------------------
  |  Branch (39:16): [True: 3.05k, False: 665]
  ------------------
   40|       |            /* Find boundaries of this statement */
   41|  3.05k|            std::string_view statement = queryString.substr(1, queryString.find('&', 1) - 1);
   42|       |
   43|       |            /* Only bother if first char of key match (early exit) */
   44|  3.05k|            if (statement.length() && statement[0] == key[0]) {
  ------------------
  |  Branch (44:17): [True: 2.33k, False: 716]
  |  Branch (44:39): [True: 1.95k, False: 381]
  ------------------
   45|       |                /* Equal sign must be present and not in the end of statement */
   46|  1.95k|                auto equality = statement.find('=');
   47|  1.95k|                if (equality != std::string_view::npos) {
  ------------------
  |  Branch (47:21): [True: 1.45k, False: 505]
  ------------------
   48|       |
   49|  1.45k|                    std::string_view statementKey = statement.substr(0, equality);
   50|  1.45k|                    std::string_view statementValue = statement.substr(equality + 1);
   51|       |
   52|       |                    /* String comparison */
   53|  1.45k|                    if (key == statementKey) {
  ------------------
  |  Branch (53:25): [True: 852, False: 600]
  ------------------
   54|       |
   55|       |                        /* Decode value inplace, put null at end if before length of original */
   56|    852|                        char *in = (char *) statementValue.data();
   57|       |
   58|       |                        /* Write offset */
   59|    852|                        unsigned int out = 0;
   60|       |
   61|       |                        /* Walk over all chars until end or null char, decoding in place */
   62|  6.14k|                        for (unsigned int i = 0; i < statementValue.length() && in[i]; i++) {
  ------------------
  |  Branch (62:50): [True: 5.52k, False: 623]
  |  Branch (62:81): [True: 5.52k, False: 0]
  ------------------
   63|       |                                /* Only bother with '%' */
   64|  5.52k|                                if (in[i] == '%') {
  ------------------
  |  Branch (64:37): [True: 1.47k, False: 4.04k]
  ------------------
   65|       |                                    /* Do we have enough data for two bytes hex? */
   66|  1.47k|                                    if (i + 2 >= statementValue.length()) {
  ------------------
  |  Branch (66:41): [True: 229, False: 1.24k]
  ------------------
   67|    229|                                        return {};
   68|    229|                                    }
   69|       |
   70|       |                                    /* Two bytes hex */
   71|  1.24k|                                    int hex1 = in[i + 1] - '0';
   72|  1.24k|                                    if (hex1 > 9) {
  ------------------
  |  Branch (72:41): [True: 866, False: 379]
  ------------------
   73|    866|                                        hex1 &= 223;
   74|    866|                                        hex1 -= 7;
   75|    866|                                    }
   76|       |
   77|  1.24k|                                    int hex2 = in[i + 2] - '0';
   78|  1.24k|                                    if (hex2 > 9) {
  ------------------
  |  Branch (78:41): [True: 712, False: 533]
  ------------------
   79|    712|                                        hex2 &= 223;
   80|    712|                                        hex2 -= 7;
   81|    712|                                    }
   82|       |
   83|  1.24k|                                    *((unsigned char *) &in[out]) = (unsigned char) (hex1 * 16 + hex2);
   84|  1.24k|                                    i += 2;
   85|  4.04k|                                } else {
   86|       |                                    /* Is this even a rule? */
   87|  4.04k|                                    if (in[i] == '+') {
  ------------------
  |  Branch (87:41): [True: 287, False: 3.76k]
  ------------------
   88|    287|                                        in[out] = ' ';
   89|  3.76k|                                    } else {
   90|  3.76k|                                        in[out] = in[i];
   91|  3.76k|                                    }
   92|  4.04k|                                }
   93|       |
   94|       |                                /* We always only write one char */
   95|  5.29k|                                out++;
   96|  5.29k|                        }
   97|       |
   98|       |                        /* If decoded string is shorter than original, put null char to stop next read */
   99|    623|                        if (out < statementValue.length()) {
  ------------------
  |  Branch (99:29): [True: 326, False: 297]
  ------------------
  100|    326|                            in[out] = 0;
  101|    326|                        }
  102|       |
  103|    623|                        return statementValue.substr(0, out);
  104|    852|                    }
  105|  1.45k|                } else {
  106|       |                    /* This querystring is invalid, cannot parse it */
  107|    505|                    return {nullptr, 0};
  108|    505|                }
  109|  1.95k|            }
  110|       |
  111|  1.69k|            queryString.remove_prefix(statement.length() + 1);
  112|  1.69k|        }
  113|       |
  114|       |        /* Nothing found is given as nullptr, while empty string is given as some pointer to the given buffer */
  115|    665|        return {nullptr, 0};
  116|  2.02k|    }

_ZN3uWS9TopicTreeINS_16TopicTreeMessageENS_19TopicTreeBigMessageEEC2ENSt3__18functionIFbPNS_10SubscriberERS1_NS3_13IteratorFlagsEEEE:
  147|  6.41k|    TopicTree(std::function<bool(Subscriber *, T &, IteratorFlags)> cb) : cb(cb) {
  148|       |
  149|  6.41k|    }
_ZN3uWS9TopicTreeINS_16TopicTreeMessageENS_19TopicTreeBigMessageEE5drainEv:
  268|  3.19M|    void drain() {
  269|  3.19M|        if (drainableSubscribers) {
  ------------------
  |  Branch (269:13): [True: 0, False: 3.19M]
  ------------------
  270|       |            /* Drain one socket a time */
  271|      0|            for (Subscriber *s = drainableSubscribers; s; s = s->next) {
  ------------------
  |  Branch (271:56): [True: 0, False: 0]
  ------------------
  272|       |                /* Instead of unlinking every single subscriber, we just leave the list undefined
  273|       |                 * and reset drainableSubscribers ptr below. */
  274|      0|                drainImpl(s);
  275|      0|            }
  276|       |            /* Drain always clears drainableSubscribers and outgoingMessages */
  277|      0|            drainableSubscribers = nullptr;
  278|      0|            outgoingMessages.clear();
  279|      0|        }
  280|  3.19M|    }
_ZN3uWS9TopicTreeINS_16TopicTreeMessageENS_19TopicTreeBigMessageEE14freeSubscriberEPNS_10SubscriberE:
  222|  40.1k|    void freeSubscriber(Subscriber *s) {
  223|       |
  224|       |        /* I guess we call this one even if we are not subscribers */
  225|  40.1k|        if (!s) {
  ------------------
  |  Branch (225:13): [True: 40.1k, False: 0]
  ------------------
  226|  40.1k|            return;
  227|  40.1k|        }
  228|       |
  229|       |        /* For all topics, unsubscribe */
  230|      0|        for (Topic *topicPtr : s->topics) {
  ------------------
  |  Branch (230:30): [True: 0, False: 0]
  ------------------
  231|       |            /* If we are the last subscriber, simply remove the whole topic */
  232|      0|            if (topicPtr->size() == 1) {
  ------------------
  |  Branch (232:17): [True: 0, False: 0]
  ------------------
  233|      0|                topics.erase(topicPtr->name);
  234|      0|            } else {
  235|       |                /* Otherwise just remove us */
  236|      0|                topicPtr->erase(s);
  237|      0|            }
  238|      0|        }
  239|       |
  240|       |        /* We also need to unlink us */
  241|      0|        if (s->needsDrainage()) {
  ------------------
  |  Branch (241:13): [True: 0, False: 0]
  ------------------
  242|      0|            unlinkDrainableSubscriber(s);
  243|      0|        }
  244|       |
  245|      0|        delete s;
  246|      0|    }

_ZN3uWS5utils9u32toaHexEjPc:
   28|  5.15k|inline int u32toaHex(uint32_t value, char *dst) {
   29|  5.15k|    char palette[] = "0123456789abcdef";
   30|  5.15k|    char temp[10];
   31|  5.15k|    char *p = temp;
   32|  5.35k|    do {
   33|  5.35k|        *p++ = palette[value & 15];
   34|  5.35k|        value >>= 4;
   35|  5.35k|    } while (value > 0);
  ------------------
  |  Branch (35:14): [True: 198, False: 5.15k]
  ------------------
   36|       |
   37|  5.15k|    int ret = (int) (p - temp);
   38|       |
   39|  5.35k|    do {
   40|  5.35k|        *dst++ = *--p;
   41|  5.35k|    } while (p != temp);
  ------------------
  |  Branch (41:14): [True: 198, False: 5.15k]
  ------------------
   42|       |
   43|  5.15k|    return ret;
   44|  5.15k|}
_ZN3uWS5utils6u64toaEmPc:
   46|  14.1k|inline int u64toa(uint64_t value, char *dst) {
   47|  14.1k|    char temp[20];
   48|  14.1k|    char *p = temp;
   49|  26.2k|    do {
   50|  26.2k|        *p++ = (char) ((value % 10) + '0');
   51|  26.2k|        value /= 10;
   52|  26.2k|    } while (value > 0);
  ------------------
  |  Branch (52:14): [True: 12.1k, False: 14.1k]
  ------------------
   53|       |
   54|  14.1k|    int ret = (int) (p - temp);
   55|       |
   56|  26.2k|    do {
   57|  26.2k|        *dst++ = *--p;
   58|  26.2k|    } while (p != temp);
  ------------------
  |  Branch (58:14): [True: 12.1k, False: 14.1k]
  ------------------
   59|       |
   60|  14.1k|    return ret;
   61|  14.1k|}

EpollHelloWorld.cpp:_ZN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataE3endEiNSt3__117basic_string_viewIcNS3_11char_traitsIcEEEE:
  196|  5.90k|    void end(int code = 0, std::string_view message = {}) {
  197|       |        /* Check if we already called this one */
  198|  5.90k|        WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) this);
  199|  5.90k|        if (webSocketData->isShuttingDown) {
  ------------------
  |  Branch (199:13): [True: 0, False: 5.90k]
  ------------------
  200|      0|            return;
  201|      0|        }
  202|       |
  203|       |        /* We postpone any FIN sending to either drainage or uncorking */
  204|  5.90k|        webSocketData->isShuttingDown = true;
  205|       |
  206|       |        /* Format and send the close frame */
  207|  5.90k|        static const int MAX_CLOSE_PAYLOAD = 123;
  208|  5.90k|        size_t length = std::min<size_t>(MAX_CLOSE_PAYLOAD, message.length());
  209|  5.90k|        char closePayload[MAX_CLOSE_PAYLOAD + 2];
  210|  5.90k|        size_t closePayloadLength = protocol::formatClosePayload(closePayload, (uint16_t) code, message.data(), length);
  211|  5.90k|        bool ok = send(std::string_view(closePayload, closePayloadLength), OpCode::CLOSE);
  212|       |
  213|       |        /* FIN if we are ok and not corked */
  214|  5.90k|        if (!this->isCorked()) {
  ------------------
  |  Branch (214:13): [True: 0, False: 5.90k]
  ------------------
  215|      0|            if (ok) {
  ------------------
  |  Branch (215:17): [True: 0, False: 0]
  ------------------
  216|       |                /* If we are not corked, and we just sent off everything, we need to FIN right here.
  217|       |                 * In all other cases, we need to fin either if uncork was successful, or when drainage is complete. */
  218|      0|                this->shutdown();
  219|      0|            }
  220|      0|        }
  221|       |
  222|  5.90k|        WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL,
  223|  5.90k|            (us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this)
  224|  5.90k|        );
  225|       |
  226|       |        /* Set shorter timeout (use ping-timeout) to avoid long hanging sockets after end() on broken connections */
  227|  5.90k|        Super::timeout(webSocketContextData->idleTimeoutComponents.second);
  228|       |
  229|       |        /* At this point we iterate all currently held subscriptions and emit an event for all of them */
  230|  5.90k|        if (webSocketData->subscriber && webSocketContextData->subscriptionHandler) {
  ------------------
  |  Branch (230:13): [True: 0, False: 5.90k]
  |  Branch (230:42): [True: 0, False: 0]
  ------------------
  231|      0|            for (Topic *t : webSocketData->subscriber->topics) {
  ------------------
  |  Branch (231:27): [True: 0, False: 0]
  ------------------
  232|      0|                webSocketContextData->subscriptionHandler(this, t->name, (int) t->size() - 1, (int) t->size());
  233|      0|            }
  234|      0|        }
  235|       |
  236|       |        /* Make sure to unsubscribe from any pub/sub node at exit */
  237|  5.90k|        webSocketContextData->topicTree->freeSubscriber(webSocketData->subscriber);
  238|  5.90k|        webSocketData->subscriber = nullptr;
  239|       |
  240|       |        /* Emit close event */
  241|  5.90k|        if (webSocketContextData->closeHandler) {
  ------------------
  |  Branch (241:13): [True: 5.90k, False: 0]
  ------------------
  242|  5.90k|            webSocketContextData->closeHandler(this, code, message);
  243|  5.90k|        }
  244|  5.90k|    }
EpollHelloWorld.cpp:_ZN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataE4sendENSt3__117basic_string_viewIcNS3_11char_traitsIcEEEENS_6OpCodeEbb:
   92|  23.5k|    SendStatus send(std::string_view message, OpCode opCode = OpCode::BINARY, bool compress = false, bool fin = true) {
   93|  23.5k|        WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL,
   94|  23.5k|            (us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this)
   95|  23.5k|        );
   96|       |
   97|       |        /* Skip sending and report success if we are over the limit of maxBackpressure */
   98|  23.5k|        if (webSocketContextData->maxBackpressure && webSocketContextData->maxBackpressure < getBufferedAmount()) {
  ------------------
  |  Branch (98:13): [True: 23.5k, False: 0]
  |  Branch (98:54): [True: 740, False: 22.7k]
  ------------------
   99|       |            /* Also defer a close if we should */
  100|    740|            if (webSocketContextData->closeOnBackpressureLimit) {
  ------------------
  |  Branch (100:17): [True: 0, False: 740]
  ------------------
  101|      0|                us_socket_shutdown_read(SSL, (us_socket_t *) this);
  102|      0|            }
  103|       |
  104|       |            /* It is okay to call send again from within this callback since we immediately return with DROPPED afterwards */
  105|    740|            if (webSocketContextData->droppedHandler) {
  ------------------
  |  Branch (105:17): [True: 0, False: 740]
  ------------------
  106|      0|                webSocketContextData->droppedHandler(this, message, opCode);
  107|      0|            }
  108|       |
  109|    740|            return DROPPED;
  110|    740|        }
  111|       |
  112|       |        /* If we are subscribers and have messages to drain we need to drain them here to stay synced */
  113|  22.7k|        WebSocketData *webSocketData = (WebSocketData *) Super::getAsyncSocketData();
  114|       |
  115|       |        /* Special path for long sends of non-compressed, non-SSL messages */
  116|  22.7k|        if (message.length() >= 16 * 1024 && !compress && !SSL && !webSocketData->subscriber && getBufferedAmount() == 0 && Super::getLoopData()->corkOffset == 0) {
  ------------------
  |  Branch (116:13): [True: 67, False: 22.7k]
  |  Branch (116:46): [True: 0, False: 67]
  |  Branch (116:59): [Folded - Ignored]
  |  Branch (116:67): [True: 0, False: 0]
  |  Branch (116:97): [True: 0, False: 0]
  |  Branch (116:125): [True: 0, False: 0]
  ------------------
  117|      0|            char header[10];
  118|      0|            int header_length = (int) protocol::formatMessage<isServer>(header, nullptr, 0, opCode, message.length(), compress, fin);
  119|      0|            int written = us_socket_write2(0, (struct us_socket_t *)this, header, header_length, message.data(), (int) message.length());
  120|       |        
  121|      0|            if (written != header_length + (int) message.length()) {
  ------------------
  |  Branch (121:17): [True: 0, False: 0]
  ------------------
  122|       |                /* Buffer up backpressure */
  123|      0|                if (written > header_length) {
  ------------------
  |  Branch (123:21): [True: 0, False: 0]
  ------------------
  124|      0|                    webSocketData->buffer.append(message.data() + written - header_length, message.length() - (size_t) (written - header_length));
  125|      0|                } else {
  126|      0|                    webSocketData->buffer.append(header + written, (size_t) header_length - (size_t) written);
  127|      0|                    webSocketData->buffer.append(message.data(), message.length());
  128|      0|                }
  129|       |                /* We cannot still be corked if we have backpressure.
  130|       |                 * We also cannot uncork normally since it will re-write the already buffered
  131|       |                 * up backpressure again. */
  132|      0|                Super::uncorkWithoutSending();
  133|      0|                return BACKPRESSURE;
  134|      0|            }
  135|  22.7k|        } else {
  136|       |
  137|  22.7k|            if (webSocketData->subscriber) {
  ------------------
  |  Branch (137:17): [True: 0, False: 22.7k]
  ------------------
  138|       |                /* This will call back into us, send. */
  139|      0|                webSocketContextData->topicTree->drain(webSocketData->subscriber);
  140|      0|            }
  141|       |
  142|       |            /* Transform the message to compressed domain if requested */
  143|  22.7k|            if (compress) {
  ------------------
  |  Branch (143:17): [True: 9.30k, False: 13.4k]
  ------------------
  144|  9.30k|                WebSocketData *webSocketData = (WebSocketData *) Super::getAsyncSocketData();
  145|       |
  146|       |                /* Check and correct the compress hint. It is never valid to compress 0 bytes */
  147|  9.30k|                if (message.length() && opCode < 3 && webSocketData->compressionStatus == WebSocketData::ENABLED) {
  ------------------
  |  Branch (147:21): [True: 7.44k, False: 1.86k]
  |  Branch (147:41): [True: 7.44k, False: 0]
  |  Branch (147:55): [True: 2.84k, False: 4.59k]
  ------------------
  148|  2.84k|                    LoopData *loopData = Super::getLoopData();
  149|       |                    /* Compress using either shared or dedicated deflationStream */
  150|  2.84k|                    if (webSocketData->deflationStream) {
  ------------------
  |  Branch (150:25): [True: 0, False: 2.84k]
  ------------------
  151|      0|                        message = webSocketData->deflationStream->deflate(loopData->zlibContext, message, false);
  152|  2.84k|                    } else {
  153|  2.84k|                        message = loopData->deflationStream->deflate(loopData->zlibContext, message, true);
  154|  2.84k|                    }
  155|  6.45k|                } else {
  156|  6.45k|                    compress = false;
  157|  6.45k|                }
  158|  9.30k|            }
  159|       |
  160|       |            /* Get size, allocate size, write if needed */
  161|  22.7k|            size_t messageFrameSize = protocol::messageFrameSize(message.length());
  162|  22.7k|            auto [sendBuffer, sendBufferAttribute] = Super::getSendBuffer(messageFrameSize);
  163|  22.7k|            protocol::formatMessage<isServer>(sendBuffer, message.data(), message.length(), opCode, message.length(), compress, fin);
  164|       |
  165|       |            /* Depending on size of message we have different paths */
  166|  22.7k|            if (sendBufferAttribute == SendBufferAttribute::NEEDS_DRAIN) {
  ------------------
  |  Branch (166:17): [True: 17.3k, False: 5.40k]
  ------------------
  167|       |                /* This is a drain */
  168|  17.3k|                auto[written, failed] = Super::write(nullptr, 0);
  169|  17.3k|                if (failed) {
  ------------------
  |  Branch (169:21): [True: 16.4k, False: 957]
  ------------------
  170|       |                    /* Return false for failure, skipping to reset the timeout below */
  171|  16.4k|                    return BACKPRESSURE;
  172|  16.4k|                }
  173|  17.3k|            } else if (sendBufferAttribute == SendBufferAttribute::NEEDS_UNCORK) {
  ------------------
  |  Branch (173:24): [True: 0, False: 5.40k]
  ------------------
  174|       |                /* Uncork if we came here uncorked */
  175|      0|                auto [written, failed] = Super::uncork();
  176|      0|                if (failed) {
  ------------------
  |  Branch (176:21): [True: 0, False: 0]
  ------------------
  177|      0|                    return BACKPRESSURE;
  178|      0|                }
  179|      0|            }
  180|       |
  181|  22.7k|        }
  182|       |
  183|       |        /* Every successful send resets the timeout */
  184|  6.36k|        if (webSocketContextData->resetIdleTimeoutOnSend) {
  ------------------
  |  Branch (184:13): [True: 0, False: 6.36k]
  ------------------
  185|      0|            Super::timeout(webSocketContextData->idleTimeoutComponents.first);
  186|      0|            WebSocketData *webSocketData = (WebSocketData *) Super::getAsyncSocketData();
  187|      0|            webSocketData->hasTimedOut = false;
  188|      0|        }
  189|       |
  190|       |        /* Return success */
  191|  6.36k|        return SUCCESS;
  192|  22.7k|    }
EpollHelloWorld.cpp:_ZN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataE11getUserDataEv:
   44|  80.3k|    USERDATA *getUserData() {
   45|  80.3k|        WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) this);
   46|       |        /* We just have it overallocated by sizeof type */
   47|  80.3k|        return (USERDATA *) (webSocketData + 1);
   48|  80.3k|    }
EpollHelloWorld.cpp:_ZN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataE4initEbNS_15CompressOptionsEONS_12BackPressureE:
   37|  40.1k|    void *init(bool perMessageDeflate, CompressOptions compressOptions, BackPressure &&backpressure) {
   38|  40.1k|        new (us_socket_ext(SSL, (us_socket_t *) this)) WebSocketData(perMessageDeflate, compressOptions, std::move(backpressure));
   39|  40.1k|        return this;
   40|  40.1k|    }

EpollHelloWorld.cpp:_ZN3uWS16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataE6createEPNS_4LoopEP19us_socket_context_tPNS_9TopicTreeINS_16TopicTreeMessageENS_19TopicTreeBigMessageEEE:
  420|  12.8k|    static WebSocketContext *create(Loop */*loop*/, us_socket_context_t *parentSocketContext, TopicTree<TopicTreeMessage, TopicTreeBigMessage> *topicTree) {
  421|  12.8k|        WebSocketContext *webSocketContext = (WebSocketContext *) us_create_child_socket_context(SSL, parentSocketContext, sizeof(WebSocketContextData<SSL, USERDATA>));
  422|  12.8k|        if (!webSocketContext) {
  ------------------
  |  Branch (422:13): [True: 0, False: 12.8k]
  ------------------
  423|      0|            return nullptr;
  424|      0|        }
  425|       |
  426|       |        /* Init socket context data */
  427|  12.8k|        new ((WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, (us_socket_context_t *)webSocketContext)) WebSocketContextData<SSL, USERDATA>(topicTree);
  428|  12.8k|        return webSocketContext->init();
  429|  12.8k|    }
EpollHelloWorld.cpp:_ZN3uWS16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataE4initEv:
  248|  12.8k|    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|  12.8k|        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|  12.8k|            WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
  257|  12.8k|            if (!webSocketData->isShuttingDown) {
  258|       |                /* Emit close event */
  259|  12.8k|                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|  12.8k|                if (webSocketData->subscriber && webSocketContextData->subscriptionHandler) {
  263|  12.8k|                    for (Topic *t : webSocketData->subscriber->topics) {
  264|  12.8k|                        webSocketContextData->subscriptionHandler((WebSocket<SSL, isServer, USERDATA> *) s, t->name, (int) t->size() - 1, (int) t->size());
  265|  12.8k|                    }
  266|  12.8k|                }
  267|       |
  268|       |                /* Make sure to unsubscribe from any pub/sub node at exit */
  269|  12.8k|                webSocketContextData->topicTree->freeSubscriber(webSocketData->subscriber);
  270|  12.8k|                webSocketData->subscriber = nullptr;
  271|       |
  272|  12.8k|                if (webSocketContextData->closeHandler) {
  273|  12.8k|                    webSocketContextData->closeHandler((WebSocket<SSL, isServer, USERDATA> *) s, 1006, {(char *) reason, (size_t) code});
  274|  12.8k|                }
  275|  12.8k|            }
  276|       |
  277|       |            /* Destruct in-placed data struct */
  278|  12.8k|            webSocketData->~WebSocketData();
  279|       |
  280|  12.8k|            return s;
  281|  12.8k|        });
  282|       |
  283|       |        /* Handle WebSocket data streams */
  284|  12.8k|        us_socket_context_on_data(SSL, getSocketContext(), [](auto *s, char *data, int length) {
  285|       |
  286|       |            /* We need the websocket data */
  287|  12.8k|            WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
  288|       |
  289|       |            /* When in websocket shutdown mode, we do not care for ANY message, whether responding close frame or not.
  290|       |             * We only care for the TCP FIN really, not emitting any message after closing is key */
  291|  12.8k|            if (webSocketData->isShuttingDown) {
  292|  12.8k|                return s;
  293|  12.8k|            }
  294|       |
  295|  12.8k|            auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
  296|  12.8k|            auto *asyncSocket = (AsyncSocket<SSL> *) s;
  297|       |
  298|       |            /* Every time we get data and not in shutdown state we simply reset the timeout */
  299|  12.8k|            asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
  300|  12.8k|            webSocketData->hasTimedOut = false;
  301|       |
  302|       |            /* We always cork on data */
  303|  12.8k|            asyncSocket->cork();
  304|       |
  305|       |            /* This parser has virtually no overhead */
  306|  12.8k|            WebSocketProtocol<isServer, WebSocketContext<SSL, isServer, USERDATA>>::consume(data, (unsigned int) length, (WebSocketState<isServer> *) webSocketData, s);
  307|       |
  308|       |            /* Uncorking a closed socekt is fine, in fact it is needed */
  309|  12.8k|            asyncSocket->uncork();
  310|       |
  311|       |            /* If uncorking was successful and we are in shutdown state then send TCP FIN */
  312|  12.8k|            if (asyncSocket->getBufferedAmount() == 0) {
  313|       |                /* We can now be in shutdown state */
  314|  12.8k|                if (webSocketData->isShuttingDown) {
  315|       |                    /* Shutting down a closed socket is handled by uSockets and just fine */
  316|  12.8k|                    asyncSocket->shutdown();
  317|  12.8k|                }
  318|  12.8k|            }
  319|       |
  320|  12.8k|            return s;
  321|  12.8k|        });
  322|       |
  323|       |        /* Handle HTTP write out (note: SSL_read may trigger this spuriously, the app need to handle spurious calls) */
  324|  12.8k|        us_socket_context_on_writable(SSL, getSocketContext(), [](auto *s) {
  325|       |
  326|       |            /* NOTE: Are we called here corked? If so, the below write code is broken, since
  327|       |             * we will have 0 as getBufferedAmount due to writing to cork buffer, then sending TCP FIN before
  328|       |             * we actually uncorked and sent off things */
  329|       |
  330|       |            /* It makes sense to check for us_is_shut_down here and return if so, to avoid shutting down twice */
  331|  12.8k|            if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) {
  332|  12.8k|                return s;
  333|  12.8k|            }
  334|       |
  335|  12.8k|            AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
  336|  12.8k|            WebSocketData *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
  337|       |
  338|       |            /* We store old backpressure since it is unclear whether write drained anything,
  339|       |             * however, in case of coming here with 0 backpressure we still need to emit drain event */
  340|  12.8k|            unsigned int backpressure = asyncSocket->getBufferedAmount();
  341|       |
  342|       |            /* Drain as much as possible */
  343|  12.8k|            asyncSocket->write(nullptr, 0);
  344|       |
  345|       |            /* Behavior: if we actively drain backpressure, always reset timeout (even if we are in shutdown) */
  346|       |            /* Also reset timeout if we came here with 0 backpressure */
  347|  12.8k|            if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
  348|  12.8k|                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
  349|  12.8k|                asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
  350|  12.8k|                webSocketData->hasTimedOut = false;
  351|  12.8k|            }
  352|       |
  353|       |            /* Are we in (WebSocket) shutdown mode? */
  354|  12.8k|            if (webSocketData->isShuttingDown) {
  355|       |                /* Check if we just now drained completely */
  356|  12.8k|                if (asyncSocket->getBufferedAmount() == 0) {
  357|       |                    /* Now perform the actual TCP/TLS shutdown which was postponed due to backpressure */
  358|  12.8k|                    asyncSocket->shutdown();
  359|  12.8k|                }
  360|  12.8k|            } else if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
  361|       |                /* Only call drain if we actually drained backpressure or if we came here with 0 backpressure */
  362|  12.8k|                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
  363|  12.8k|                if (webSocketContextData->drainHandler) {
  364|  12.8k|                    webSocketContextData->drainHandler((WebSocket<SSL, isServer, USERDATA> *) s);
  365|  12.8k|                }
  366|       |                /* No need to check for closed here as we leave the handler immediately*/
  367|  12.8k|            }
  368|       |
  369|  12.8k|            return s;
  370|  12.8k|        });
  371|       |
  372|       |        /* Handle FIN, HTTP does not support half-closed sockets, so simply close */
  373|  12.8k|        us_socket_context_on_end(SSL, getSocketContext(), [](auto *s) {
  374|       |
  375|       |            /* If we get a fin, we just close I guess */
  376|  12.8k|            us_socket_close(SSL, (us_socket_t *) s, 0, nullptr);
  377|       |
  378|  12.8k|            return s;
  379|  12.8k|        });
  380|       |
  381|  12.8k|        us_socket_context_on_long_timeout(SSL, getSocketContext(), [](auto *s) {
  382|  12.8k|            ((WebSocket<SSL, isServer, USERDATA> *) s)->end(1000, "please reconnect");
  383|       |
  384|  12.8k|            return s;
  385|  12.8k|        });
  386|       |
  387|       |        /* Handle socket timeouts, simply close them so to not confuse client with FIN */
  388|  12.8k|        us_socket_context_on_timeout(SSL, getSocketContext(), [](auto *s) {
  389|       |
  390|  12.8k|            auto *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
  391|  12.8k|            auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
  392|       |
  393|  12.8k|            if (webSocketContextData->sendPingsAutomatically && !webSocketData->isShuttingDown && !webSocketData->hasTimedOut) {
  394|  12.8k|                webSocketData->hasTimedOut = true;
  395|  12.8k|                us_socket_timeout(SSL, s, webSocketContextData->idleTimeoutComponents.second);
  396|       |                /* Send ping without being corked */
  397|  12.8k|                ((AsyncSocket<SSL> *) s)->write("\x89\x00", 2);
  398|  12.8k|                return s;
  399|  12.8k|            }
  400|       |
  401|       |            /* Timeout is very simple; we just close it */
  402|       |            /* Warning: we happen to know forceClose will not use first parameter so pass nullptr here */
  403|  12.8k|            forceClose(nullptr, s, ERR_WEBSOCKET_TIMEOUT);
  404|       |
  405|  12.8k|            return s;
  406|  12.8k|        });
  407|       |
  408|  12.8k|        return this;
  409|  12.8k|    }
EpollHelloWorld.cpp:_ZZN3uWS16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataE4initEvENKUlPT_iPvE_clI11us_socket_tEEDaS4_iS5_:
  254|  40.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|  40.1k|            WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
  257|  40.1k|            if (!webSocketData->isShuttingDown) {
  ------------------
  |  Branch (257:17): [True: 34.2k, False: 5.90k]
  ------------------
  258|       |                /* Emit close event */
  259|  34.2k|                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|  34.2k|                if (webSocketData->subscriber && webSocketContextData->subscriptionHandler) {
  ------------------
  |  Branch (262:21): [True: 0, False: 34.2k]
  |  Branch (262:50): [True: 0, False: 0]
  ------------------
  263|      0|                    for (Topic *t : webSocketData->subscriber->topics) {
  ------------------
  |  Branch (263:35): [True: 0, False: 0]
  ------------------
  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|  34.2k|                webSocketContextData->topicTree->freeSubscriber(webSocketData->subscriber);
  270|  34.2k|                webSocketData->subscriber = nullptr;
  271|       |
  272|  34.2k|                if (webSocketContextData->closeHandler) {
  ------------------
  |  Branch (272:21): [True: 34.2k, False: 0]
  ------------------
  273|  34.2k|                    webSocketContextData->closeHandler((WebSocket<SSL, isServer, USERDATA> *) s, 1006, {(char *) reason, (size_t) code});
  274|  34.2k|                }
  275|  34.2k|            }
  276|       |
  277|       |            /* Destruct in-placed data struct */
  278|  40.1k|            webSocketData->~WebSocketData();
  279|       |
  280|  40.1k|            return s;
  281|  40.1k|        });
EpollHelloWorld.cpp:_ZZN3uWS16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataE4initEvENKUlPT_PciE_clI11us_socket_tEEDaS4_S5_i:
  284|  59.0k|        us_socket_context_on_data(SSL, getSocketContext(), [](auto *s, char *data, int length) {
  285|       |
  286|       |            /* We need the websocket data */
  287|  59.0k|            WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s));
  288|       |
  289|       |            /* When in websocket shutdown mode, we do not care for ANY message, whether responding close frame or not.
  290|       |             * We only care for the TCP FIN really, not emitting any message after closing is key */
  291|  59.0k|            if (webSocketData->isShuttingDown) {
  ------------------
  |  Branch (291:17): [True: 375, False: 58.6k]
  ------------------
  292|    375|                return s;
  293|    375|            }
  294|       |
  295|  58.6k|            auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
  296|  58.6k|            auto *asyncSocket = (AsyncSocket<SSL> *) s;
  297|       |
  298|       |            /* Every time we get data and not in shutdown state we simply reset the timeout */
  299|  58.6k|            asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
  300|  58.6k|            webSocketData->hasTimedOut = false;
  301|       |
  302|       |            /* We always cork on data */
  303|  58.6k|            asyncSocket->cork();
  304|       |
  305|       |            /* This parser has virtually no overhead */
  306|  58.6k|            WebSocketProtocol<isServer, WebSocketContext<SSL, isServer, USERDATA>>::consume(data, (unsigned int) length, (WebSocketState<isServer> *) webSocketData, s);
  307|       |
  308|       |            /* Uncorking a closed socekt is fine, in fact it is needed */
  309|  58.6k|            asyncSocket->uncork();
  310|       |
  311|       |            /* If uncorking was successful and we are in shutdown state then send TCP FIN */
  312|  58.6k|            if (asyncSocket->getBufferedAmount() == 0) {
  ------------------
  |  Branch (312:17): [True: 24.4k, False: 34.2k]
  ------------------
  313|       |                /* We can now be in shutdown state */
  314|  24.4k|                if (webSocketData->isShuttingDown) {
  ------------------
  |  Branch (314:21): [True: 953, False: 23.4k]
  ------------------
  315|       |                    /* Shutting down a closed socket is handled by uSockets and just fine */
  316|    953|                    asyncSocket->shutdown();
  317|    953|                }
  318|  24.4k|            }
  319|       |
  320|  58.6k|            return s;
  321|  59.0k|        });
EpollHelloWorld.cpp:_ZN3uWS16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataE13setCompressedEPNS_14WebSocketStateILb1EEEPv:
   44|  2.60k|    static bool setCompressed(WebSocketState<isServer> */*wState*/, void *s) {
   45|  2.60k|        WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) s);
   46|       |
   47|  2.60k|        if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::ENABLED) {
  ------------------
  |  Branch (47:13): [True: 1.53k, False: 1.06k]
  ------------------
   48|  1.53k|            webSocketData->compressionStatus = WebSocketData::CompressionStatus::COMPRESSED_FRAME;
   49|  1.53k|            return true;
   50|  1.53k|        } else {
   51|  1.06k|            return false;
   52|  1.06k|        }
   53|  2.60k|    }
EpollHelloWorld.cpp:_ZN3uWS16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataE10forceCloseEPNS_14WebSocketStateILb1EEEPvNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEE:
   55|  12.9k|    static void forceClose(WebSocketState<isServer> */*wState*/, void *s, std::string_view reason = {}) {
   56|  12.9k|        us_socket_close(SSL, (us_socket_t *) s, (int) reason.length(), (void *) reason.data());
   57|  12.9k|    }
EpollHelloWorld.cpp:_ZN3uWS16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataE19refusePayloadLengthEmPNS_14WebSocketStateILb1EEEPv:
  241|  97.2k|    static bool refusePayloadLength(uint64_t length, WebSocketState<isServer> */*wState*/, void *s) {
  242|  97.2k|        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|  97.2k|        return webSocketContextData->maxPayloadLength < length;
  246|  97.2k|    }
EpollHelloWorld.cpp:_ZN3uWS16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataE14handleFragmentEPcmjibPNS_14WebSocketStateILb1EEEPv:
   60|  81.8k|    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|  81.8k|        WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
   63|  81.8k|        WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) s);
   64|       |
   65|       |        /* Is this a non-control frame? */
   66|  81.8k|        if (opCode < 3) {
  ------------------
  |  Branch (66:13): [True: 63.4k, False: 18.3k]
  ------------------
   67|       |            /* Did we get everything in one go? */
   68|  63.4k|            if (!remainingBytes && fin && !webSocketData->fragmentBuffer.length()) {
  ------------------
  |  Branch (68:17): [True: 27.9k, False: 35.4k]
  |  Branch (68:36): [True: 14.8k, False: 13.1k]
  |  Branch (68:43): [True: 12.0k, False: 2.79k]
  ------------------
   69|       |
   70|       |                /* Handle compressed frame */
   71|  12.0k|                if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::COMPRESSED_FRAME) {
  ------------------
  |  Branch (71:21): [True: 752, False: 11.3k]
  ------------------
   72|    752|                        webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED;
   73|       |
   74|    752|                        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|    752|                        std::optional<std::string_view> inflatedFrame;
   77|    752|                        if (webSocketData->inflationStream) {
  ------------------
  |  Branch (77:29): [True: 0, False: 752]
  ------------------
   78|      0|                            inflatedFrame = webSocketData->inflationStream->inflate(loopData->zlibContext, {data, length}, webSocketContextData->maxPayloadLength, false);
   79|    752|                        } else {
   80|    752|                            inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {data, length}, webSocketContextData->maxPayloadLength, true);
   81|    752|                        }
   82|       |
   83|    752|                        if (!inflatedFrame.has_value()) {
  ------------------
  |  Branch (83:29): [True: 0, False: 752]
  ------------------
   84|      0|                            forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE_INFLATION);
   85|      0|                            return true;
   86|    752|                        } else {
   87|    752|                            data = (char *) inflatedFrame->data();
   88|    752|                            length = inflatedFrame->length();
   89|    752|                        }
   90|    752|                }
   91|       |
   92|       |                /* Check text messages for Utf-8 validity */
   93|  12.0k|                if (opCode == 1 && !protocol::isValidUtf8((unsigned char *) data, length)) {
  ------------------
  |  Branch (93:21): [True: 9.22k, False: 2.83k]
  |  Branch (93:36): [True: 2.62k, False: 6.60k]
  ------------------
   94|  2.62k|                    forceClose(webSocketState, s, ERR_INVALID_TEXT);
   95|  2.62k|                    return true;
   96|  2.62k|                }
   97|       |
   98|       |                /* Emit message event & break if we are closed or shut down when returning */
   99|  9.43k|                if (webSocketContextData->messageHandler) {
  ------------------
  |  Branch (99:21): [True: 7.77k, False: 1.65k]
  ------------------
  100|  7.77k|                    webSocketContextData->messageHandler((WebSocket<SSL, isServer, USERDATA> *) s, std::string_view(data, length), (OpCode) opCode);
  101|  7.77k|                    if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
  ------------------
  |  Branch (101:25): [True: 0, False: 7.77k]
  |  Branch (101:72): [True: 0, False: 7.77k]
  ------------------
  102|      0|                        return true;
  103|      0|                    }
  104|  7.77k|                }
  105|  51.3k|            } else {
  106|       |                /* Allocate fragment buffer up front first time */
  107|  51.3k|                if (!webSocketData->fragmentBuffer.length()) {
  ------------------
  |  Branch (107:21): [True: 10.2k, False: 41.1k]
  ------------------
  108|  10.2k|                    webSocketData->fragmentBuffer.reserve(length + remainingBytes);
  109|  10.2k|                }
  110|       |                /* Fragments forming a big message are not caught until appending them */
  111|  51.3k|                if (refusePayloadLength(length + webSocketData->fragmentBuffer.length(), webSocketState, s)) {
  ------------------
  |  Branch (111:21): [True: 75, False: 51.3k]
  ------------------
  112|     75|                    forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE);
  113|     75|                    return true;
  114|     75|                }
  115|  51.3k|                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.3k|                if (!remainingBytes && fin) {
  ------------------
  |  Branch (119:21): [True: 15.9k, False: 35.4k]
  |  Branch (119:40): [True: 2.79k, False: 13.1k]
  ------------------
  120|       |
  121|       |                    /* Handle compression */
  122|  2.79k|                    if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::COMPRESSED_FRAME) {
  ------------------
  |  Branch (122:25): [True: 654, False: 2.14k]
  ------------------
  123|    654|                            webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED;
  124|       |
  125|       |                            /* 9 bytes of padding for libdeflate, 4 for zlib */
  126|    654|                            webSocketData->fragmentBuffer.append("123456789");
  127|       |
  128|    654|                            LoopData *loopData = (LoopData *) us_loop_ext(
  129|    654|                                us_socket_context_loop(SSL,
  130|    654|                                    us_socket_context(SSL, (us_socket_t *) s)
  131|    654|                                )
  132|    654|                            );
  133|       |
  134|       |                            /* Decompress using shared or dedicated decompressor */
  135|    654|                            std::optional<std::string_view> inflatedFrame;
  136|    654|                            if (webSocketData->inflationStream) {
  ------------------
  |  Branch (136:33): [True: 0, False: 654]
  ------------------
  137|      0|                                inflatedFrame = webSocketData->inflationStream->inflate(loopData->zlibContext, {webSocketData->fragmentBuffer.data(), webSocketData->fragmentBuffer.length() - 9}, webSocketContextData->maxPayloadLength, false);
  138|    654|                            } else {
  139|    654|                                inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {webSocketData->fragmentBuffer.data(), webSocketData->fragmentBuffer.length() - 9}, webSocketContextData->maxPayloadLength, true);
  140|    654|                            }
  141|       |
  142|    654|                            if (!inflatedFrame.has_value()) {
  ------------------
  |  Branch (142:33): [True: 0, False: 654]
  ------------------
  143|      0|                                forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE_INFLATION);
  144|      0|                                return true;
  145|    654|                            } else {
  146|    654|                                data = (char *) inflatedFrame->data();
  147|    654|                                length = inflatedFrame->length();
  148|    654|                            }
  149|       |
  150|       |
  151|  2.14k|                    } else {
  152|       |                        // reset length and data ptrs
  153|  2.14k|                        length = webSocketData->fragmentBuffer.length();
  154|  2.14k|                        data = webSocketData->fragmentBuffer.data();
  155|  2.14k|                    }
  156|       |
  157|       |                    /* Check text messages for Utf-8 validity */
  158|  2.79k|                    if (opCode == 1 && !protocol::isValidUtf8((unsigned char *) data, length)) {
  ------------------
  |  Branch (158:25): [True: 746, False: 2.05k]
  |  Branch (158:40): [True: 298, False: 448]
  ------------------
  159|    298|                        forceClose(webSocketState, s, ERR_INVALID_TEXT);
  160|    298|                        return true;
  161|    298|                    }
  162|       |
  163|       |                    /* Emit message and check for shutdown or close */
  164|  2.50k|                    if (webSocketContextData->messageHandler) {
  ------------------
  |  Branch (164:25): [True: 2.27k, False: 231]
  ------------------
  165|  2.27k|                        webSocketContextData->messageHandler((WebSocket<SSL, isServer, USERDATA> *) s, std::string_view(data, length), (OpCode) opCode);
  166|  2.27k|                        if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
  ------------------
  |  Branch (166:29): [True: 0, False: 2.27k]
  |  Branch (166:76): [True: 0, False: 2.27k]
  ------------------
  167|      0|                            return true;
  168|      0|                        }
  169|  2.27k|                    }
  170|       |
  171|       |                    /* If we shutdown or closed, this will be taken care of elsewhere */
  172|  2.50k|                    webSocketData->fragmentBuffer.clear();
  173|  2.50k|                }
  174|  51.3k|            }
  175|  63.4k|        } else {
  176|       |            /* Control frames need the websocket to send pings, pongs and close */
  177|  18.3k|            WebSocket<SSL, isServer, USERDATA> *webSocket = (WebSocket<SSL, isServer, USERDATA> *) s;
  178|       |
  179|  18.3k|            if (!remainingBytes && fin && !webSocketData->controlTipLength) {
  ------------------
  |  Branch (179:17): [True: 14.6k, False: 3.75k]
  |  Branch (179:36): [True: 14.6k, False: 0]
  |  Branch (179:43): [True: 11.7k, False: 2.82k]
  ------------------
  180|  11.7k|                if (opCode == CLOSE) {
  ------------------
  |  Branch (180:21): [True: 4.31k, False: 7.48k]
  ------------------
  181|  4.31k|                    auto closeFrame = protocol::parseClosePayload(data, length);
  182|  4.31k|                    webSocket->end(closeFrame.code, std::string_view(closeFrame.message, closeFrame.length));
  183|  4.31k|                    return true;
  184|  7.48k|                } else {
  185|  7.48k|                    if (opCode == PING) {
  ------------------
  |  Branch (185:25): [True: 6.91k, False: 569]
  ------------------
  186|  6.91k|                        webSocket->send(std::string_view(data, length), (OpCode) OpCode::PONG);
  187|  6.91k|                        if (webSocketContextData->pingHandler) {
  ------------------
  |  Branch (187:29): [True: 6.54k, False: 370]
  ------------------
  188|  6.54k|                            webSocketContextData->pingHandler(webSocket, {data, length});
  189|  6.54k|                            if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
  ------------------
  |  Branch (189:33): [True: 0, False: 6.54k]
  |  Branch (189:80): [True: 0, False: 6.54k]
  ------------------
  190|      0|                                return true;
  191|      0|                            }
  192|  6.54k|                        }
  193|  6.91k|                    } else if (opCode == PONG) {
  ------------------
  |  Branch (193:32): [True: 569, False: 0]
  ------------------
  194|    569|                        if (webSocketContextData->pongHandler) {
  ------------------
  |  Branch (194:29): [True: 373, False: 196]
  ------------------
  195|    373|                            webSocketContextData->pongHandler(webSocket, {data, length});
  196|    373|                            if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
  ------------------
  |  Branch (196:33): [True: 0, False: 373]
  |  Branch (196:80): [True: 0, False: 373]
  ------------------
  197|      0|                                return true;
  198|      0|                            }
  199|    373|                        }
  200|    569|                    }
  201|  7.48k|                }
  202|  11.7k|            } else {
  203|       |                /* Here we never mind any size optimizations as we are in the worst possible path */
  204|  6.57k|                webSocketData->fragmentBuffer.append(data, length);
  205|  6.57k|                webSocketData->controlTipLength += (unsigned int) length;
  206|       |
  207|  6.57k|                if (!remainingBytes && fin) {
  ------------------
  |  Branch (207:21): [True: 2.82k, False: 3.75k]
  |  Branch (207:40): [True: 2.82k, False: 0]
  ------------------
  208|  2.82k|                    char *controlBuffer = (char *) webSocketData->fragmentBuffer.data() + webSocketData->fragmentBuffer.length() - webSocketData->controlTipLength;
  209|  2.82k|                    if (opCode == CLOSE) {
  ------------------
  |  Branch (209:25): [True: 1.59k, False: 1.23k]
  ------------------
  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.59k|                    } else {
  214|  1.23k|                        if (opCode == PING) {
  ------------------
  |  Branch (214:29): [True: 649, False: 584]
  ------------------
  215|    649|                            webSocket->send(std::string_view(controlBuffer, webSocketData->controlTipLength), (OpCode) OpCode::PONG);
  216|    649|                            if (webSocketContextData->pingHandler) {
  ------------------
  |  Branch (216:33): [True: 450, False: 199]
  ------------------
  217|    450|                                webSocketContextData->pingHandler(webSocket, std::string_view(controlBuffer, webSocketData->controlTipLength));
  218|    450|                                if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
  ------------------
  |  Branch (218:37): [True: 0, False: 450]
  |  Branch (218:84): [True: 0, False: 450]
  ------------------
  219|      0|                                    return true;
  220|      0|                                }
  221|    450|                            }
  222|    649|                        } else if (opCode == PONG) {
  ------------------
  |  Branch (222:36): [True: 584, False: 0]
  ------------------
  223|    584|                            if (webSocketContextData->pongHandler) {
  ------------------
  |  Branch (223:33): [True: 274, False: 310]
  ------------------
  224|    274|                                webSocketContextData->pongHandler(webSocket, std::string_view(controlBuffer, webSocketData->controlTipLength));
  225|    274|                                if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) {
  ------------------
  |  Branch (225:37): [True: 0, False: 274]
  |  Branch (225:84): [True: 0, False: 274]
  ------------------
  226|      0|                                    return true;
  227|      0|                                }
  228|    274|                            }
  229|    584|                        }
  230|  1.23k|                    }
  231|       |
  232|       |                    /* Same here, we do not care for any particular smart allocation scheme */
  233|  1.23k|                    webSocketData->fragmentBuffer.resize((unsigned int) webSocketData->fragmentBuffer.length() - webSocketData->controlTipLength);
  234|  1.23k|                    webSocketData->controlTipLength = 0;
  235|  1.23k|                }
  236|  6.57k|            }
  237|  18.3k|        }
  238|  72.9k|        return false;
  239|  81.8k|    }
EpollHelloWorld.cpp:_ZZN3uWS16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataE4initEvENKUlPT_E_clI11us_socket_tEEDaS4_:
  324|  8.87k|        us_socket_context_on_writable(SSL, getSocketContext(), [](auto *s) {
  325|       |
  326|       |            /* NOTE: Are we called here corked? If so, the below write code is broken, since
  327|       |             * we will have 0 as getBufferedAmount due to writing to cork buffer, then sending TCP FIN before
  328|       |             * we actually uncorked and sent off things */
  329|       |
  330|       |            /* It makes sense to check for us_is_shut_down here and return if so, to avoid shutting down twice */
  331|  8.87k|            if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) {
  ------------------
  |  Branch (331:17): [True: 0, False: 8.87k]
  ------------------
  332|      0|                return s;
  333|      0|            }
  334|       |
  335|  8.87k|            AsyncSocket<SSL> *asyncSocket = (AsyncSocket<SSL> *) s;
  336|  8.87k|            WebSocketData *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
  337|       |
  338|       |            /* We store old backpressure since it is unclear whether write drained anything,
  339|       |             * however, in case of coming here with 0 backpressure we still need to emit drain event */
  340|  8.87k|            unsigned int backpressure = asyncSocket->getBufferedAmount();
  341|       |
  342|       |            /* Drain as much as possible */
  343|  8.87k|            asyncSocket->write(nullptr, 0);
  344|       |
  345|       |            /* Behavior: if we actively drain backpressure, always reset timeout (even if we are in shutdown) */
  346|       |            /* Also reset timeout if we came here with 0 backpressure */
  347|  8.87k|            if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
  ------------------
  |  Branch (347:17): [True: 224, False: 8.65k]
  |  Branch (347:34): [True: 6.35k, False: 2.29k]
  ------------------
  348|  6.57k|                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
  349|  6.57k|                asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first);
  350|  6.57k|                webSocketData->hasTimedOut = false;
  351|  6.57k|            }
  352|       |
  353|       |            /* Are we in (WebSocket) shutdown mode? */
  354|  8.87k|            if (webSocketData->isShuttingDown) {
  ------------------
  |  Branch (354:17): [True: 1.94k, False: 6.93k]
  ------------------
  355|       |                /* Check if we just now drained completely */
  356|  1.94k|                if (asyncSocket->getBufferedAmount() == 0) {
  ------------------
  |  Branch (356:21): [True: 878, False: 1.06k]
  ------------------
  357|       |                    /* Now perform the actual TCP/TLS shutdown which was postponed due to backpressure */
  358|    878|                    asyncSocket->shutdown();
  359|    878|                }
  360|  6.93k|            } else if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) {
  ------------------
  |  Branch (360:24): [True: 224, False: 6.70k]
  |  Branch (360:41): [True: 5.04k, False: 1.66k]
  ------------------
  361|       |                /* Only call drain if we actually drained backpressure or if we came here with 0 backpressure */
  362|  5.26k|                auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
  363|  5.26k|                if (webSocketContextData->drainHandler) {
  ------------------
  |  Branch (363:21): [True: 5.04k, False: 226]
  ------------------
  364|  5.04k|                    webSocketContextData->drainHandler((WebSocket<SSL, isServer, USERDATA> *) s);
  365|  5.04k|                }
  366|       |                /* No need to check for closed here as we leave the handler immediately*/
  367|  5.26k|            }
  368|       |
  369|  8.87k|            return s;
  370|  8.87k|        });
EpollHelloWorld.cpp:_ZZN3uWS16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataE4initEvENKUlPT_E0_clI11us_socket_tEEDaS4_:
  373|  1.06k|        us_socket_context_on_end(SSL, getSocketContext(), [](auto *s) {
  374|       |
  375|       |            /* If we get a fin, we just close I guess */
  376|  1.06k|            us_socket_close(SSL, (us_socket_t *) s, 0, nullptr);
  377|       |
  378|  1.06k|            return s;
  379|  1.06k|        });
EpollHelloWorld.cpp:_ZZN3uWS16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataE4initEvENKUlPT_E2_clI11us_socket_tEEDaS4_:
  388|  5.41k|        us_socket_context_on_timeout(SSL, getSocketContext(), [](auto *s) {
  389|       |
  390|  5.41k|            auto *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s));
  391|  5.41k|            auto *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s));
  392|       |
  393|  5.41k|            if (webSocketContextData->sendPingsAutomatically && !webSocketData->isShuttingDown && !webSocketData->hasTimedOut) {
  ------------------
  |  Branch (393:17): [True: 5.41k, False: 0]
  |  Branch (393:65): [True: 2.41k, False: 3.00k]
  |  Branch (393:99): [True: 2.15k, False: 258]
  ------------------
  394|  2.15k|                webSocketData->hasTimedOut = true;
  395|  2.15k|                us_socket_timeout(SSL, s, webSocketContextData->idleTimeoutComponents.second);
  396|       |                /* Send ping without being corked */
  397|  2.15k|                ((AsyncSocket<SSL> *) s)->write("\x89\x00", 2);
  398|  2.15k|                return s;
  399|  2.15k|            }
  400|       |
  401|       |            /* Timeout is very simple; we just close it */
  402|       |            /* Warning: we happen to know forceClose will not use first parameter so pass nullptr here */
  403|  3.26k|            forceClose(nullptr, s, ERR_WEBSOCKET_TIMEOUT);
  404|       |
  405|  3.26k|            return s;
  406|  5.41k|        });
EpollHelloWorld.cpp:_ZN3uWS16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataE4freeEv:
  411|  12.8k|    void free() {
  412|  12.8k|        WebSocketContextData<SSL, USERDATA> *webSocketContextData = (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, (us_socket_context_t *) this);
  413|  12.8k|        webSocketContextData->~WebSocketContextData();
  414|       |
  415|  12.8k|        us_socket_context_free(SSL, (us_socket_context_t *) this);
  416|  12.8k|    }
EpollHelloWorld.cpp:_ZN3uWS16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataE16getSocketContextEv:
   35|  83.3k|    us_socket_context_t *getSocketContext() {
   36|  83.3k|        return (us_socket_context_t *) this;
   37|  83.3k|    }
EpollHelloWorld.cpp:_ZN3uWS16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataE6getExtEv:
   39|   205k|    WebSocketContextData<SSL, USERDATA> *getExt() {
   40|   205k|        return (WebSocketContextData<SSL, USERDATA> *) us_socket_context_ext(SSL, (us_socket_context_t *) this);
   41|   205k|    }

EpollHelloWorld.cpp:_ZN3uWS20WebSocketContextDataILb0EZ4testvE13PerSocketDataEC2EPNS_9TopicTreeINS_16TopicTreeMessageENS_19TopicTreeBigMessageEEE:
  102|  12.8k|    WebSocketContextData(TopicTree<TopicTreeMessage, TopicTreeBigMessage> *topicTree) : topicTree(topicTree) {
  103|       |
  104|  12.8k|    }
EpollHelloWorld.cpp:_ZN3uWS20WebSocketContextDataILb0EZ4testvE13PerSocketDataED2Ev:
   98|  12.8k|    ~WebSocketContextData() {
   99|       |
  100|  12.8k|    }
EpollHelloWorld.cpp:_ZN3uWS20WebSocketContextDataILb0EZ4testvE13PerSocketDataE29calculateIdleTimeoutCompnentsEt:
   86|  12.8k|    void calculateIdleTimeoutCompnents(unsigned short idleTimeout) {
   87|  12.8k|        unsigned short margin = 4;
   88|       |        /* 4, 8 or 16 seconds margin based on idleTimeout */
   89|  25.6k|        while ((int) idleTimeout - margin * 2 >= margin * 2 && margin < 16) {
  ------------------
  |  Branch (89:16): [True: 19.2k, False: 6.41k]
  |  Branch (89:64): [True: 12.8k, False: 6.41k]
  ------------------
   90|  12.8k|            margin = (unsigned short) (margin << 1);
   91|  12.8k|        }
   92|  12.8k|        idleTimeoutComponents = {
   93|  12.8k|            idleTimeout - (sendPingsAutomatically ? margin : 0), /* reduce normal idleTimeout if it is extended by ping-timeout */
  ------------------
  |  Branch (93:28): [True: 12.8k, False: 0]
  ------------------
   94|  12.8k|            margin /* ping-timeout - also used for end() timeout */
   95|  12.8k|        };
   96|  12.8k|    }

_ZN3uWS13WebSocketDataD2Ev:
   69|  40.1k|    ~WebSocketData() {
   70|  40.1k|        if (deflationStream) {
  ------------------
  |  Branch (70:13): [True: 0, False: 40.1k]
  ------------------
   71|      0|            delete deflationStream;
   72|      0|        }
   73|       |
   74|  40.1k|        if (inflationStream) {
  ------------------
  |  Branch (74:13): [True: 0, False: 40.1k]
  ------------------
   75|      0|            delete inflationStream;
   76|      0|        }
   77|       |
   78|  40.1k|        if (subscriber) {
  ------------------
  |  Branch (78:13): [True: 0, False: 40.1k]
  ------------------
   79|      0|            delete subscriber;
   80|      0|        }
   81|  40.1k|    }
_ZN3uWS13WebSocketDataC2EbNS_15CompressOptionsEONS_12BackPressureE:
   55|  40.1k|    WebSocketData(bool perMessageDeflate, CompressOptions compressOptions, BackPressure &&backpressure) : AsyncSocketData<false>(std::move(backpressure)), WebSocketState<true>() {
   56|  40.1k|        compressionStatus = perMessageDeflate ? ENABLED : DISABLED;
  ------------------
  |  Branch (56:29): [True: 2.87k, False: 37.2k]
  ------------------
   57|       |
   58|       |        /* Initialize the dedicated sliding window(s) */
   59|  40.1k|        if (perMessageDeflate) {
  ------------------
  |  Branch (59:13): [True: 2.87k, False: 37.2k]
  ------------------
   60|  2.87k|            if ((compressOptions & CompressOptions::_COMPRESSOR_MASK) != CompressOptions::SHARED_COMPRESSOR) {
  ------------------
  |  Branch (60:17): [True: 0, False: 2.87k]
  ------------------
   61|      0|                deflationStream = new DeflationStream(compressOptions);
   62|      0|            }
   63|  2.87k|            if ((compressOptions & CompressOptions::_DECOMPRESSOR_MASK) != CompressOptions::SHARED_DECOMPRESSOR) {
  ------------------
  |  Branch (63:17): [True: 0, False: 2.87k]
  ------------------
   64|      0|                inflationStream = new InflationStream(compressOptions);
   65|      0|            }
   66|  2.87k|        }
   67|  40.1k|    }

EpollHelloWorld.cpp:_ZN3uWSL20negotiateCompressionEbiiNSt3__117basic_string_viewIcNS0_11char_traitsIcEEEE:
  144|  4.69k|static inline std::tuple<bool, int, int, std::string_view> negotiateCompression(bool wantCompression, int wantedCompressionWindow, int wantedInflationWindow, std::string_view offer) {
  145|       |
  146|       |    /* If we don't want compression then we are done here */
  147|  4.69k|    if (!wantCompression) {
  ------------------
  |  Branch (147:9): [True: 0, False: 4.69k]
  ------------------
  148|      0|        return {false, 0, 0, ""};
  149|      0|    }
  150|       |
  151|  4.69k|    ExtensionsParser ep(offer.data(), offer.length());
  152|       |
  153|  4.69k|    static thread_local std::string response;
  154|  4.69k|    response = "";
  155|       |
  156|  4.69k|    int compressionWindow = wantedCompressionWindow;
  157|  4.69k|    int inflationWindow = wantedInflationWindow;
  158|  4.69k|    bool compression = false;
  159|       |
  160|  4.69k|    if (ep.xWebKitDeflateFrame) {
  ------------------
  |  Branch (160:9): [True: 696, False: 4.00k]
  ------------------
  161|       |        /* We now have compression */
  162|    696|        compression = true;
  163|    696|        response = "x-webkit-deflate-frame";
  164|       |
  165|       |        /* If the other peer has DEMANDED us no sliding window,
  166|       |         * we cannot compress with anything other than shared compressor */
  167|    696|        if (ep.noContextTakeover) {
  ------------------
  |  Branch (167:13): [True: 202, False: 494]
  ------------------
  168|       |            /* We must fail here right now (fix pub/sub) */
  169|    202|#ifndef UWS_ALLOW_SHARED_AND_DEDICATED_COMPRESSOR_MIX
  170|    202|            if (wantedCompressionWindow != 0) {
  ------------------
  |  Branch (170:17): [True: 0, False: 202]
  ------------------
  171|      0|                return {false, 0, 0, ""};
  172|      0|            }
  173|    202|#endif
  174|       |
  175|    202|            compressionWindow = 0;
  176|    202|        }
  177|       |
  178|       |        /* If the other peer has DEMANDED us to use a limited sliding window,
  179|       |         * we have to limit out compression sliding window */
  180|    696|        if (ep.maxWindowBits && ep.maxWindowBits < compressionWindow) {
  ------------------
  |  Branch (180:13): [True: 298, False: 398]
  |  Branch (180:33): [True: 0, False: 298]
  ------------------
  181|      0|            compressionWindow = ep.maxWindowBits;
  182|      0|#ifndef UWS_ALLOW_8_WINDOW_BITS
  183|       |            /* We cannot really deny this, so we have to disable compression in this case */
  184|      0|            if (compressionWindow == 8) {
  ------------------
  |  Branch (184:17): [True: 0, False: 0]
  ------------------
  185|      0|                return {false, 0, 0, ""};
  186|      0|            }
  187|      0|#endif
  188|      0|        }
  189|       |
  190|       |        /* We decide our own inflation sliding window (and their compression sliding window) */
  191|    696|        if (wantedInflationWindow < 15) {
  ------------------
  |  Branch (191:13): [True: 696, False: 0]
  ------------------
  192|    696|            if (!wantedInflationWindow) {
  ------------------
  |  Branch (192:17): [True: 696, False: 0]
  ------------------
  193|    696|                response += "; no_context_takeover";
  194|    696|            } else {
  195|      0|                response += "; max_window_bits=" + std::to_string(wantedInflationWindow);
  196|      0|            }
  197|    696|        }
  198|  4.00k|    } else if (ep.perMessageDeflate) {
  ------------------
  |  Branch (198:16): [True: 2.17k, False: 1.82k]
  ------------------
  199|       |        /* We now have compression */
  200|  2.17k|        compression = true;
  201|  2.17k|        response = "permessage-deflate";
  202|       |
  203|  2.17k|        if (ep.clientNoContextTakeover) {
  ------------------
  |  Branch (203:13): [True: 228, False: 1.94k]
  ------------------
  204|    228|            inflationWindow = 0;
  205|  1.94k|        } else if (ep.clientMaxWindowBits && ep.clientMaxWindowBits != 1) {
  ------------------
  |  Branch (205:20): [True: 429, False: 1.52k]
  |  Branch (205:46): [True: 223, False: 206]
  ------------------
  206|    223|            inflationWindow = std::min<int>(ep.clientMaxWindowBits, inflationWindow);
  207|    223|        }
  208|       |
  209|       |        /* Whatever we have now, write */
  210|  2.17k|        if (inflationWindow < 15) {
  ------------------
  |  Branch (210:13): [True: 2.17k, False: 0]
  ------------------
  211|  2.17k|            if (!inflationWindow || !ep.clientMaxWindowBits) {
  ------------------
  |  Branch (211:17): [True: 2.17k, False: 0]
  |  Branch (211:37): [True: 0, False: 0]
  ------------------
  212|  2.17k|                response += "; client_no_context_takeover";
  213|  2.17k|                inflationWindow = 0;
  214|  2.17k|            } else {
  215|      0|                response += "; client_max_window_bits=" + std::to_string(inflationWindow);
  216|      0|            }
  217|  2.17k|        }
  218|       |
  219|       |        /* This block basically lets the client lower it */
  220|  2.17k|        if (ep.serverNoContextTakeover) {
  ------------------
  |  Branch (220:13): [True: 199, False: 1.97k]
  ------------------
  221|       |        /* This is an important (temporary) fix since we haven't allowed
  222|       |         * these two modes to mix, and pub/sub will not handle this case (yet) */
  223|       |#ifdef UWS_ALLOW_SHARED_AND_DEDICATED_COMPRESSOR_MIX
  224|       |            compressionWindow = 0;
  225|       |#endif
  226|  1.97k|        } else if (ep.serverMaxWindowBits) {
  ------------------
  |  Branch (226:20): [True: 655, False: 1.32k]
  ------------------
  227|    655|            compressionWindow = std::min<int>(ep.serverMaxWindowBits, compressionWindow);
  228|    655|#ifndef UWS_ALLOW_8_WINDOW_BITS
  229|       |            /* Zlib cannot do windowBits=8, memLevel=1 so we raise it up to 9 minimum */
  230|    655|            if (compressionWindow == 8) {
  ------------------
  |  Branch (230:17): [True: 0, False: 655]
  ------------------
  231|      0|                compressionWindow = 9;
  232|      0|            }
  233|    655|#endif
  234|    655|        }
  235|       |
  236|       |        /* Whatever we have now, write */
  237|  2.17k|        if (compressionWindow < 15) {
  ------------------
  |  Branch (237:13): [True: 2.17k, False: 0]
  ------------------
  238|  2.17k|            if (!compressionWindow) {
  ------------------
  |  Branch (238:17): [True: 2.17k, False: 0]
  ------------------
  239|  2.17k|                response += "; server_no_context_takeover";
  240|  2.17k|            } else {
  241|      0|                response += "; server_max_window_bits=" + std::to_string(compressionWindow);
  242|      0|            }
  243|  2.17k|        }
  244|  2.17k|    }
  245|       |
  246|       |    /* A final sanity check (this check does not actually catch too high values!) */
  247|  4.69k|    if ((compressionWindow && compressionWindow < 8) || compressionWindow > 15 || (inflationWindow && inflationWindow < 8) || inflationWindow > 15) {
  ------------------
  |  Branch (247:10): [True: 0, False: 4.69k]
  |  Branch (247:31): [True: 0, False: 0]
  |  Branch (247:57): [True: 0, False: 4.69k]
  |  Branch (247:84): [True: 0, False: 4.69k]
  |  Branch (247:103): [True: 0, False: 0]
  |  Branch (247:127): [True: 0, False: 4.69k]
  ------------------
  248|      0|        return {false, 0, 0, ""};
  249|      0|    }
  250|       |
  251|  4.69k|    return {compression, compressionWindow, inflationWindow, response};
  252|  4.69k|}
_ZN3uWS16ExtensionsParserC2EPKcm:
   93|  4.69k|    ExtensionsParser(const char *data, size_t length) {
   94|  4.69k|        const char *stop = data + length;
   95|  4.69k|        int token = 1;
   96|       |
   97|       |        /* Ignore anything before permessage-deflate or x-webkit-deflate-frame */
   98|  14.4k|        for (; token && token != TOK_PERMESSAGE_DEFLATE && token != TOK_X_WEBKIT_DEFLATE_FRAME; token = getToken(data, stop));
  ------------------
  |  Branch (98:16): [True: 12.5k, False: 1.82k]
  |  Branch (98:25): [True: 10.4k, False: 2.17k]
  |  Branch (98:60): [True: 9.70k, False: 696]
  ------------------
   99|       |
  100|       |        /* What protocol are we going to use? */
  101|  4.69k|        perMessageDeflate = (token == TOK_PERMESSAGE_DEFLATE);
  102|  4.69k|        xWebKitDeflateFrame = (token == TOK_X_WEBKIT_DEFLATE_FRAME);
  103|       |
  104|  16.2k|        while ((token = getToken(data, stop))) {
  ------------------
  |  Branch (104:16): [True: 11.9k, False: 4.27k]
  ------------------
  105|  11.9k|            switch (token) {
  106|    229|            case TOK_X_WEBKIT_DEFLATE_FRAME:
  ------------------
  |  Branch (106:13): [True: 229, False: 11.7k]
  ------------------
  107|       |                /* Duplicates not allowed/supported */
  108|    229|                return;
  109|    396|            case TOK_NO_CONTEXT_TAKEOVER:
  ------------------
  |  Branch (109:13): [True: 396, False: 11.5k]
  ------------------
  110|    396|                noContextTakeover = true;
  111|    396|                break;
  112|    492|            case TOK_MAX_WINDOW_BITS:
  ------------------
  |  Branch (112:13): [True: 492, False: 11.4k]
  ------------------
  113|    492|                maxWindowBits = 1;
  114|    492|                lastInteger = &maxWindowBits;
  115|    492|                break;
  116|    194|            case TOK_PERMESSAGE_DEFLATE:
  ------------------
  |  Branch (116:13): [True: 194, False: 11.7k]
  ------------------
  117|       |                /* Duplicates not allowed/supported */
  118|    194|                return;
  119|    393|            case TOK_SERVER_NO_CONTEXT_TAKEOVER:
  ------------------
  |  Branch (119:13): [True: 393, False: 11.5k]
  ------------------
  120|    393|                serverNoContextTakeover = true;
  121|    393|                break;
  122|    400|            case TOK_CLIENT_NO_CONTEXT_TAKEOVER:
  ------------------
  |  Branch (122:13): [True: 400, False: 11.5k]
  ------------------
  123|    400|                clientNoContextTakeover = true;
  124|    400|                break;
  125|    855|            case TOK_SERVER_MAX_WINDOW_BITS:
  ------------------
  |  Branch (125:13): [True: 855, False: 11.0k]
  ------------------
  126|    855|                serverMaxWindowBits = 1;
  127|    855|                lastInteger = &serverMaxWindowBits;
  128|    855|                break;
  129|    617|            case TOK_CLIENT_MAX_WINDOW_BITS:
  ------------------
  |  Branch (129:13): [True: 617, False: 11.3k]
  ------------------
  130|    617|                clientMaxWindowBits = 1;
  131|    617|                lastInteger = &clientMaxWindowBits;
  132|    617|                break;
  133|  8.37k|            default:
  ------------------
  |  Branch (133:13): [True: 8.37k, False: 3.57k]
  ------------------
  134|  8.37k|                if (token < 0 && lastInteger) {
  ------------------
  |  Branch (134:21): [True: 2.65k, False: 5.71k]
  |  Branch (134:34): [True: 2.15k, False: 505]
  ------------------
  135|  2.15k|                    *lastInteger = -token;
  136|  2.15k|                }
  137|  8.37k|                break;
  138|  11.9k|            }
  139|  11.9k|        }
  140|  4.69k|    }
_ZN3uWS16ExtensionsParser8getTokenERPKcS2_:
   69|  25.9k|    int getToken(const char *&in, const char *stop) {
   70|  52.0k|        while (in != stop && !isalnum(*in)) {
  ------------------
  |  Branch (70:16): [True: 47.6k, False: 4.37k]
  |  Branch (70:30): [True: 26.0k, False: 21.5k]
  ------------------
   71|  26.0k|            in++;
   72|  26.0k|        }
   73|       |
   74|       |        /* Don't care more than this for now */
   75|  25.9k|        static_assert(SHRT_MIN > INT_MIN, "Integer overflow fix is invalid for this platform, report this as a bug!");
   76|       |
   77|  25.9k|        int hashedToken = 0;
   78|   205k|        while (in != stop && (isalnum(*in) || *in == '-' || *in == '_')) {
  ------------------
  |  Branch (78:16): [True: 197k, False: 7.78k]
  |  Branch (78:31): [True: 170k, False: 27.5k]
  |  Branch (78:47): [True: 7.98k, False: 19.5k]
  |  Branch (78:61): [True: 1.41k, False: 18.1k]
  ------------------
   79|   179k|            if (isdigit(*in)) {
  ------------------
  |  Branch (79:17): [True: 17.6k, False: 161k]
  ------------------
   80|       |                /* This check is a quick and incorrect fix for integer overflow
   81|       |                 * in oss-fuzz but we don't care as it doesn't matter either way */
   82|  17.6k|                if (hashedToken > SHRT_MIN && hashedToken < SHRT_MAX) {
  ------------------
  |  Branch (82:21): [True: 17.0k, False: 529]
  |  Branch (82:47): [True: 16.5k, False: 504]
  ------------------
   83|  16.5k|                    hashedToken = hashedToken * 10 - (*in - '0');
   84|  16.5k|                }
   85|   161k|            } else {
   86|   161k|                hashedToken += *in;
   87|   161k|            }
   88|   179k|            in++;
   89|   179k|        }
   90|  25.9k|        return hashedToken;
   91|  25.9k|    }

_ZN3uWS18WebSocketHandshake8generateEPKcPc:
  116|  40.1k|    static inline void generate(const char input[24], char output[28]) {
  117|  40.1k|        uint32_t b_output[5] = {
  118|  40.1k|            0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0
  119|  40.1k|        };
  120|  40.1k|        uint32_t b_input[16] = {
  121|  40.1k|            0, 0, 0, 0, 0, 0, 0x32353845, 0x41464135, 0x2d453931, 0x342d3437, 0x44412d39,
  122|  40.1k|            0x3543412d, 0x43354142, 0x30444338, 0x35423131, 0x80000000
  123|  40.1k|        };
  124|       |
  125|   281k|        for (int i = 0; i < 6; i++) {
  ------------------
  |  Branch (125:25): [True: 240k, False: 40.1k]
  ------------------
  126|   240k|            b_input[i] = (uint32_t) ((input[4 * i + 3] & 0xff) | (input[4 * i + 2] & 0xff) << 8 | (input[4 * i + 1] & 0xff) << 16 | (input[4 * i + 0] & 0xff) << 24);
  127|   240k|        }
  128|  40.1k|        sha1(b_output, b_input);
  129|  40.1k|        uint32_t last_b[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 480};
  130|  40.1k|        sha1(b_output, last_b);
  131|   240k|        for (int i = 0; i < 5; i++) {
  ------------------
  |  Branch (131:25): [True: 200k, False: 40.1k]
  ------------------
  132|   200k|            uint32_t tmp = b_output[i];
  133|   200k|            char *bytes = (char *) &b_output[i];
  134|   200k|            bytes[3] = (char) (tmp & 0xff);
  135|   200k|            bytes[2] = (char) ((tmp >> 8) & 0xff);
  136|   200k|            bytes[1] = (char) ((tmp >> 16) & 0xff);
  137|   200k|            bytes[0] = (char) ((tmp >> 24) & 0xff);
  138|   200k|        }
  139|  40.1k|        base64((unsigned char *) b_output, output);
  140|  40.1k|    }
_ZN3uWS18WebSocketHandshake4sha1EPjS1_:
   91|  80.3k|    static inline void sha1(uint32_t hash[5], uint32_t b[16]) {
   92|  80.3k|        uint32_t a[5] = {hash[4], hash[3], hash[2], hash[1], hash[0]};
   93|  80.3k|        static_for<16, Sha1Loop1>()(a, b);
   94|  80.3k|        static_for<4, Sha1Loop2>()(a, b);
   95|  80.3k|        static_for<20, Sha1Loop3>()(a, b);
   96|  80.3k|        static_for<20, Sha1Loop4>()(a, b);
   97|  80.3k|        static_for<20, Sha1Loop5>()(a, b);
   98|  80.3k|        static_for<5, Sha1Loop6>()(a, hash);
   99|  80.3k|    }
_ZN3uWS18WebSocketHandshake10static_forILi16ENS0_9Sha1Loop1EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi15ENS0_9Sha1Loop1EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi14ENS0_9Sha1Loop1EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi13ENS0_9Sha1Loop1EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi12ENS0_9Sha1Loop1EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi11ENS0_9Sha1Loop1EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi10ENS0_9Sha1Loop1EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi9ENS0_9Sha1Loop1EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi8ENS0_9Sha1Loop1EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi7ENS0_9Sha1Loop1EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi6ENS0_9Sha1Loop1EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi5ENS0_9Sha1Loop1EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi4ENS0_9Sha1Loop1EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi3ENS0_9Sha1Loop1EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi2ENS0_9Sha1Loop1EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi1ENS0_9Sha1Loop1EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi0ENS0_9Sha1Loop1EEclEPjS4_:
   37|  80.3k|        void operator()(uint32_t */*a*/, uint32_t */*hash*/) {}
_ZN3uWS18WebSocketHandshake9Sha1Loop11fILi0EEEvPjS3_:
   47|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   48|  80.3k|            a[i % 5] += ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5);
   49|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   50|  80.3k|        }
_ZN3uWS18WebSocketHandshake3rolEjm:
   40|  17.9M|    static inline uint32_t rol(uint32_t value, size_t bits) {return (value << bits) | (value >> (32 - bits));}
_ZN3uWS18WebSocketHandshake9Sha1Loop11fILi1EEEvPjS3_:
   47|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   48|  80.3k|            a[i % 5] += ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5);
   49|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   50|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop11fILi2EEEvPjS3_:
   47|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   48|  80.3k|            a[i % 5] += ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5);
   49|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   50|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop11fILi3EEEvPjS3_:
   47|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   48|  80.3k|            a[i % 5] += ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5);
   49|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   50|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop11fILi4EEEvPjS3_:
   47|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   48|  80.3k|            a[i % 5] += ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5);
   49|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   50|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop11fILi5EEEvPjS3_:
   47|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   48|  80.3k|            a[i % 5] += ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5);
   49|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   50|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop11fILi6EEEvPjS3_:
   47|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   48|  80.3k|            a[i % 5] += ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5);
   49|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   50|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop11fILi7EEEvPjS3_:
   47|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   48|  80.3k|            a[i % 5] += ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5);
   49|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   50|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop11fILi8EEEvPjS3_:
   47|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   48|  80.3k|            a[i % 5] += ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5);
   49|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   50|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop11fILi9EEEvPjS3_:
   47|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   48|  80.3k|            a[i % 5] += ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5);
   49|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   50|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop11fILi10EEEvPjS3_:
   47|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   48|  80.3k|            a[i % 5] += ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5);
   49|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   50|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop11fILi11EEEvPjS3_:
   47|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   48|  80.3k|            a[i % 5] += ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5);
   49|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   50|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop11fILi12EEEvPjS3_:
   47|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   48|  80.3k|            a[i % 5] += ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5);
   49|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   50|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop11fILi13EEEvPjS3_:
   47|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   48|  80.3k|            a[i % 5] += ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5);
   49|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   50|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop11fILi14EEEvPjS3_:
   47|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   48|  80.3k|            a[i % 5] += ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5);
   49|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   50|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop11fILi15EEEvPjS3_:
   47|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   48|  80.3k|            a[i % 5] += ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5);
   49|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   50|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi4ENS0_9Sha1Loop2EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi3ENS0_9Sha1Loop2EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi2ENS0_9Sha1Loop2EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi1ENS0_9Sha1Loop2EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi0ENS0_9Sha1Loop2EEclEPjS4_:
   37|  80.3k|        void operator()(uint32_t */*a*/, uint32_t */*hash*/) {}
_ZN3uWS18WebSocketHandshake9Sha1Loop21fILi0EEEvPjS3_:
   54|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   55|  80.3k|            b[i] = blk(b, i);
   56|  80.3k|            a[(1 + i) % 5] += ((a[(4 + i) % 5] & (a[(3 + i) % 5] ^ a[(2 + i) % 5])) ^ a[(2 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(5 + i) % 5], 5);
   57|  80.3k|            a[(4 + i) % 5] = rol(a[(4 + i) % 5], 30);
   58|  80.3k|        }
_ZN3uWS18WebSocketHandshake3blkEPjm:
   41|  5.13M|    static inline uint32_t blk(uint32_t b[16], size_t i) {
   42|  5.13M|        return rol(b[(i + 13) & 15] ^ b[(i + 8) & 15] ^ b[(i + 2) & 15] ^ b[i], 1);
   43|  5.13M|    }
_ZN3uWS18WebSocketHandshake9Sha1Loop21fILi1EEEvPjS3_:
   54|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   55|  80.3k|            b[i] = blk(b, i);
   56|  80.3k|            a[(1 + i) % 5] += ((a[(4 + i) % 5] & (a[(3 + i) % 5] ^ a[(2 + i) % 5])) ^ a[(2 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(5 + i) % 5], 5);
   57|  80.3k|            a[(4 + i) % 5] = rol(a[(4 + i) % 5], 30);
   58|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop21fILi2EEEvPjS3_:
   54|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   55|  80.3k|            b[i] = blk(b, i);
   56|  80.3k|            a[(1 + i) % 5] += ((a[(4 + i) % 5] & (a[(3 + i) % 5] ^ a[(2 + i) % 5])) ^ a[(2 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(5 + i) % 5], 5);
   57|  80.3k|            a[(4 + i) % 5] = rol(a[(4 + i) % 5], 30);
   58|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop21fILi3EEEvPjS3_:
   54|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   55|  80.3k|            b[i] = blk(b, i);
   56|  80.3k|            a[(1 + i) % 5] += ((a[(4 + i) % 5] & (a[(3 + i) % 5] ^ a[(2 + i) % 5])) ^ a[(2 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(5 + i) % 5], 5);
   57|  80.3k|            a[(4 + i) % 5] = rol(a[(4 + i) % 5], 30);
   58|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi20ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi19ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi18ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi17ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi16ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi15ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi14ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi13ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi12ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi11ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi10ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi9ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi8ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi7ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi6ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi5ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi4ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi3ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi2ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi1ENS0_9Sha1Loop3EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi0ENS0_9Sha1Loop3EEclEPjS4_:
   37|  80.3k|        void operator()(uint32_t */*a*/, uint32_t */*hash*/) {}
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi0EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi1EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi2EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi3EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi4EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi5EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi6EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi7EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi8EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi9EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi10EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi11EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi12EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi13EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi14EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi15EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi16EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi17EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi18EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop31fILi19EEEvPjS3_:
   62|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   63|  80.3k|            b[(i + 4) % 16] = blk(b, (i + 4) % 16);
   64|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
   65|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   66|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi20ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi19ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi18ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi17ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi16ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi15ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi14ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi13ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi12ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi11ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi10ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi9ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi8ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi7ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi6ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi5ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi4ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi3ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi2ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi1ENS0_9Sha1Loop4EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi0ENS0_9Sha1Loop4EEclEPjS4_:
   37|  80.3k|        void operator()(uint32_t */*a*/, uint32_t */*hash*/) {}
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi0EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi1EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi2EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi3EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi4EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi5EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi6EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi7EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi8EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi9EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi10EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi11EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi12EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi13EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi14EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi15EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi16EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi17EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi18EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop41fILi19EEEvPjS3_:
   70|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   71|  80.3k|            b[(i + 8) % 16] = blk(b, (i + 8) % 16);
   72|  80.3k|            a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
   73|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   74|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi20ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi19ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi18ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi17ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi16ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi15ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi14ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi13ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi12ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi11ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi10ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi9ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi8ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi7ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi6ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi5ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi4ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi3ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi2ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi1ENS0_9Sha1Loop5EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi0ENS0_9Sha1Loop5EEclEPjS4_:
   37|  80.3k|        void operator()(uint32_t */*a*/, uint32_t */*hash*/) {}
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi0EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi1EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi2EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi3EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi4EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi5EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi6EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi7EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi8EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi9EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi10EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi11EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi12EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi13EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi14EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi15EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi16EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi17EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi18EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop51fILi19EEEvPjS3_:
   78|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   79|  80.3k|            b[(i + 12) % 16] = blk(b, (i + 12) % 16);
   80|  80.3k|            a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
   81|  80.3k|            a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
   82|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi5ENS0_9Sha1Loop6EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi4ENS0_9Sha1Loop6EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi3ENS0_9Sha1Loop6EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi2ENS0_9Sha1Loop6EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi1ENS0_9Sha1Loop6EEclEPjS4_:
   29|  80.3k|        void operator()(uint32_t *a, uint32_t *b) {
   30|  80.3k|            static_for<N - 1, T>()(a, b);
   31|  80.3k|            T::template f<N - 1>(a, b);
   32|  80.3k|        }
_ZN3uWS18WebSocketHandshake10static_forILi0ENS0_9Sha1Loop6EEclEPjS4_:
   37|  80.3k|        void operator()(uint32_t */*a*/, uint32_t */*hash*/) {}
_ZN3uWS18WebSocketHandshake9Sha1Loop61fILi0EEEvPjS3_:
   86|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   87|  80.3k|            b[i] += a[4 - i];
   88|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop61fILi1EEEvPjS3_:
   86|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   87|  80.3k|            b[i] += a[4 - i];
   88|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop61fILi2EEEvPjS3_:
   86|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   87|  80.3k|            b[i] += a[4 - i];
   88|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop61fILi3EEEvPjS3_:
   86|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   87|  80.3k|            b[i] += a[4 - i];
   88|  80.3k|        }
_ZN3uWS18WebSocketHandshake9Sha1Loop61fILi4EEEvPjS3_:
   86|  80.3k|        static inline void f(uint32_t *a, uint32_t *b) {
   87|  80.3k|            b[i] += a[4 - i];
   88|  80.3k|        }
_ZN3uWS18WebSocketHandshake6base64EPhPc:
  101|  40.1k|    static inline void base64(unsigned char *src, char *dst) {
  102|  40.1k|        const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  103|   281k|        for (int i = 0; i < 18; i += 3) {
  ------------------
  |  Branch (103:25): [True: 240k, False: 40.1k]
  ------------------
  104|   240k|            *dst++ = b64[(src[i] >> 2) & 63];
  105|   240k|            *dst++ = b64[((src[i] & 3) << 4) | ((src[i + 1] & 240) >> 4)];
  106|   240k|            *dst++ = b64[((src[i + 1] & 15) << 2) | ((src[i + 2] & 192) >> 6)];
  107|   240k|            *dst++ = b64[src[i + 2] & 63];
  108|   240k|        }
  109|  40.1k|        *dst++ = b64[(src[18] >> 2) & 63];
  110|  40.1k|        *dst++ = b64[((src[18] & 3) << 4) | ((src[19] & 240) >> 4)];
  111|  40.1k|        *dst++ = b64[((src[19] & 15) << 2)];
  112|  40.1k|        *dst++ = '=';
  113|  40.1k|    }

EpollHelloWorld.cpp:_ZN3uWS8protocolL13formatMessageILb1EEEmPcPKcmNS_6OpCodeEmbb:
  209|  22.7k|static inline size_t formatMessage(char *dst, const char *src, size_t length, OpCode opCode, size_t reportedLength, bool compressed, bool fin) {
  210|  22.7k|    size_t messageLength;
  211|  22.7k|    size_t headerLength;
  212|  22.7k|    if (reportedLength < 126) {
  ------------------
  |  Branch (212:9): [True: 22.0k, False: 719]
  ------------------
  213|  22.0k|        headerLength = 2;
  214|  22.0k|        dst[1] = (char) reportedLength;
  215|  22.0k|    } else if (reportedLength <= UINT16_MAX) {
  ------------------
  |  Branch (215:16): [True: 719, False: 0]
  ------------------
  216|    719|        headerLength = 4;
  217|    719|        dst[1] = 126;
  218|    719|        uint16_t tmp = cond_byte_swap<uint16_t>((uint16_t) reportedLength);
  219|    719|        memcpy(&dst[2], &tmp, sizeof(uint16_t));
  220|    719|    } else {
  221|      0|        headerLength = 10;
  222|      0|        dst[1] = 127;
  223|      0|        uint64_t tmp = cond_byte_swap<uint64_t>((uint64_t) reportedLength);
  224|      0|        memcpy(&dst[2], &tmp, sizeof(uint64_t));
  225|      0|    }
  226|       |
  227|  22.7k|    dst[0] = (char) ((fin ? 128 : 0) | ((compressed && opCode) ? SND_COMPRESSED : 0) | (char) opCode);
  ------------------
  |  Branch (227:23): [True: 22.7k, False: 0]
  |  Branch (227:42): [True: 2.84k, False: 19.9k]
  |  Branch (227:56): [True: 2.84k, False: 0]
  ------------------
  228|       |
  229|       |    //printf("%d\n", (int)dst[0]);
  230|       |
  231|  22.7k|    char mask[4];
  232|  22.7k|    if (!isServer) {
  ------------------
  |  Branch (232:9): [Folded - Ignored]
  ------------------
  233|      0|        dst[1] |= 0x80;
  234|      0|        uint32_t random = (uint32_t) rand();
  235|      0|        memcpy(mask, &random, 4);
  236|      0|        memcpy(dst + headerLength, &random, 4);
  237|      0|        headerLength += 4;
  238|      0|    }
  239|       |
  240|  22.7k|    messageLength = headerLength + length;
  241|  22.7k|    memcpy(dst + headerLength, src, length);
  242|       |
  243|  22.7k|    if (!isServer) {
  ------------------
  |  Branch (243:9): [Folded - Ignored]
  ------------------
  244|       |
  245|       |        // overwrites up to 3 bytes outside of the given buffer!
  246|       |        //WebSocketProtocol<isServer>::unmaskInplace(dst + headerLength, dst + headerLength + length, mask);
  247|       |
  248|       |        // this is not optimal
  249|      0|        char *start = dst + headerLength;
  250|      0|        char *stop = start + length;
  251|      0|        int i = 0;
  252|      0|        while (start != stop) {
  ------------------
  |  Branch (252:16): [True: 0, False: 0]
  ------------------
  253|      0|            (*start++) ^= mask[i++ % 4];
  254|      0|        }
  255|      0|    }
  256|  22.7k|    return messageLength;
  257|  22.7k|}
_ZN3uWS8protocol14cond_byte_swapItEET_S2_:
   95|  13.1k|T cond_byte_swap(T value) {
   96|  13.1k|    uint32_t endian_test = 1;
   97|  13.1k|    if (*((char *)&endian_test)) {
  ------------------
  |  Branch (97:9): [True: 13.1k, False: 0]
  ------------------
   98|  13.1k|        union {
   99|  13.1k|            T i;
  100|  13.1k|            uint8_t b[sizeof(T)];
  101|  13.1k|        } src = { value }, dst;
  102|       |
  103|  39.3k|        for (unsigned int i = 0; i < sizeof(value); i++) {
  ------------------
  |  Branch (103:34): [True: 26.2k, False: 13.1k]
  ------------------
  104|  26.2k|            dst.b[i] = src.b[sizeof(value) - 1 - i];
  105|  26.2k|        }
  106|       |
  107|  13.1k|        return dst.i;
  108|  13.1k|    }
  109|      0|    return value;
  110|  13.1k|}
_ZN3uWS8protocol14cond_byte_swapImEET_S2_:
   95|  3.63k|T cond_byte_swap(T value) {
   96|  3.63k|    uint32_t endian_test = 1;
   97|  3.63k|    if (*((char *)&endian_test)) {
  ------------------
  |  Branch (97:9): [True: 3.63k, False: 0]
  ------------------
   98|  3.63k|        union {
   99|  3.63k|            T i;
  100|  3.63k|            uint8_t b[sizeof(T)];
  101|  3.63k|        } src = { value }, dst;
  102|       |
  103|  32.6k|        for (unsigned int i = 0; i < sizeof(value); i++) {
  ------------------
  |  Branch (103:34): [True: 29.0k, False: 3.63k]
  ------------------
  104|  29.0k|            dst.b[i] = src.b[sizeof(value) - 1 - i];
  105|  29.0k|        }
  106|       |
  107|  3.63k|        return dst.i;
  108|  3.63k|    }
  109|      0|    return value;
  110|  3.63k|}
EpollHelloWorld.cpp:_ZN3uWS8protocolL16messageFrameSizeEm:
  193|  22.7k|static inline size_t messageFrameSize(size_t messageSize) {
  194|  22.7k|    if (messageSize < 126) {
  ------------------
  |  Branch (194:9): [True: 22.0k, False: 719]
  ------------------
  195|  22.0k|        return 2 + messageSize;
  196|  22.0k|    } else if (messageSize <= UINT16_MAX) {
  ------------------
  |  Branch (196:16): [True: 719, False: 0]
  ------------------
  197|    719|        return 4 + messageSize;
  198|    719|    }
  199|      0|    return 10 + messageSize;
  200|  22.7k|}
EpollHelloWorld.cpp:_ZN3uWS17WebSocketProtocolILb1ENS_16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataEEE7consumeEPcjPNS_14WebSocketStateILb1EEEPv:
  458|  58.6k|    static inline void consume(char *src, unsigned int length, WebSocketState<isServer> *wState, void *user) {
  459|  58.6k|        if (wState->state.spillLength) {
  ------------------
  |  Branch (459:13): [True: 2.50k, False: 56.1k]
  ------------------
  460|  2.50k|            src -= wState->state.spillLength;
  461|  2.50k|            length += wState->state.spillLength;
  462|  2.50k|            memcpy(src, wState->state.spill, wState->state.spillLength);
  463|  2.50k|        }
  464|  58.6k|        if (wState->state.wantsHead) {
  ------------------
  |  Branch (464:13): [True: 21.9k, False: 36.7k]
  ------------------
  465|  25.6k|            parseNext:
  466|  55.7k|            while (length >= SHORT_MESSAGE_HEADER) {
  ------------------
  |  Branch (466:20): [True: 52.3k, False: 3.34k]
  ------------------
  467|       |
  468|       |                // invalid reserved bits / invalid opcodes / invalid control frames / set compressed frame
  469|  52.3k|                if ((rsv1(src) && !Impl::setCompressed(wState, user)) || rsv23(src) || (getOpCode(src) > 2 && getOpCode(src) < 8) ||
  ------------------
  |  Branch (469:22): [True: 2.60k, False: 49.7k]
  |  Branch (469:35): [True: 1.06k, False: 1.53k]
  |  Branch (469:74): [True: 1.80k, False: 49.4k]
  |  Branch (469:89): [True: 15.9k, False: 33.5k]
  |  Branch (469:111): [True: 236, False: 15.7k]
  ------------------
  470|  52.3k|                    getOpCode(src) > 10 || (getOpCode(src) > 2 && (!isFin(src) || payloadLength(src) > 125))) {
  ------------------
  |  Branch (470:21): [True: 333, False: 48.9k]
  |  Branch (470:45): [True: 15.3k, False: 33.5k]
  |  Branch (470:68): [True: 244, False: 15.1k]
  |  Branch (470:83): [True: 325, False: 14.8k]
  ------------------
  471|  4.00k|                    Impl::forceClose(wState, user);
  472|  4.00k|                    return;
  473|  4.00k|                }
  474|       |
  475|  48.3k|                if (payloadLength(src) < 126) {
  ------------------
  |  Branch (475:21): [True: 38.1k, False: 10.1k]
  ------------------
  476|  38.1k|                    if (consumeMessage<SHORT_MESSAGE_HEADER, uint8_t>(payloadLength(src), src, length, wState, user)) {
  ------------------
  |  Branch (476:25): [True: 12.3k, False: 25.8k]
  ------------------
  477|  12.3k|                        return;
  478|  12.3k|                    }
  479|  38.1k|                } else if (payloadLength(src) == 126) {
  ------------------
  |  Branch (479:28): [True: 6.27k, False: 3.91k]
  ------------------
  480|  6.27k|                    if (length < MEDIUM_MESSAGE_HEADER) {
  ------------------
  |  Branch (480:25): [True: 239, False: 6.03k]
  ------------------
  481|    239|                        break;
  482|  6.03k|                    } else if(consumeMessage<MEDIUM_MESSAGE_HEADER, uint16_t>(protocol::cond_byte_swap<uint16_t>(protocol::bit_cast<uint16_t>(src + 2)), src, length, wState, user)) {
  ------------------
  |  Branch (482:31): [True: 2.98k, False: 3.05k]
  ------------------
  483|  2.98k|                        return;
  484|  2.98k|                    }
  485|  6.27k|                } else if (length < LONG_MESSAGE_HEADER) {
  ------------------
  |  Branch (485:28): [True: 289, False: 3.63k]
  ------------------
  486|    289|                    break;
  487|  3.63k|                } else if (consumeMessage<LONG_MESSAGE_HEADER, uint64_t>(protocol::cond_byte_swap<uint64_t>(protocol::bit_cast<uint64_t>(src + 2)), src, length, wState, user)) {
  ------------------
  |  Branch (487:28): [True: 2.42k, False: 1.20k]
  ------------------
  488|  2.42k|                    return;
  489|  2.42k|                }
  490|  48.3k|            }
  491|  3.87k|            if (length) {
  ------------------
  |  Branch (491:17): [True: 2.94k, False: 927]
  ------------------
  492|  2.94k|                memcpy(wState->state.spill, src, length);
  493|  2.94k|                wState->state.spillLength = length & 0xf;
  494|  2.94k|            }
  495|  36.7k|        } else if (consumeContinuation(src, length, wState, user)) {
  ------------------
  |  Branch (495:20): [True: 3.67k, False: 33.0k]
  ------------------
  496|  3.67k|            goto parseNext;
  497|  3.67k|        }
  498|  58.6k|    }
EpollHelloWorld.cpp:_ZN3uWS17WebSocketProtocolILb1ENS_16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataEEE4rsv1EPc:
  274|  52.3k|    static inline bool rsv1(char *frame) {return *((unsigned char *) frame) & 64;}
EpollHelloWorld.cpp:_ZN3uWS17WebSocketProtocolILb1ENS_16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataEEE5rsv23EPc:
  273|  51.2k|    static inline bool rsv23(char *frame) {return *((unsigned char *) frame) & 48;}
EpollHelloWorld.cpp:_ZN3uWS17WebSocketProtocolILb1ENS_16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataEEE9getOpCodeEPc:
  271|   253k|    static inline unsigned char getOpCode(char *frame) {return *((unsigned char *) frame) & 15;}
EpollHelloWorld.cpp:_ZN3uWS17WebSocketProtocolILb1ENS_16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataEEE5isFinEPc:
  270|   106k|    static inline bool isFin(char *frame) {return *((unsigned char *) frame) & 128;}
EpollHelloWorld.cpp:_ZN3uWS17WebSocketProtocolILb1ENS_16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataEEE13payloadLengthEPc:
  272|   111k|    static inline unsigned char payloadLength(char *frame) {return ((unsigned char *) frame)[1] & 127;}
EpollHelloWorld.cpp:_ZN3uWS17WebSocketProtocolILb1ENS_16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataEEE14consumeMessageILj6EhEEbT0_RPcRjPNS_14WebSocketStateILb1EEEPv:
  340|  38.1k|    static inline bool consumeMessage(T payLength, char *&src, unsigned int &length, WebSocketState<isServer> *wState, void *user) {
  341|  38.1k|        if (getOpCode(src)) {
  ------------------
  |  Branch (341:13): [True: 30.4k, False: 7.68k]
  ------------------
  342|  30.4k|            if (wState->state.opStack == 1 || (!wState->state.lastFin && getOpCode(src) < 2)) {
  ------------------
  |  Branch (342:17): [True: 197, False: 30.2k]
  |  Branch (342:48): [True: 2.98k, False: 27.3k]
  |  Branch (342:74): [True: 234, False: 2.75k]
  ------------------
  343|    431|                Impl::forceClose(wState, user);
  344|    431|                return true;
  345|    431|            }
  346|  30.0k|            wState->state.opCode[++wState->state.opStack] = (OpCode) getOpCode(src);
  347|  30.0k|        } else if (wState->state.opStack == -1) {
  ------------------
  |  Branch (347:20): [True: 355, False: 7.33k]
  ------------------
  348|    355|            Impl::forceClose(wState, user);
  349|    355|            return true;
  350|    355|        }
  351|  37.3k|        wState->state.lastFin = isFin(src);
  352|       |
  353|  37.3k|        if (Impl::refusePayloadLength(payLength, wState, user)) {
  ------------------
  |  Branch (353:13): [True: 0, False: 37.3k]
  ------------------
  354|      0|            Impl::forceClose(wState, user, ERR_TOO_BIG_MESSAGE);
  355|      0|            return true;
  356|      0|        }
  357|       |
  358|  37.3k|        if (payLength + MESSAGE_HEADER <= length) {
  ------------------
  |  Branch (358:13): [True: 31.9k, False: 5.38k]
  ------------------
  359|  31.9k|            bool fin = isFin(src);
  360|  31.9k|            if (isServer) {
  ------------------
  |  Branch (360:17): [Folded - Ignored]
  ------------------
  361|       |                /* This guy can never be assumed to be perfectly aligned since we can get multiple messages in one read */
  362|  31.9k|                unmaskImpreciseCopyMask<MESSAGE_HEADER>(src + MESSAGE_HEADER, (unsigned int) payLength);
  363|  31.9k|                if (Impl::handleFragment(src, payLength, 0, wState->state.opCode[wState->state.opStack], fin, wState, user)) {
  ------------------
  |  Branch (363:21): [True: 6.17k, False: 25.8k]
  ------------------
  364|  6.17k|                    return true;
  365|  6.17k|                }
  366|  31.9k|            } else {
  367|      0|                if (Impl::handleFragment(src + MESSAGE_HEADER, payLength, 0, wState->state.opCode[wState->state.opStack], isFin(src), wState, user)) {
  ------------------
  |  Branch (367:21): [True: 0, False: 0]
  ------------------
  368|      0|                    return true;
  369|      0|                }
  370|      0|            }
  371|       |
  372|  25.8k|            if (fin) {
  ------------------
  |  Branch (372:17): [True: 15.4k, False: 10.3k]
  ------------------
  373|  15.4k|                wState->state.opStack--;
  374|  15.4k|            }
  375|       |
  376|  25.8k|            src += payLength + MESSAGE_HEADER;
  377|  25.8k|            length -= (unsigned int) (payLength + MESSAGE_HEADER);
  378|  25.8k|            wState->state.spillLength = 0;
  379|  25.8k|            return false;
  380|  31.9k|        } else {
  381|  5.38k|            wState->state.spillLength = 0;
  382|  5.38k|            wState->state.wantsHead = false;
  383|  5.38k|            wState->remainingBytes = (unsigned int) (payLength - length + MESSAGE_HEADER);
  384|  5.38k|            bool fin = isFin(src);
  385|  5.38k|            if constexpr (isServer) {
  ------------------
  |  Branch (385:27): [Folded - Ignored]
  ------------------
  386|  5.38k|                memcpy(wState->mask, src + MESSAGE_HEADER - 4, 4);
  387|  5.38k|                uint64_t mask;
  388|  5.38k|                memcpy(&mask, src + MESSAGE_HEADER - 4, 4);
  389|  5.38k|                memcpy(((char *)&mask) + 4, src + MESSAGE_HEADER - 4, 4);
  390|  5.38k|                unmaskImprecise8<0>(src + MESSAGE_HEADER, mask, length);
  391|  5.38k|                rotateMask(4 - (length - MESSAGE_HEADER) % 4, wState->mask);
  392|  5.38k|            }
  393|  5.38k|            Impl::handleFragment(src + MESSAGE_HEADER, length - MESSAGE_HEADER, wState->remainingBytes, wState->state.opCode[wState->state.opStack], fin, wState, user);
  394|  5.38k|            return true;
  395|  5.38k|        }
  396|  37.3k|    }
EpollHelloWorld.cpp:_ZN3uWS17WebSocketProtocolILb1ENS_16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataEEE23unmaskImpreciseCopyMaskILi6EEEvPcj:
  308|  31.9k|    static inline void unmaskImpreciseCopyMask(char *src, unsigned int length) {
  309|  31.9k|        if constexpr (HEADER_SIZE != 6) {
  ------------------
  |  Branch (309:23): [Folded - Ignored]
  ------------------
  310|  31.9k|            char mask[8] = {src[-4], src[-3], src[-2], src[-1], src[-4], src[-3], src[-2], src[-1]};
  311|  31.9k|            uint64_t maskInt;
  312|  31.9k|            memcpy(&maskInt, mask, 8);
  313|  31.9k|            unmaskImprecise8<HEADER_SIZE>(src, maskInt, length);
  314|  31.9k|        } else {
  315|  31.9k|            char mask[4] = {src[-4], src[-3], src[-2], src[-1]};
  316|  31.9k|            uint32_t maskInt;
  317|  31.9k|            memcpy(&maskInt, mask, 4);
  318|  31.9k|            unmaskImprecise4<HEADER_SIZE>(src, maskInt, length);
  319|  31.9k|        }
  320|  31.9k|    }
EpollHelloWorld.cpp:_ZN3uWS17WebSocketProtocolILb1ENS_16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataEEE16unmaskImprecise4ILi6EEEvPcjj:
  297|  31.9k|    static inline void unmaskImprecise4(char *src, uint32_t mask, unsigned int length) {
  298|   103k|        for (unsigned int n = (length >> 2) + 1; n; n--) {
  ------------------
  |  Branch (298:50): [True: 71.0k, False: 31.9k]
  ------------------
  299|  71.0k|            uint32_t loaded;
  300|  71.0k|            memcpy(&loaded, src, 4);
  301|  71.0k|            loaded ^= mask;
  302|  71.0k|            memcpy(src - DESTINATION, &loaded, 4);
  303|  71.0k|            src += 4;
  304|  71.0k|        }
  305|  31.9k|    }
EpollHelloWorld.cpp:_ZN3uWS8protocolL11isValidUtf8EPhm:
  117|  12.4k|{
  118|  40.4k|    for (unsigned char *e = s + length; s != e; ) {
  ------------------
  |  Branch (118:41): [True: 39.6k, False: 808]
  ------------------
  119|  39.6k|        if (s + 4 <= e) {
  ------------------
  |  Branch (119:13): [True: 30.3k, False: 9.23k]
  ------------------
  120|  30.3k|            uint32_t tmp;
  121|  30.3k|            memcpy(&tmp, s, 4);
  122|  30.3k|            if ((tmp & 0x80808080) == 0) {
  ------------------
  |  Branch (122:17): [True: 25.7k, False: 4.58k]
  ------------------
  123|  25.7k|                s += 4;
  124|  25.7k|                continue;
  125|  25.7k|            }
  126|  30.3k|        }
  127|       |
  128|  18.4k|        while (!(*s & 0x80)) {
  ------------------
  |  Branch (128:16): [True: 11.9k, False: 6.56k]
  ------------------
  129|  11.9k|            if (++s == e) {
  ------------------
  |  Branch (129:17): [True: 7.24k, False: 4.65k]
  ------------------
  130|  7.24k|                return true;
  131|  7.24k|            }
  132|  11.9k|        }
  133|       |
  134|  6.56k|        if ((s[0] & 0x60) == 0x40) {
  ------------------
  |  Branch (134:13): [True: 1.64k, False: 4.92k]
  ------------------
  135|  1.64k|            if (s + 1 >= e || (s[1] & 0xc0) != 0x80 || (s[0] & 0xfe) == 0xc0) {
  ------------------
  |  Branch (135:17): [True: 222, False: 1.42k]
  |  Branch (135:31): [True: 401, False: 1.02k]
  |  Branch (135:56): [True: 195, False: 831]
  ------------------
  136|    818|                return false;
  137|    818|            }
  138|    831|            s += 2;
  139|  4.92k|        } else if ((s[0] & 0xf0) == 0xe0) {
  ------------------
  |  Branch (139:20): [True: 2.21k, False: 2.70k]
  ------------------
  140|  2.21k|            if (s + 2 >= e || (s[1] & 0xc0) != 0x80 || (s[2] & 0xc0) != 0x80 ||
  ------------------
  |  Branch (140:17): [True: 211, False: 2.00k]
  |  Branch (140:31): [True: 641, False: 1.36k]
  |  Branch (140:56): [True: 249, False: 1.11k]
  ------------------
  141|  2.21k|                    (s[0] == 0xe0 && (s[1] & 0xe0) == 0x80) || (s[0] == 0xed && (s[1] & 0xe0) == 0xa0)) {
  ------------------
  |  Branch (141:22): [True: 442, False: 671]
  |  Branch (141:38): [True: 237, False: 205]
  |  Branch (141:65): [True: 396, False: 480]
  |  Branch (141:81): [True: 194, False: 202]
  ------------------
  142|  1.53k|                return false;
  143|  1.53k|            }
  144|    682|            s += 3;
  145|  2.70k|        } else if ((s[0] & 0xf8) == 0xf0) {
  ------------------
  |  Branch (145:20): [True: 2.16k, False: 542]
  ------------------
  146|  2.16k|            if (s + 3 >= e || (s[1] & 0xc0) != 0x80 || (s[2] & 0xc0) != 0x80 || (s[3] & 0xc0) != 0x80 ||
  ------------------
  |  Branch (146:17): [True: 277, False: 1.88k]
  |  Branch (146:31): [True: 207, False: 1.68k]
  |  Branch (146:56): [True: 242, False: 1.43k]
  |  Branch (146:81): [True: 224, False: 1.21k]
  ------------------
  147|  2.16k|                    (s[0] == 0xf0 && (s[1] & 0xf0) == 0x80) || (s[0] == 0xf4 && s[1] > 0x8f) || s[0] > 0xf4) {
  ------------------
  |  Branch (147:22): [True: 389, False: 825]
  |  Branch (147:38): [True: 194, False: 195]
  |  Branch (147:65): [True: 393, False: 627]
  |  Branch (147:81): [True: 196, False: 197]
  |  Branch (147:97): [True: 197, False: 627]
  ------------------
  148|  1.53k|                return false;
  149|  1.53k|            }
  150|    627|            s += 4;
  151|    627|        } else {
  152|    542|            return false;
  153|    542|        }
  154|  6.56k|    }
  155|    808|    return true;
  156|  12.4k|}
EpollHelloWorld.cpp:_ZN3uWS8protocolL17parseClosePayloadEPcm:
  164|  5.90k|static inline CloseFrame parseClosePayload(char *src, size_t length) {
  165|       |    /* If we get no code or message, default to reporting 1005 no status code present */
  166|  5.90k|    CloseFrame cf = {1005, nullptr, 0};
  167|  5.90k|    if (length >= 2) {
  ------------------
  |  Branch (167:9): [True: 5.36k, False: 542]
  ------------------
  168|  5.36k|        memcpy(&cf.code, src, 2);
  169|  5.36k|        cf = {cond_byte_swap<uint16_t>(cf.code), src + 2, length - 2};
  170|  5.36k|        if (cf.code < 1000 || cf.code > 4999 || (cf.code > 1011 && cf.code < 4000) ||
  ------------------
  |  Branch (170:13): [True: 558, False: 4.80k]
  |  Branch (170:31): [True: 1.48k, False: 3.32k]
  |  Branch (170:50): [True: 1.51k, False: 1.81k]
  |  Branch (170:68): [True: 418, False: 1.09k]
  ------------------
  171|  5.36k|            (cf.code >= 1004 && cf.code <= 1006) || !isValidUtf8((unsigned char *) cf.message, cf.length)) {
  ------------------
  |  Branch (171:14): [True: 1.95k, False: 946]
  |  Branch (171:33): [True: 390, False: 1.56k]
  |  Branch (171:53): [True: 1.50k, False: 1.00k]
  ------------------
  172|       |            /* Even though we got a WebSocket close frame, it in itself is abnormal */
  173|  4.35k|            return {1006, nullptr, 0};
  174|  4.35k|        }
  175|  5.36k|    }
  176|  1.54k|    return cf;
  177|  5.90k|}
EpollHelloWorld.cpp:_ZN3uWS8protocolL18formatClosePayloadEPctPKcm:
  179|  5.90k|static inline size_t formatClosePayload(char *dst, uint16_t code, const char *message, size_t length) {
  180|       |    /* We could have more strict checks here, but never append code 0 or 1005 or 1006 */
  181|  5.90k|    if (code && code != 1005 && code != 1006) {
  ------------------
  |  Branch (181:9): [True: 5.90k, False: 0]
  |  Branch (181:17): [True: 5.36k, False: 542]
  |  Branch (181:33): [True: 1.00k, False: 4.35k]
  ------------------
  182|  1.00k|        code = cond_byte_swap<uint16_t>(code);
  183|  1.00k|        memcpy(dst, &code, 2);
  184|       |        /* It is invalid to pass nullptr to memcpy, even though length is 0 */
  185|  1.00k|        if (message) {
  ------------------
  |  Branch (185:13): [True: 1.00k, False: 0]
  ------------------
  186|  1.00k|            memcpy(dst + 2, message, length);
  187|  1.00k|        }
  188|  1.00k|        return length + 2;
  189|  1.00k|    }
  190|  4.89k|    return 0;
  191|  5.90k|}
EpollHelloWorld.cpp:_ZN3uWS17WebSocketProtocolILb1ENS_16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataEEE16unmaskImprecise8ILi0EEEvPcmj:
  285|  8.08k|    static inline void unmaskImprecise8(char *src, uint64_t mask, unsigned int length) {
  286|  53.0k|        for (unsigned int n = (length >> 3) + 1; n; n--) {
  ------------------
  |  Branch (286:50): [True: 44.9k, False: 8.08k]
  ------------------
  287|  44.9k|            uint64_t loaded;
  288|  44.9k|            memcpy(&loaded, src, 8);
  289|  44.9k|            loaded ^= mask;
  290|  44.9k|            memcpy(src - DESTINATION, &loaded, 8);
  291|  44.9k|            src += 8;
  292|  44.9k|        }
  293|  8.08k|    }
EpollHelloWorld.cpp:_ZN3uWS17WebSocketProtocolILb1ENS_16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataEEE10rotateMaskEjPc:
  322|  38.7k|    static inline void rotateMask(unsigned int offset, char *mask) {
  323|  38.7k|        char originalMask[4] = {mask[0], mask[1], mask[2], mask[3]};
  324|  38.7k|        mask[(0 + offset) % 4] = originalMask[0];
  325|  38.7k|        mask[(1 + offset) % 4] = originalMask[1];
  326|  38.7k|        mask[(2 + offset) % 4] = originalMask[2];
  327|  38.7k|        mask[(3 + offset) % 4] = originalMask[3];
  328|  38.7k|    }
EpollHelloWorld.cpp:_ZN3uWS17WebSocketProtocolILb1ENS_16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataEEE14consumeMessageILj8EtEEbT0_RPcRjPNS_14WebSocketStateILb1EEEPv:
  340|  6.03k|    static inline bool consumeMessage(T payLength, char *&src, unsigned int &length, WebSocketState<isServer> *wState, void *user) {
  341|  6.03k|        if (getOpCode(src)) {
  ------------------
  |  Branch (341:13): [True: 4.90k, False: 1.12k]
  ------------------
  342|  4.90k|            if (wState->state.opStack == 1 || (!wState->state.lastFin && getOpCode(src) < 2)) {
  ------------------
  |  Branch (342:17): [True: 194, False: 4.71k]
  |  Branch (342:48): [True: 1.88k, False: 2.82k]
  |  Branch (342:74): [True: 195, False: 1.69k]
  ------------------
  343|    389|                Impl::forceClose(wState, user);
  344|    389|                return true;
  345|    389|            }
  346|  4.51k|            wState->state.opCode[++wState->state.opStack] = (OpCode) getOpCode(src);
  347|  4.51k|        } else if (wState->state.opStack == -1) {
  ------------------
  |  Branch (347:20): [True: 194, False: 931]
  ------------------
  348|    194|            Impl::forceClose(wState, user);
  349|    194|            return true;
  350|    194|        }
  351|  5.44k|        wState->state.lastFin = isFin(src);
  352|       |
  353|  5.44k|        if (Impl::refusePayloadLength(payLength, wState, user)) {
  ------------------
  |  Branch (353:13): [True: 476, False: 4.97k]
  ------------------
  354|    476|            Impl::forceClose(wState, user, ERR_TOO_BIG_MESSAGE);
  355|    476|            return true;
  356|    476|        }
  357|       |
  358|  4.97k|        if (payLength + MESSAGE_HEADER <= length) {
  ------------------
  |  Branch (358:13): [True: 3.45k, False: 1.52k]
  ------------------
  359|  3.45k|            bool fin = isFin(src);
  360|  3.45k|            if (isServer) {
  ------------------
  |  Branch (360:17): [Folded - Ignored]
  ------------------
  361|       |                /* This guy can never be assumed to be perfectly aligned since we can get multiple messages in one read */
  362|  3.45k|                unmaskImpreciseCopyMask<MESSAGE_HEADER>(src + MESSAGE_HEADER, (unsigned int) payLength);
  363|  3.45k|                if (Impl::handleFragment(src, payLength, 0, wState->state.opCode[wState->state.opStack], fin, wState, user)) {
  ------------------
  |  Branch (363:21): [True: 401, False: 3.05k]
  ------------------
  364|    401|                    return true;
  365|    401|                }
  366|  3.45k|            } else {
  367|      0|                if (Impl::handleFragment(src + MESSAGE_HEADER, payLength, 0, wState->state.opCode[wState->state.opStack], isFin(src), wState, user)) {
  ------------------
  |  Branch (367:21): [True: 0, False: 0]
  ------------------
  368|      0|                    return true;
  369|      0|                }
  370|      0|            }
  371|       |
  372|  3.05k|            if (fin) {
  ------------------
  |  Branch (372:17): [True: 2.17k, False: 876]
  ------------------
  373|  2.17k|                wState->state.opStack--;
  374|  2.17k|            }
  375|       |
  376|  3.05k|            src += payLength + MESSAGE_HEADER;
  377|  3.05k|            length -= (unsigned int) (payLength + MESSAGE_HEADER);
  378|  3.05k|            wState->state.spillLength = 0;
  379|  3.05k|            return false;
  380|  3.45k|        } else {
  381|  1.52k|            wState->state.spillLength = 0;
  382|  1.52k|            wState->state.wantsHead = false;
  383|  1.52k|            wState->remainingBytes = (unsigned int) (payLength - length + MESSAGE_HEADER);
  384|  1.52k|            bool fin = isFin(src);
  385|  1.52k|            if constexpr (isServer) {
  ------------------
  |  Branch (385:27): [Folded - Ignored]
  ------------------
  386|  1.52k|                memcpy(wState->mask, src + MESSAGE_HEADER - 4, 4);
  387|  1.52k|                uint64_t mask;
  388|  1.52k|                memcpy(&mask, src + MESSAGE_HEADER - 4, 4);
  389|  1.52k|                memcpy(((char *)&mask) + 4, src + MESSAGE_HEADER - 4, 4);
  390|  1.52k|                unmaskImprecise8<0>(src + MESSAGE_HEADER, mask, length);
  391|  1.52k|                rotateMask(4 - (length - MESSAGE_HEADER) % 4, wState->mask);
  392|  1.52k|            }
  393|  1.52k|            Impl::handleFragment(src + MESSAGE_HEADER, length - MESSAGE_HEADER, wState->remainingBytes, wState->state.opCode[wState->state.opStack], fin, wState, user);
  394|  1.52k|            return true;
  395|  1.52k|        }
  396|  4.97k|    }
EpollHelloWorld.cpp:_ZN3uWS17WebSocketProtocolILb1ENS_16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataEEE23unmaskImpreciseCopyMaskILi8EEEvPcj:
  308|  3.45k|    static inline void unmaskImpreciseCopyMask(char *src, unsigned int length) {
  309|  3.45k|        if constexpr (HEADER_SIZE != 6) {
  ------------------
  |  Branch (309:23): [Folded - Ignored]
  ------------------
  310|  3.45k|            char mask[8] = {src[-4], src[-3], src[-2], src[-1], src[-4], src[-3], src[-2], src[-1]};
  311|  3.45k|            uint64_t maskInt;
  312|  3.45k|            memcpy(&maskInt, mask, 8);
  313|  3.45k|            unmaskImprecise8<HEADER_SIZE>(src, maskInt, length);
  314|  3.45k|        } else {
  315|  3.45k|            char mask[4] = {src[-4], src[-3], src[-2], src[-1]};
  316|  3.45k|            uint32_t maskInt;
  317|  3.45k|            memcpy(&maskInt, mask, 4);
  318|  3.45k|            unmaskImprecise4<HEADER_SIZE>(src, maskInt, length);
  319|  3.45k|        }
  320|  3.45k|    }
EpollHelloWorld.cpp:_ZN3uWS17WebSocketProtocolILb1ENS_16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataEEE16unmaskImprecise8ILi8EEEvPcmj:
  285|  3.45k|    static inline void unmaskImprecise8(char *src, uint64_t mask, unsigned int length) {
  286|  15.8k|        for (unsigned int n = (length >> 3) + 1; n; n--) {
  ------------------
  |  Branch (286:50): [True: 12.4k, False: 3.45k]
  ------------------
  287|  12.4k|            uint64_t loaded;
  288|  12.4k|            memcpy(&loaded, src, 8);
  289|  12.4k|            loaded ^= mask;
  290|  12.4k|            memcpy(src - DESTINATION, &loaded, 8);
  291|  12.4k|            src += 8;
  292|  12.4k|        }
  293|  3.45k|    }
_ZN3uWS8protocol8bit_castItEET_Pc:
   87|  6.03k|T bit_cast(char *c) {
   88|  6.03k|    T val;
   89|  6.03k|    memcpy(&val, c, sizeof(T));
   90|  6.03k|    return val;
   91|  6.03k|}
EpollHelloWorld.cpp:_ZN3uWS17WebSocketProtocolILb1ENS_16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataEEE14consumeMessageILj14EmEEbT0_RPcRjPNS_14WebSocketStateILb1EEEPv:
  340|  3.63k|    static inline bool consumeMessage(T payLength, char *&src, unsigned int &length, WebSocketState<isServer> *wState, void *user) {
  341|  3.63k|        if (getOpCode(src)) {
  ------------------
  |  Branch (341:13): [True: 2.47k, False: 1.15k]
  ------------------
  342|  2.47k|            if (wState->state.opStack == 1 || (!wState->state.lastFin && getOpCode(src) < 2)) {
  ------------------
  |  Branch (342:17): [True: 194, False: 2.28k]
  |  Branch (342:48): [True: 482, False: 1.80k]
  |  Branch (342:74): [True: 194, False: 288]
  ------------------
  343|    388|                Impl::forceClose(wState, user);
  344|    388|                return true;
  345|    388|            }
  346|  2.09k|            wState->state.opCode[++wState->state.opStack] = (OpCode) getOpCode(src);
  347|  2.09k|        } else if (wState->state.opStack == -1) {
  ------------------
  |  Branch (347:20): [True: 194, False: 957]
  ------------------
  348|    194|            Impl::forceClose(wState, user);
  349|    194|            return true;
  350|    194|        }
  351|  3.04k|        wState->state.lastFin = isFin(src);
  352|       |
  353|  3.04k|        if (Impl::refusePayloadLength(payLength, wState, user)) {
  ------------------
  |  Branch (353:13): [True: 309, False: 2.73k]
  ------------------
  354|    309|            Impl::forceClose(wState, user, ERR_TOO_BIG_MESSAGE);
  355|    309|            return true;
  356|    309|        }
  357|       |
  358|  2.73k|        if (payLength + MESSAGE_HEADER <= length) {
  ------------------
  |  Branch (358:13): [True: 1.56k, False: 1.17k]
  ------------------
  359|  1.56k|            bool fin = isFin(src);
  360|  1.56k|            if (isServer) {
  ------------------
  |  Branch (360:17): [Folded - Ignored]
  ------------------
  361|       |                /* This guy can never be assumed to be perfectly aligned since we can get multiple messages in one read */
  362|  1.56k|                unmaskImpreciseCopyMask<MESSAGE_HEADER>(src + MESSAGE_HEADER, (unsigned int) payLength);
  363|  1.56k|                if (Impl::handleFragment(src, payLength, 0, wState->state.opCode[wState->state.opStack], fin, wState, user)) {
  ------------------
  |  Branch (363:21): [True: 357, False: 1.20k]
  ------------------
  364|    357|                    return true;
  365|    357|                }
  366|  1.56k|            } else {
  367|      0|                if (Impl::handleFragment(src + MESSAGE_HEADER, payLength, 0, wState->state.opCode[wState->state.opStack], isFin(src), wState, user)) {
  ------------------
  |  Branch (367:21): [True: 0, False: 0]
  ------------------
  368|      0|                    return true;
  369|      0|                }
  370|      0|            }
  371|       |
  372|  1.20k|            if (fin) {
  ------------------
  |  Branch (372:17): [True: 378, False: 829]
  ------------------
  373|    378|                wState->state.opStack--;
  374|    378|            }
  375|       |
  376|  1.20k|            src += payLength + MESSAGE_HEADER;
  377|  1.20k|            length -= (unsigned int) (payLength + MESSAGE_HEADER);
  378|  1.20k|            wState->state.spillLength = 0;
  379|  1.20k|            return false;
  380|  1.56k|        } else {
  381|  1.17k|            wState->state.spillLength = 0;
  382|  1.17k|            wState->state.wantsHead = false;
  383|  1.17k|            wState->remainingBytes = (unsigned int) (payLength - length + MESSAGE_HEADER);
  384|  1.17k|            bool fin = isFin(src);
  385|  1.17k|            if constexpr (isServer) {
  ------------------
  |  Branch (385:27): [Folded - Ignored]
  ------------------
  386|  1.17k|                memcpy(wState->mask, src + MESSAGE_HEADER - 4, 4);
  387|  1.17k|                uint64_t mask;
  388|  1.17k|                memcpy(&mask, src + MESSAGE_HEADER - 4, 4);
  389|  1.17k|                memcpy(((char *)&mask) + 4, src + MESSAGE_HEADER - 4, 4);
  390|  1.17k|                unmaskImprecise8<0>(src + MESSAGE_HEADER, mask, length);
  391|  1.17k|                rotateMask(4 - (length - MESSAGE_HEADER) % 4, wState->mask);
  392|  1.17k|            }
  393|  1.17k|            Impl::handleFragment(src + MESSAGE_HEADER, length - MESSAGE_HEADER, wState->remainingBytes, wState->state.opCode[wState->state.opStack], fin, wState, user);
  394|  1.17k|            return true;
  395|  1.17k|        }
  396|  2.73k|    }
EpollHelloWorld.cpp:_ZN3uWS17WebSocketProtocolILb1ENS_16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataEEE23unmaskImpreciseCopyMaskILi14EEEvPcj:
  308|  1.56k|    static inline void unmaskImpreciseCopyMask(char *src, unsigned int length) {
  309|  1.56k|        if constexpr (HEADER_SIZE != 6) {
  ------------------
  |  Branch (309:23): [Folded - Ignored]
  ------------------
  310|  1.56k|            char mask[8] = {src[-4], src[-3], src[-2], src[-1], src[-4], src[-3], src[-2], src[-1]};
  311|  1.56k|            uint64_t maskInt;
  312|  1.56k|            memcpy(&maskInt, mask, 8);
  313|  1.56k|            unmaskImprecise8<HEADER_SIZE>(src, maskInt, length);
  314|  1.56k|        } else {
  315|  1.56k|            char mask[4] = {src[-4], src[-3], src[-2], src[-1]};
  316|  1.56k|            uint32_t maskInt;
  317|  1.56k|            memcpy(&maskInt, mask, 4);
  318|  1.56k|            unmaskImprecise4<HEADER_SIZE>(src, maskInt, length);
  319|  1.56k|        }
  320|  1.56k|    }
EpollHelloWorld.cpp:_ZN3uWS17WebSocketProtocolILb1ENS_16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataEEE16unmaskImprecise8ILi14EEEvPcmj:
  285|  1.56k|    static inline void unmaskImprecise8(char *src, uint64_t mask, unsigned int length) {
  286|  9.57k|        for (unsigned int n = (length >> 3) + 1; n; n--) {
  ------------------
  |  Branch (286:50): [True: 8.00k, False: 1.56k]
  ------------------
  287|  8.00k|            uint64_t loaded;
  288|  8.00k|            memcpy(&loaded, src, 8);
  289|  8.00k|            loaded ^= mask;
  290|  8.00k|            memcpy(src - DESTINATION, &loaded, 8);
  291|  8.00k|            src += 8;
  292|  8.00k|        }
  293|  1.56k|    }
_ZN3uWS8protocol8bit_castImEET_Pc:
   87|  3.63k|T bit_cast(char *c) {
   88|  3.63k|    T val;
   89|  3.63k|    memcpy(&val, c, sizeof(T));
   90|  3.63k|    return val;
   91|  3.63k|}
EpollHelloWorld.cpp:_ZN3uWS17WebSocketProtocolILb1ENS_16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataEEE19consumeContinuationERPcRjPNS_14WebSocketStateILb1EEEPv:
  405|  36.7k|    static inline bool consumeContinuation(char *&src, unsigned int &length, WebSocketState<isServer> *wState, void *user) {
  406|  36.7k|        if (wState->remainingBytes <= length) {
  ------------------
  |  Branch (406:13): [True: 5.56k, False: 31.1k]
  ------------------
  407|  5.56k|            if (isServer) {
  ------------------
  |  Branch (407:17): [Folded - Ignored]
  ------------------
  408|  5.56k|                unsigned int n = wState->remainingBytes >> 2;
  409|  5.56k|                unmaskInplace(src, src + n * 4, wState->mask);
  410|  15.7k|                for (unsigned int i = 0, s = wState->remainingBytes % 4; i < s; i++) {
  ------------------
  |  Branch (410:74): [True: 10.1k, False: 5.56k]
  ------------------
  411|  10.1k|                    src[n * 4 + i] ^= wState->mask[i];
  412|  10.1k|                }
  413|  5.56k|            }
  414|       |
  415|  5.56k|            if (Impl::handleFragment(src, wState->remainingBytes, 0, wState->state.opCode[wState->state.opStack], wState->state.lastFin, wState, user)) {
  ------------------
  |  Branch (415:17): [True: 1.89k, False: 3.67k]
  ------------------
  416|  1.89k|                return false;
  417|  1.89k|            }
  418|       |
  419|  3.67k|            if (wState->state.lastFin) {
  ------------------
  |  Branch (419:17): [True: 2.65k, False: 1.01k]
  ------------------
  420|  2.65k|                wState->state.opStack--;
  421|  2.65k|            }
  422|       |
  423|  3.67k|            src += wState->remainingBytes;
  424|  3.67k|            length -= wState->remainingBytes;
  425|  3.67k|            wState->state.wantsHead = true;
  426|  3.67k|            return true;
  427|  31.1k|        } else {
  428|  31.1k|            if (isServer) {
  ------------------
  |  Branch (428:17): [Folded - Ignored]
  ------------------
  429|       |                /* No need to unmask if mask is 0 */
  430|  31.1k|                uint32_t nullmask = 0;
  431|  31.1k|                if (memcmp(wState->mask, &nullmask, sizeof(uint32_t))) {
  ------------------
  |  Branch (431:21): [True: 30.7k, False: 398]
  ------------------
  432|  30.7k|                    if /*constexpr*/ (LIBUS_RECV_BUFFER_LENGTH == length) {
  ------------------
  |  |   22|  30.7k|#define LIBUS_RECV_BUFFER_LENGTH 524288
  ------------------
  |  Branch (432:39): [True: 0, False: 30.7k]
  ------------------
  433|      0|                        unmaskAll(src, wState->mask);
  434|  30.7k|                    } else {
  435|       |                        // Slow path
  436|  30.7k|                        unmaskInplace(src, src + ((length >> 2) + 1) * 4, wState->mask);
  437|  30.7k|                    }
  438|  30.7k|                }
  439|  31.1k|            }
  440|       |
  441|  31.1k|            wState->remainingBytes -= length;
  442|  31.1k|            if (Impl::handleFragment(src, length, wState->remainingBytes, wState->state.opCode[wState->state.opStack], wState->state.lastFin, wState, user)) {
  ------------------
  |  Branch (442:17): [True: 66, False: 31.0k]
  ------------------
  443|     66|                return false;
  444|     66|            }
  445|       |
  446|  31.0k|            if (isServer && length % 4) {
  ------------------
  |  Branch (446:17): [Folded - Ignored]
  |  Branch (446:29): [True: 30.6k, False: 402]
  ------------------
  447|  30.6k|                rotateMask(4 - (length % 4), wState->mask);
  448|  30.6k|            }
  449|  31.0k|            return false;
  450|  31.1k|        }
  451|  36.7k|    }
EpollHelloWorld.cpp:_ZN3uWS17WebSocketProtocolILb1ENS_16WebSocketContextILb0ELb1EZ4testvE13PerSocketDataEEE13unmaskInplaceEPcS5_S5_:
  330|  36.3k|    static inline void unmaskInplace(char *data, char *stop, char *mask) {
  331|  1.13M|        while (data < stop) {
  ------------------
  |  Branch (331:16): [True: 1.09M, False: 36.3k]
  ------------------
  332|  1.09M|            *(data++) ^= mask[0];
  333|  1.09M|            *(data++) ^= mask[1];
  334|  1.09M|            *(data++) ^= mask[2];
  335|  1.09M|            *(data++) ^= mask[3];
  336|  1.09M|        }
  337|  36.3k|    }
_ZN3uWS14WebSocketStateILb1EE5StateC2Ev:
   70|  40.1k|        State() {
   71|  40.1k|            wantsHead = true;
   72|  40.1k|            spillLength = 0;
   73|  40.1k|            opStack = -1;
   74|  40.1k|            lastFin = true;
   75|  40.1k|        }

apple_no_sigpipe:
  269|  1.75M|LIBUS_SOCKET_DESCRIPTOR apple_no_sigpipe(LIBUS_SOCKET_DESCRIPTOR fd) {
  270|       |#ifdef __APPLE__
  271|       |    if (fd != LIBUS_SOCKET_ERROR) {
  272|       |        int no_sigpipe = 1;
  273|       |        setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *) &no_sigpipe, sizeof(int));
  274|       |    }
  275|       |#endif
  276|  1.75M|    return fd;
  277|  1.75M|}
bsd_set_nonblocking:
  279|  1.75M|LIBUS_SOCKET_DESCRIPTOR bsd_set_nonblocking(LIBUS_SOCKET_DESCRIPTOR fd) {
  280|       |#ifdef _WIN32
  281|       |    /* Libuv will set windows sockets as non-blocking */
  282|       |#else
  283|  1.75M|    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
  284|  1.75M|#endif
  285|  1.75M|    return fd;
  286|  1.75M|}
bsd_socket_nodelay:
  288|  1.74M|void bsd_socket_nodelay(LIBUS_SOCKET_DESCRIPTOR fd, int enabled) {
  289|  1.74M|    setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *) &enabled, sizeof(enabled));
  290|  1.74M|}
bsd_socket_flush:
  292|    255|void bsd_socket_flush(LIBUS_SOCKET_DESCRIPTOR fd) {
  293|       |    // Linux TCP_CORK has the same underlying corking mechanism as with MSG_MORE
  294|    255|#ifdef TCP_CORK
  295|    255|    int enabled = 0;
  296|    255|    setsockopt(fd, IPPROTO_TCP, TCP_CORK, (void *) &enabled, sizeof(int));
  297|    255|#endif
  298|    255|}
bsd_create_socket:
  300|  12.6k|LIBUS_SOCKET_DESCRIPTOR bsd_create_socket(int domain, int type, int protocol) {
  301|       |    // returns INVALID_SOCKET on error
  302|  12.6k|    int flags = 0;
  303|  12.6k|#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
  304|  12.6k|    flags = SOCK_CLOEXEC | SOCK_NONBLOCK;
  305|  12.6k|#endif
  306|       |
  307|  12.6k|    LIBUS_SOCKET_DESCRIPTOR created_fd = socket(domain, type | flags, protocol);
  ------------------
  |  |   38|  12.6k|#define LIBUS_SOCKET_DESCRIPTOR int
  ------------------
  308|       |
  309|  12.6k|    return bsd_set_nonblocking(apple_no_sigpipe(created_fd));
  310|  12.6k|}
bsd_close_socket:
  312|  1.74M|void bsd_close_socket(LIBUS_SOCKET_DESCRIPTOR fd) {
  313|       |#ifdef _WIN32
  314|       |    closesocket(fd);
  315|       |#else
  316|  1.74M|    close(fd);
  317|  1.74M|#endif
  318|  1.74M|}
bsd_shutdown_socket:
  320|   286k|void bsd_shutdown_socket(LIBUS_SOCKET_DESCRIPTOR fd) {
  321|       |#ifdef _WIN32
  322|       |    shutdown(fd, SD_SEND);
  323|       |#else
  324|   286k|    shutdown(fd, SHUT_WR);
  325|   286k|#endif
  326|   286k|}
bsd_shutdown_socket_read:
  328|    852|void bsd_shutdown_socket_read(LIBUS_SOCKET_DESCRIPTOR fd) {
  329|       |#ifdef _WIN32
  330|       |    shutdown(fd, SD_RECEIVE);
  331|       |#else
  332|    852|    shutdown(fd, SHUT_RD);
  333|    852|#endif
  334|    852|}
internal_finalize_bsd_addr:
  336|  1.77M|void internal_finalize_bsd_addr(struct bsd_addr_t *addr) {
  337|       |    // parse, so to speak, the address
  338|  1.77M|    if (addr->mem.ss_family == AF_INET6) {
  ------------------
  |  Branch (338:9): [True: 1.03M, False: 749k]
  ------------------
  339|  1.03M|        addr->ip = (char *) &((struct sockaddr_in6 *) addr)->sin6_addr;
  340|  1.03M|        addr->ip_length = sizeof(struct in6_addr);
  341|  1.03M|        addr->port = ntohs(((struct sockaddr_in6 *) addr)->sin6_port);
  342|  1.03M|    } else if (addr->mem.ss_family == AF_INET) {
  ------------------
  |  Branch (342:16): [True: 749k, False: 0]
  ------------------
  343|   749k|        addr->ip = (char *) &((struct sockaddr_in *) addr)->sin_addr;
  344|   749k|        addr->ip_length = sizeof(struct in_addr);
  345|   749k|        addr->port = ntohs(((struct sockaddr_in *) addr)->sin_port);
  346|   749k|    } else {
  347|      0|        addr->ip_length = 0;
  348|      0|        addr->port = -1;
  349|      0|    }
  350|  1.77M|}
bsd_local_addr:
  352|  2.32k|int bsd_local_addr(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd_addr_t *addr) {
  353|  2.32k|    addr->len = sizeof(addr->mem);
  354|  2.32k|    if (getsockname(fd, (struct sockaddr *) &addr->mem, &addr->len)) {
  ------------------
  |  Branch (354:9): [True: 2.32k, False: 0]
  ------------------
  355|  2.32k|        return -1;
  356|  2.32k|    }
  357|      0|    internal_finalize_bsd_addr(addr);
  358|      0|    return 0;
  359|  2.32k|}
bsd_remote_addr:
  361|  39.0k|int bsd_remote_addr(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd_addr_t *addr) {
  362|  39.0k|    addr->len = sizeof(addr->mem);
  363|  39.0k|    if (getpeername(fd, (struct sockaddr *) &addr->mem, &addr->len)) {
  ------------------
  |  Branch (363:9): [True: 0, False: 39.0k]
  ------------------
  364|      0|        return -1;
  365|      0|    }
  366|  39.0k|    internal_finalize_bsd_addr(addr);
  367|  39.0k|    return 0;
  368|  39.0k|}
bsd_addr_get_ip:
  370|  1.77M|char *bsd_addr_get_ip(struct bsd_addr_t *addr) {
  371|  1.77M|    return addr->ip;
  372|  1.77M|}
bsd_addr_get_ip_length:
  374|  1.81M|int bsd_addr_get_ip_length(struct bsd_addr_t *addr) {
  375|  1.81M|    return addr->ip_length;
  376|  1.81M|}
bsd_accept_socket:
  383|  2.96M|LIBUS_SOCKET_DESCRIPTOR bsd_accept_socket(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd_addr_t *addr) {
  384|  2.96M|    LIBUS_SOCKET_DESCRIPTOR accepted_fd;
  ------------------
  |  |   38|  2.96M|#define LIBUS_SOCKET_DESCRIPTOR int
  ------------------
  385|  2.96M|    addr->len = sizeof(addr->mem);
  386|       |
  387|  2.96M|#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
  388|       |    // Linux, FreeBSD
  389|  2.96M|    accepted_fd = accept4(fd, (struct sockaddr *) addr, &addr->len, SOCK_CLOEXEC | SOCK_NONBLOCK);
  390|       |#else
  391|       |    // Windows, OS X
  392|       |    accepted_fd = accept(fd, (struct sockaddr *) addr, &addr->len);
  393|       |
  394|       |#endif
  395|       |
  396|       |    /* We cannot rely on addr since it is not initialized if failed */
  397|  2.96M|    if (accepted_fd == LIBUS_SOCKET_ERROR) {
  ------------------
  |  |   44|  2.96M|#define LIBUS_SOCKET_ERROR -1
  ------------------
  |  Branch (397:9): [True: 1.22M, False: 1.74M]
  ------------------
  398|  1.22M|        return LIBUS_SOCKET_ERROR;
  ------------------
  |  |   44|  1.22M|#define LIBUS_SOCKET_ERROR -1
  ------------------
  399|  1.22M|    }
  400|       |
  401|  1.74M|    internal_finalize_bsd_addr(addr);
  402|       |
  403|  1.74M|    return bsd_set_nonblocking(apple_no_sigpipe(accepted_fd));
  404|  2.96M|}
bsd_recv:
  406|   479k|int bsd_recv(LIBUS_SOCKET_DESCRIPTOR fd, void *buf, int length, int flags) {
  407|   479k|    return recv(fd, buf, length, flags);
  408|   479k|}
bsd_send:
  436|   438k|int bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int msg_more) {
  437|       |
  438|       |    // MSG_MORE (Linux), MSG_PARTIAL (Windows), TCP_NOPUSH (BSD)
  439|       |
  440|       |#ifndef MSG_NOSIGNAL
  441|       |#define MSG_NOSIGNAL 0
  442|       |#endif
  443|       |
  444|   438k|#ifdef MSG_MORE
  445|       |
  446|       |    // for Linux we do not want signals
  447|   438k|    return send(fd, buf, length, ((msg_more != 0) * MSG_MORE) | MSG_NOSIGNAL);
  448|       |
  449|       |#else
  450|       |
  451|       |    // use TCP_NOPUSH
  452|       |
  453|       |    return send(fd, buf, length, MSG_NOSIGNAL);
  454|       |
  455|       |#endif
  456|   438k|}
bsd_would_block:
  458|  4.31k|int bsd_would_block() {
  459|       |#ifdef _WIN32
  460|       |    return WSAGetLastError() == WSAEWOULDBLOCK;
  461|       |#else
  462|  4.31k|    return errno == EWOULDBLOCK;// || errno == EAGAIN;
  463|  4.31k|#endif
  464|  4.31k|}
bsd_create_listen_socket:
  468|  6.41k|LIBUS_SOCKET_DESCRIPTOR bsd_create_listen_socket(const char *host, int port, int options) {
  469|  6.41k|    struct addrinfo hints, *result;
  470|  6.41k|    memset(&hints, 0, sizeof(struct addrinfo));
  471|       |
  472|  6.41k|    hints.ai_flags = AI_PASSIVE;
  473|  6.41k|    hints.ai_family = AF_UNSPEC;
  474|  6.41k|    hints.ai_socktype = SOCK_STREAM;
  475|       |
  476|  6.41k|    char port_string[16];
  477|  6.41k|    snprintf(port_string, 16, "%d", port);
  478|       |
  479|  6.41k|    if (getaddrinfo(host, port_string, &hints, &result)) {
  ------------------
  |  Branch (479:9): [True: 0, False: 6.41k]
  ------------------
  480|      0|        return LIBUS_SOCKET_ERROR;
  ------------------
  |  |   44|      0|#define LIBUS_SOCKET_ERROR -1
  ------------------
  481|      0|    }
  482|       |
  483|  6.41k|    LIBUS_SOCKET_DESCRIPTOR listenFd = LIBUS_SOCKET_ERROR;
  ------------------
  |  |   38|  6.41k|#define LIBUS_SOCKET_DESCRIPTOR int
  ------------------
                  LIBUS_SOCKET_DESCRIPTOR listenFd = LIBUS_SOCKET_ERROR;
  ------------------
  |  |   44|  6.41k|#define LIBUS_SOCKET_ERROR -1
  ------------------
  484|  6.41k|    struct addrinfo *listenAddr;
  485|  12.8k|    for (struct addrinfo *a = result; a && listenFd == LIBUS_SOCKET_ERROR; a = a->ai_next) {
  ------------------
  |  |   44|  6.41k|#define LIBUS_SOCKET_ERROR -1
  ------------------
  |  Branch (485:39): [True: 6.41k, False: 6.41k]
  |  Branch (485:44): [True: 6.41k, False: 0]
  ------------------
  486|  6.41k|        if (a->ai_family == AF_INET6) {
  ------------------
  |  Branch (486:13): [True: 5.46k, False: 946]
  ------------------
  487|  5.46k|            listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol);
  488|  5.46k|            listenAddr = a;
  489|  5.46k|        }
  490|  6.41k|    }
  491|       |
  492|  7.36k|    for (struct addrinfo *a = result; a && listenFd == LIBUS_SOCKET_ERROR; a = a->ai_next) {
  ------------------
  |  |   44|  6.41k|#define LIBUS_SOCKET_ERROR -1
  ------------------
  |  Branch (492:39): [True: 6.41k, False: 946]
  |  Branch (492:44): [True: 946, False: 5.46k]
  ------------------
  493|    946|        if (a->ai_family == AF_INET) {
  ------------------
  |  Branch (493:13): [True: 803, False: 143]
  ------------------
  494|    803|            listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol);
  495|    803|            listenAddr = a;
  496|    803|        }
  497|    946|    }
  498|       |
  499|  6.41k|    if (listenFd == LIBUS_SOCKET_ERROR) {
  ------------------
  |  |   44|  6.41k|#define LIBUS_SOCKET_ERROR -1
  ------------------
  |  Branch (499:9): [True: 143, False: 6.27k]
  ------------------
  500|    143|        freeaddrinfo(result);
  501|    143|        return LIBUS_SOCKET_ERROR;
  ------------------
  |  |   44|    143|#define LIBUS_SOCKET_ERROR -1
  ------------------
  502|    143|    }
  503|       |
  504|  6.27k|    if (port != 0) {
  ------------------
  |  Branch (504:9): [True: 6.27k, False: 0]
  ------------------
  505|       |        /* Otherwise, always enable SO_REUSEPORT and SO_REUSEADDR _unless_ options specify otherwise */
  506|       |#ifdef _WIN32
  507|       |        if (options & LIBUS_LISTEN_EXCLUSIVE_PORT) {
  508|       |            int optval2 = 1;
  509|       |            setsockopt(listenFd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (void *) &optval2, sizeof(optval2));
  510|       |        } else {
  511|       |            int optval3 = 1;
  512|       |            setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval3, sizeof(optval3));
  513|       |        }
  514|       |#else
  515|  6.27k|    #if /*defined(__linux) &&*/ defined(SO_REUSEPORT)
  516|  6.27k|        if (!(options & LIBUS_LISTEN_EXCLUSIVE_PORT)) {
  ------------------
  |  Branch (516:13): [True: 6.27k, False: 0]
  ------------------
  517|  6.27k|            int optval = 1;
  518|  6.27k|            setsockopt(listenFd, SOL_SOCKET, SO_REUSEPORT, (void *) &optval, sizeof(optval));
  519|  6.27k|        }
  520|  6.27k|    #endif
  521|  6.27k|        int enabled = 1;
  522|  6.27k|        setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, (void *) &enabled, sizeof(enabled));
  523|  6.27k|#endif
  524|       |
  525|  6.27k|    }
  526|       |    
  527|  6.27k|#ifdef IPV6_V6ONLY
  528|  6.27k|    int disabled = 0;
  529|  6.27k|    setsockopt(listenFd, IPPROTO_IPV6, IPV6_V6ONLY, (void *) &disabled, sizeof(disabled));
  530|  6.27k|#endif
  531|       |
  532|  6.27k|    if (bind(listenFd, listenAddr->ai_addr, (socklen_t) listenAddr->ai_addrlen) || listen(listenFd, 512)) {
  ------------------
  |  Branch (532:9): [True: 0, False: 6.27k]
  |  Branch (532:84): [True: 12, False: 6.25k]
  ------------------
  533|     12|        bsd_close_socket(listenFd);
  534|     12|        freeaddrinfo(result);
  535|     12|        return LIBUS_SOCKET_ERROR;
  ------------------
  |  |   44|     12|#define LIBUS_SOCKET_ERROR -1
  ------------------
  536|     12|    }
  537|       |
  538|  6.25k|    freeaddrinfo(result);
  539|  6.25k|    return listenFd;
  540|  6.27k|}
bsd_create_connect_socket:
  712|  6.41k|LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(const char *host, int port, const char *source_host, int options) {
  713|  6.41k|    struct addrinfo hints, *result;
  714|  6.41k|    memset(&hints, 0, sizeof(struct addrinfo));
  715|  6.41k|    hints.ai_family = AF_UNSPEC;
  716|  6.41k|    hints.ai_socktype = SOCK_STREAM;
  717|       |
  718|  6.41k|    char port_string[16];
  719|  6.41k|    snprintf(port_string, 16, "%d", port);
  720|       |
  721|  6.41k|    if (getaddrinfo(host, port_string, &hints, &result) != 0) {
  ------------------
  |  Branch (721:9): [True: 21, False: 6.39k]
  ------------------
  722|     21|        return LIBUS_SOCKET_ERROR;
  ------------------
  |  |   44|     21|#define LIBUS_SOCKET_ERROR -1
  ------------------
  723|     21|    }
  724|       |
  725|  6.39k|    LIBUS_SOCKET_DESCRIPTOR fd = bsd_create_socket(result->ai_family, result->ai_socktype, result->ai_protocol);
  ------------------
  |  |   38|  6.39k|#define LIBUS_SOCKET_DESCRIPTOR int
  ------------------
  726|  6.39k|    if (fd == LIBUS_SOCKET_ERROR) {
  ------------------
  |  |   44|  6.39k|#define LIBUS_SOCKET_ERROR -1
  ------------------
  |  Branch (726:9): [True: 4.06k, False: 2.32k]
  ------------------
  727|  4.06k|        freeaddrinfo(result);
  728|  4.06k|        return LIBUS_SOCKET_ERROR;
  ------------------
  |  |   44|  4.06k|#define LIBUS_SOCKET_ERROR -1
  ------------------
  729|  4.06k|    }
  730|       |
  731|  2.32k|    if (source_host) {
  ------------------
  |  Branch (731:9): [True: 2.32k, False: 0]
  ------------------
  732|  2.32k|        struct addrinfo *interface_result;
  733|  2.32k|        if (!getaddrinfo(source_host, NULL, NULL, &interface_result)) {
  ------------------
  |  Branch (733:13): [True: 2.32k, False: 4]
  ------------------
  734|  2.32k|            int ret = bind(fd, interface_result->ai_addr, (socklen_t) interface_result->ai_addrlen);
  735|  2.32k|            freeaddrinfo(interface_result);
  736|  2.32k|            if (ret == LIBUS_SOCKET_ERROR) {
  ------------------
  |  |   44|  2.32k|#define LIBUS_SOCKET_ERROR -1
  ------------------
  |  Branch (736:17): [True: 0, False: 2.32k]
  ------------------
  737|      0|                bsd_close_socket(fd);
  738|      0|                freeaddrinfo(result);
  739|      0|                return LIBUS_SOCKET_ERROR;
  ------------------
  |  |   44|      0|#define LIBUS_SOCKET_ERROR -1
  ------------------
  740|      0|            }
  741|  2.32k|        }
  742|  2.32k|    }
  743|       |
  744|  2.32k|    connect(fd, result->ai_addr, (socklen_t) result->ai_addrlen);
  745|  2.32k|    freeaddrinfo(result);
  746|       |
  747|  2.32k|    return fd;
  748|  2.32k|}

default_is_low_prio_handler:
   25|   479k|int default_is_low_prio_handler(struct us_socket_t *s) {
   26|   479k|    return 0;
   27|   479k|}
us_socket_context_timestamp:
   31|  6.41k|unsigned short us_socket_context_timestamp(int ssl, struct us_socket_context_t *context) {
   32|  6.41k|    return context->timestamp;
   33|  6.41k|}
us_listen_socket_close:
   35|  6.25k|void us_listen_socket_close(int ssl, struct us_listen_socket_t *ls) {
   36|       |    /* us_listen_socket_t extends us_socket_t so we close in similar ways */
   37|  6.25k|    if (!us_socket_is_closed(0, &ls->s)) {
  ------------------
  |  Branch (37:9): [True: 6.25k, False: 0]
  ------------------
   38|  6.25k|        us_internal_socket_context_unlink_listen_socket(ls->s.context, ls);
   39|  6.25k|        us_poll_stop((struct us_poll_t *) &ls->s, ls->s.context->loop);
   40|  6.25k|        bsd_close_socket(us_poll_fd((struct us_poll_t *) &ls->s));
   41|       |
   42|       |        /* Link this socket to the close-list and let it be deleted after this iteration */
   43|  6.25k|        ls->s.next = ls->s.context->loop->data.closed_head;
   44|  6.25k|        ls->s.context->loop->data.closed_head = &ls->s;
   45|       |
   46|       |        /* Any socket with prev = context is marked as closed */
   47|  6.25k|        ls->s.prev = (struct us_socket_t *) ls->s.context;
   48|  6.25k|    }
   49|       |
   50|       |    /* We cannot immediately free a listen socket as we can be inside an accept loop */
   51|  6.25k|}
us_internal_socket_context_unlink_listen_socket:
   71|  6.25k|void us_internal_socket_context_unlink_listen_socket(struct us_socket_context_t *context, struct us_listen_socket_t *ls) {
   72|       |    /* We have to properly update the iterator used to sweep sockets for timeouts */
   73|  6.25k|    if (ls == (struct us_listen_socket_t *) context->iterator) {
  ------------------
  |  Branch (73:9): [True: 0, False: 6.25k]
  ------------------
   74|      0|        context->iterator = ls->s.next;
   75|      0|    }
   76|       |
   77|  6.25k|    if (ls->s.prev == ls->s.next) {
  ------------------
  |  Branch (77:9): [True: 6.25k, False: 0]
  ------------------
   78|  6.25k|        context->head_listen_sockets = 0;
   79|  6.25k|    } else {
   80|      0|        if (ls->s.prev) {
  ------------------
  |  Branch (80:13): [True: 0, False: 0]
  ------------------
   81|      0|            ls->s.prev->next = ls->s.next;
   82|      0|        } else {
   83|      0|            context->head_listen_sockets = (struct us_listen_socket_t *) ls->s.next;
   84|      0|        }
   85|      0|        if (ls->s.next) {
  ------------------
  |  Branch (85:13): [True: 0, False: 0]
  ------------------
   86|      0|            ls->s.next->prev = ls->s.prev;
   87|      0|        }
   88|      0|    }
   89|  6.25k|}
us_internal_socket_context_unlink_socket:
   91|  1.78M|void us_internal_socket_context_unlink_socket(struct us_socket_context_t *context, struct us_socket_t *s) {
   92|       |    /* We have to properly update the iterator used to sweep sockets for timeouts */
   93|  1.78M|    if (s == context->iterator) {
  ------------------
  |  Branch (93:9): [True: 5.31k, False: 1.77M]
  ------------------
   94|  5.31k|        context->iterator = s->next;
   95|  5.31k|    }
   96|       |
   97|  1.78M|    if (s->prev == s->next) {
  ------------------
  |  Branch (97:9): [True: 221k, False: 1.56M]
  ------------------
   98|   221k|        context->head_sockets = 0;
   99|  1.56M|    } else {
  100|  1.56M|        if (s->prev) {
  ------------------
  |  Branch (100:13): [True: 700k, False: 860k]
  ------------------
  101|   700k|            s->prev->next = s->next;
  102|   860k|        } else {
  103|   860k|            context->head_sockets = s->next;
  104|   860k|        }
  105|  1.56M|        if (s->next) {
  ------------------
  |  Branch (105:13): [True: 1.55M, False: 10.4k]
  ------------------
  106|  1.55M|            s->next->prev = s->prev;
  107|  1.55M|        }
  108|  1.56M|    }
  109|  1.78M|}
us_internal_socket_context_link_listen_socket:
  112|  6.25k|void us_internal_socket_context_link_listen_socket(struct us_socket_context_t *context, struct us_listen_socket_t *ls) {
  113|  6.25k|    ls->s.context = context;
  114|  6.25k|    ls->s.next = (struct us_socket_t *) context->head_listen_sockets;
  115|  6.25k|    ls->s.prev = 0;
  116|  6.25k|    if (context->head_listen_sockets) {
  ------------------
  |  Branch (116:9): [True: 0, False: 6.25k]
  ------------------
  117|      0|        context->head_listen_sockets->s.prev = &ls->s;
  118|      0|    }
  119|  6.25k|    context->head_listen_sockets = ls;
  120|  6.25k|}
us_internal_socket_context_link_socket:
  123|  1.78M|void us_internal_socket_context_link_socket(struct us_socket_context_t *context, struct us_socket_t *s) {
  124|  1.78M|    s->context = context;
  125|  1.78M|    s->next = context->head_sockets;
  126|  1.78M|    s->prev = 0;
  127|  1.78M|    if (context->head_sockets) {
  ------------------
  |  Branch (127:9): [True: 1.56M, False: 221k]
  ------------------
  128|  1.56M|        context->head_sockets->prev = s;
  129|  1.56M|    }
  130|  1.78M|    context->head_sockets = s;
  131|  1.78M|}
us_socket_context_loop:
  133|  3.10M|struct us_loop_t *us_socket_context_loop(int ssl, struct us_socket_context_t *context) {
  134|  3.10M|    return context->loop;
  135|  3.10M|}
us_socket_context_find_server_name_userdata:
  140|  6.41k|void *us_socket_context_find_server_name_userdata(int ssl, struct us_socket_context_t *context, const char *hostname_pattern) {
  141|       |#ifndef LIBUS_NO_SSL
  142|       |    if (ssl) {
  143|       |        return us_internal_ssl_socket_context_find_server_name_userdata((struct us_internal_ssl_socket_context_t *) context, hostname_pattern);
  144|       |    }
  145|       |#endif
  146|  6.41k|    return NULL;
  147|  6.41k|}
us_socket_context_remove_server_name:
  169|  6.41k|void us_socket_context_remove_server_name(int ssl, struct us_socket_context_t *context, const char *hostname_pattern) {
  170|       |#ifndef LIBUS_NO_SSL
  171|       |    if (ssl) {
  172|       |        us_internal_ssl_socket_context_remove_server_name((struct us_internal_ssl_socket_context_t *) context, hostname_pattern);
  173|       |    }
  174|       |#endif
  175|  6.41k|}
us_socket_context_on_server_name:
  182|  6.41k|void us_socket_context_on_server_name(int ssl, struct us_socket_context_t *context, void (*cb)(struct us_socket_context_t *, const char *hostname)) {
  183|       |#ifndef LIBUS_NO_SSL
  184|       |    if (ssl) {
  185|       |        us_internal_ssl_socket_context_on_server_name((struct us_internal_ssl_socket_context_t *) context, (void (*)(struct us_internal_ssl_socket_context_t *, const char *hostname)) cb);
  186|       |    }
  187|       |#endif
  188|  6.41k|}
us_socket_context_get_native_handle:
  192|  6.41k|void *us_socket_context_get_native_handle(int ssl, struct us_socket_context_t *context) {
  193|       |#ifndef LIBUS_NO_SSL
  194|       |    if (ssl) {
  195|       |        return us_internal_ssl_socket_context_get_native_handle((struct us_internal_ssl_socket_context_t *) context);
  196|       |    }
  197|       |#endif
  198|       |
  199|       |    /* There is no native handle for a non-SSL socket context */
  200|  6.41k|    return 0;
  201|  6.41k|}
us_create_socket_context:
  204|  25.6k|struct us_socket_context_t *us_create_socket_context(int ssl, struct us_loop_t *loop, int context_ext_size, struct us_socket_context_options_t options) {
  205|       |#ifndef LIBUS_NO_SSL
  206|       |    if (ssl) {
  207|       |        /* This function will call us, again, with SSL = false and a bigger ext_size */
  208|       |        return (struct us_socket_context_t *) us_internal_create_ssl_socket_context(loop, context_ext_size, options);
  209|       |    }
  210|       |#endif
  211|       |
  212|       |    /* This path is taken once either way - always BEFORE whatever SSL may do LATER.
  213|       |     * context_ext_size will however be modified larger in case of SSL, to hold SSL extensions */
  214|       |
  215|  25.6k|    struct us_socket_context_t *context = malloc(sizeof(struct us_socket_context_t) + context_ext_size);
  216|  25.6k|    context->loop = loop;
  217|  25.6k|    context->head_sockets = 0;
  218|  25.6k|    context->head_listen_sockets = 0;
  219|  25.6k|    context->iterator = 0;
  220|  25.6k|    context->next = 0;
  221|  25.6k|    context->is_low_prio = default_is_low_prio_handler;
  222|       |
  223|       |    /* Begin at 0 */
  224|  25.6k|    context->timestamp = 0;
  225|  25.6k|    context->long_timestamp = 0;
  226|  25.6k|    context->global_tick = 0;
  227|       |
  228|       |    /* Some new events must be set to null for backwards compatibility */
  229|  25.6k|    context->on_pre_open = 0;
  230|       |
  231|  25.6k|    us_internal_loop_link(loop, context);
  232|       |
  233|       |    /* If we are called from within SSL code, SSL code will make further changes to us */
  234|  25.6k|    return context;
  235|  25.6k|}
us_socket_context_free:
  237|  25.6k|void us_socket_context_free(int ssl, struct us_socket_context_t *context) {
  238|       |#ifndef LIBUS_NO_SSL
  239|       |    if (ssl) {
  240|       |        /* This function will call us again with SSL=false */
  241|       |        us_internal_ssl_socket_context_free((struct us_internal_ssl_socket_context_t *) context);
  242|       |        return;
  243|       |    }
  244|       |#endif
  245|       |
  246|       |    /* This path is taken once either way - always AFTER whatever SSL may do BEFORE.
  247|       |     * This is the opposite order compared to when creating the context - SSL code is cleaning up before non-SSL */
  248|       |
  249|  25.6k|    us_internal_loop_unlink(context->loop, context);
  250|  25.6k|    free(context);
  251|  25.6k|}
us_socket_context_listen:
  253|  6.41k|struct us_listen_socket_t *us_socket_context_listen(int ssl, struct us_socket_context_t *context, const char *host, int port, int options, int socket_ext_size) {
  254|       |#ifndef LIBUS_NO_SSL
  255|       |    if (ssl) {
  256|       |        return us_internal_ssl_socket_context_listen((struct us_internal_ssl_socket_context_t *) context, host, port, options, socket_ext_size);
  257|       |    }
  258|       |#endif
  259|       |
  260|  6.41k|    LIBUS_SOCKET_DESCRIPTOR listen_socket_fd = bsd_create_listen_socket(host, port, options);
  ------------------
  |  |   38|  6.41k|#define LIBUS_SOCKET_DESCRIPTOR int
  ------------------
  261|       |
  262|  6.41k|    if (listen_socket_fd == LIBUS_SOCKET_ERROR) {
  ------------------
  |  |   44|  6.41k|#define LIBUS_SOCKET_ERROR -1
  ------------------
  |  Branch (262:9): [True: 155, False: 6.25k]
  ------------------
  263|    155|        return 0;
  264|    155|    }
  265|       |
  266|  6.25k|    struct us_poll_t *p = us_create_poll(context->loop, 0, sizeof(struct us_listen_socket_t));
  267|  6.25k|    us_poll_init(p, listen_socket_fd, POLL_TYPE_SEMI_SOCKET);
  268|  6.25k|    us_poll_start(p, context->loop, LIBUS_SOCKET_READABLE);
  ------------------
  |  |   27|  6.25k|#define LIBUS_SOCKET_READABLE EPOLLIN
  ------------------
  269|       |
  270|  6.25k|    struct us_listen_socket_t *ls = (struct us_listen_socket_t *) p;
  271|       |
  272|  6.25k|    ls->s.context = context;
  273|  6.25k|    ls->s.timeout = 255;
  274|  6.25k|    ls->s.long_timeout = 255;
  275|  6.25k|    ls->s.low_prio_state = 0;
  276|  6.25k|    ls->s.next = 0;
  277|  6.25k|    us_internal_socket_context_link_listen_socket(context, ls);
  278|       |
  279|  6.25k|    ls->socket_ext_size = socket_ext_size;
  280|       |
  281|  6.25k|    return ls;
  282|  6.41k|}
us_socket_context_connect:
  315|  6.41k|struct us_socket_t *us_socket_context_connect(int ssl, struct us_socket_context_t *context, const char *host, int port, const char *source_host, int options, int socket_ext_size) {
  316|       |#ifndef LIBUS_NO_SSL
  317|       |    if (ssl) {
  318|       |        return (struct us_socket_t *) us_internal_ssl_socket_context_connect((struct us_internal_ssl_socket_context_t *) context, host, port, source_host, options, socket_ext_size);
  319|       |    }
  320|       |#endif
  321|       |
  322|  6.41k|    LIBUS_SOCKET_DESCRIPTOR connect_socket_fd = bsd_create_connect_socket(host, port, source_host, options);
  ------------------
  |  |   38|  6.41k|#define LIBUS_SOCKET_DESCRIPTOR int
  ------------------
  323|  6.41k|    if (connect_socket_fd == LIBUS_SOCKET_ERROR) {
  ------------------
  |  |   44|  6.41k|#define LIBUS_SOCKET_ERROR -1
  ------------------
  |  Branch (323:9): [True: 4.09k, False: 2.32k]
  ------------------
  324|  4.09k|        return 0;
  325|  4.09k|    }
  326|       |
  327|       |    /* Connect sockets are semi-sockets just like listen sockets */
  328|  2.32k|    struct us_poll_t *p = us_create_poll(context->loop, 0, sizeof(struct us_socket_t) + socket_ext_size);
  329|  2.32k|    us_poll_init(p, connect_socket_fd, POLL_TYPE_SEMI_SOCKET);
  330|  2.32k|    us_poll_start(p, context->loop, LIBUS_SOCKET_WRITABLE);
  ------------------
  |  |   28|  2.32k|#define LIBUS_SOCKET_WRITABLE EPOLLOUT
  ------------------
  331|       |
  332|  2.32k|    struct us_socket_t *connect_socket = (struct us_socket_t *) p;
  333|       |
  334|       |    /* Link it into context so that timeout fires properly */
  335|  2.32k|    connect_socket->context = context;
  336|  2.32k|    connect_socket->timeout = 255;
  337|  2.32k|    connect_socket->long_timeout = 255;
  338|  2.32k|    connect_socket->low_prio_state = 0;
  339|  2.32k|    us_internal_socket_context_link_socket(context, connect_socket);
  340|       |
  341|  2.32k|    return connect_socket;
  342|  6.41k|}
us_create_child_socket_context:
  373|  12.8k|struct us_socket_context_t *us_create_child_socket_context(int ssl, struct us_socket_context_t *context, int context_ext_size) {
  374|       |#ifndef LIBUS_NO_SSL
  375|       |    if (ssl) {
  376|       |        return (struct us_socket_context_t *) us_internal_create_child_ssl_socket_context((struct us_internal_ssl_socket_context_t *) context, context_ext_size);
  377|       |    }
  378|       |#endif
  379|       |
  380|       |    /* For TCP we simply create a new context as nothing is shared */
  381|  12.8k|    struct us_socket_context_options_t options = {0};
  382|  12.8k|    return us_create_socket_context(ssl, context->loop, context_ext_size, options);
  383|  12.8k|}
us_socket_context_adopt_socket:
  386|  40.1k|struct us_socket_t *us_socket_context_adopt_socket(int ssl, struct us_socket_context_t *context, struct us_socket_t *s, int ext_size) {
  387|       |#ifndef LIBUS_NO_SSL
  388|       |    if (ssl) {
  389|       |        return (struct us_socket_t *) us_internal_ssl_socket_context_adopt_socket((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t *) s, ext_size);
  390|       |    }
  391|       |#endif
  392|       |
  393|       |    /* Cannot adopt a closed socket */
  394|  40.1k|    if (us_socket_is_closed(ssl, s)) {
  ------------------
  |  Branch (394:9): [True: 0, False: 40.1k]
  ------------------
  395|      0|        return s;
  396|      0|    }
  397|       |
  398|  40.1k|    if (s->low_prio_state != 1) {
  ------------------
  |  Branch (398:9): [True: 40.1k, False: 0]
  ------------------
  399|       |        /* This properly updates the iterator if in on_timeout */
  400|  40.1k|        us_internal_socket_context_unlink_socket(s->context, s);
  401|  40.1k|    }
  402|       |
  403|  40.1k|    struct us_socket_t *new_s = (struct us_socket_t *) us_poll_resize(&s->p, s->context->loop, sizeof(struct us_socket_t) + ext_size);
  404|  40.1k|    new_s->timeout = 255;
  405|  40.1k|    new_s->long_timeout = 255;
  406|       |
  407|  40.1k|    if (new_s->low_prio_state == 1) {
  ------------------
  |  Branch (407:9): [True: 0, False: 40.1k]
  ------------------
  408|       |        /* update pointers in low-priority queue */
  409|      0|        if (!new_s->prev) new_s->context->loop->data.low_prio_head = new_s;
  ------------------
  |  Branch (409:13): [True: 0, False: 0]
  ------------------
  410|      0|        else new_s->prev->next = new_s;
  411|       |
  412|      0|        if (new_s->next) new_s->next->prev = new_s;
  ------------------
  |  Branch (412:13): [True: 0, False: 0]
  ------------------
  413|  40.1k|    } else {
  414|  40.1k|        us_internal_socket_context_link_socket(context, new_s);
  415|  40.1k|    }
  416|       |
  417|  40.1k|    return new_s;
  418|  40.1k|}
us_socket_context_on_open:
  426|  12.8k|void us_socket_context_on_open(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_open)(struct us_socket_t *s, int is_client, char *ip, int ip_length)) {
  427|       |#ifndef LIBUS_NO_SSL
  428|       |    if (ssl) {
  429|       |        us_internal_ssl_socket_context_on_open((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *, int,  char *, int)) on_open);
  430|       |        return;
  431|       |    }
  432|       |#endif
  433|       |
  434|  12.8k|    context->on_open = on_open;
  435|  12.8k|}
us_socket_context_on_close:
  437|  25.6k|void us_socket_context_on_close(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_close)(struct us_socket_t *s, int code, void *reason)) {
  438|       |#ifndef LIBUS_NO_SSL
  439|       |    if (ssl) {
  440|       |        us_internal_ssl_socket_context_on_close((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *, int code, void *reason)) on_close);
  441|       |        return;
  442|       |    }
  443|       |#endif
  444|       |
  445|  25.6k|    context->on_close = on_close;
  446|  25.6k|}
us_socket_context_on_data:
  448|  25.6k|void us_socket_context_on_data(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_data)(struct us_socket_t *s, char *data, int length)) {
  449|       |#ifndef LIBUS_NO_SSL
  450|       |    if (ssl) {
  451|       |        us_internal_ssl_socket_context_on_data((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *, char *, int)) on_data);
  452|       |        return;
  453|       |    }
  454|       |#endif
  455|       |
  456|  25.6k|    context->on_data = on_data;
  457|  25.6k|}
us_socket_context_on_writable:
  459|  25.6k|void us_socket_context_on_writable(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_writable)(struct us_socket_t *s)) {
  460|       |#ifndef LIBUS_NO_SSL
  461|       |    if (ssl) {
  462|       |        us_internal_ssl_socket_context_on_writable((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *)) on_writable);
  463|       |        return;
  464|       |    }
  465|       |#endif
  466|       |
  467|  25.6k|    context->on_writable = on_writable;
  468|  25.6k|}
us_socket_context_on_long_timeout:
  470|  12.8k|void us_socket_context_on_long_timeout(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_long_timeout)(struct us_socket_t *)) {
  471|       |#ifndef LIBUS_NO_SSL
  472|       |    if (ssl) {
  473|       |        us_internal_ssl_socket_context_on_long_timeout((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *)) on_long_timeout);
  474|       |        return;
  475|       |    }
  476|       |#endif
  477|       |
  478|  12.8k|    context->on_socket_long_timeout = on_long_timeout;
  479|  12.8k|}
us_socket_context_on_timeout:
  481|  19.2k|void us_socket_context_on_timeout(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_timeout)(struct us_socket_t *)) {
  482|       |#ifndef LIBUS_NO_SSL
  483|       |    if (ssl) {
  484|       |        us_internal_ssl_socket_context_on_timeout((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *)) on_timeout);
  485|       |        return;
  486|       |    }
  487|       |#endif
  488|       |
  489|  19.2k|    context->on_socket_timeout = on_timeout;
  490|  19.2k|}
us_socket_context_on_end:
  492|  25.6k|void us_socket_context_on_end(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_end)(struct us_socket_t *)) {
  493|       |#ifndef LIBUS_NO_SSL
  494|       |    if (ssl) {
  495|       |        us_internal_ssl_socket_context_on_end((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *)) on_end);
  496|       |        return;
  497|       |    }
  498|       |#endif
  499|       |
  500|  25.6k|    context->on_end = on_end;
  501|  25.6k|}
us_socket_context_on_connect_error:
  503|  6.41k|void us_socket_context_on_connect_error(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_connect_error)(struct us_socket_t *s, int code)) {
  504|       |#ifndef LIBUS_NO_SSL
  505|       |    if (ssl) {
  506|       |        us_internal_ssl_socket_context_on_connect_error((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *, int)) on_connect_error);
  507|       |        return;
  508|       |    }
  509|       |#endif
  510|       |    
  511|  6.41k|    context->on_connect_error = on_connect_error;
  512|  6.41k|}
us_socket_context_ext:
  514|  4.51M|void *us_socket_context_ext(int ssl, struct us_socket_context_t *context) {
  515|       |#ifndef LIBUS_NO_SSL
  516|       |    if (ssl) {
  517|       |        return us_internal_ssl_socket_context_ext((struct us_internal_ssl_socket_context_t *) context);
  518|       |    }
  519|       |#endif
  520|       |
  521|  4.51M|    return context + 1;
  522|  4.51M|}

us_loop_free:
   36|  6.41k|void us_loop_free(struct us_loop_t *loop) {
   37|  6.41k|    us_internal_loop_data_free(loop);
   38|  6.41k|    close(loop->fd);
   39|  6.41k|    free(loop);
   40|  6.41k|}
us_create_poll:
   43|  1.76M|struct us_poll_t *us_create_poll(struct us_loop_t *loop, int fallthrough, unsigned int ext_size) {
   44|  1.76M|    if (!fallthrough) {
  ------------------
  |  Branch (44:9): [True: 1.74M, False: 19.2k]
  ------------------
   45|  1.74M|        loop->num_polls++;
   46|  1.74M|    }
   47|  1.76M|    return malloc(sizeof(struct us_poll_t) + ext_size);
   48|  1.76M|}
us_poll_free:
   51|  1.76M|void us_poll_free(struct us_poll_t *p, struct us_loop_t *loop) {
   52|  1.76M|    loop->num_polls--;
   53|  1.76M|    free(p);
   54|  1.76M|}
us_poll_ext:
   56|  39.0k|void *us_poll_ext(struct us_poll_t *p) {
   57|  39.0k|    return p + 1;
   58|  39.0k|}
us_poll_init:
   61|  1.76M|void us_poll_init(struct us_poll_t *p, LIBUS_SOCKET_DESCRIPTOR fd, int poll_type) {
   62|  1.76M|    p->state.fd = fd;
   63|  1.76M|    p->state.poll_type = poll_type;
   64|  1.76M|}
us_poll_events:
   66|  11.0M|int us_poll_events(struct us_poll_t *p) {
   67|  11.0M|    return ((p->state.poll_type & POLL_TYPE_POLLING_IN) ? LIBUS_SOCKET_READABLE : 0) | ((p->state.poll_type & POLL_TYPE_POLLING_OUT) ? LIBUS_SOCKET_WRITABLE : 0);
  ------------------
  |  |   27|  11.0M|#define LIBUS_SOCKET_READABLE EPOLLIN
  ------------------
                  return ((p->state.poll_type & POLL_TYPE_POLLING_IN) ? LIBUS_SOCKET_READABLE : 0) | ((p->state.poll_type & POLL_TYPE_POLLING_OUT) ? LIBUS_SOCKET_WRITABLE : 0);
  ------------------
  |  |   28|  11.0M|#define LIBUS_SOCKET_WRITABLE EPOLLOUT
  ------------------
  |  Branch (67:13): [True: 11.0M, False: 40.1k]
  |  Branch (67:89): [True: 838k, False: 10.2M]
  ------------------
   68|  11.0M|}
us_poll_fd:
   70|  9.88M|LIBUS_SOCKET_DESCRIPTOR us_poll_fd(struct us_poll_t *p) {
   71|  9.88M|    return p->state.fd;
   72|  9.88M|}
us_internal_poll_type:
   75|  10.6M|int us_internal_poll_type(struct us_poll_t *p) {
   76|  10.6M|    return p->state.poll_type & 3;
   77|  10.6M|}
us_internal_poll_set_type:
   80|   286k|void us_internal_poll_set_type(struct us_poll_t *p, int poll_type) {
   81|   286k|    p->state.poll_type = poll_type | (p->state.poll_type & 12);
   82|   286k|}
us_timer_ext:
   85|  1.26M|void *us_timer_ext(struct us_timer_t *timer) {
   86|  1.26M|    return ((struct us_internal_callback_t *) timer) + 1;
   87|  1.26M|}
us_create_loop:
   96|  6.41k|struct us_loop_t *us_create_loop(void *hint, void (*wakeup_cb)(struct us_loop_t *loop), void (*pre_cb)(struct us_loop_t *loop), void (*post_cb)(struct us_loop_t *loop), unsigned int ext_size) {
   97|  6.41k|    struct us_loop_t *loop = (struct us_loop_t *) malloc(sizeof(struct us_loop_t) + ext_size);
   98|  6.41k|    loop->num_polls = 0;
   99|       |    /* These could be accessed if we close a poll before starting the loop */
  100|  6.41k|    loop->num_ready_polls = 0;
  101|  6.41k|    loop->current_ready_poll = 0;
  102|       |
  103|  6.41k|#ifdef LIBUS_USE_EPOLL
  104|  6.41k|    loop->fd = epoll_create1(EPOLL_CLOEXEC);
  105|       |#else
  106|       |    loop->fd = kqueue();
  107|       |#endif
  108|       |
  109|  6.41k|    us_internal_loop_data_init(loop, wakeup_cb, pre_cb, post_cb);
  110|  6.41k|    return loop;
  111|  6.41k|}
us_loop_run:
  113|  6.41k|void us_loop_run(struct us_loop_t *loop) {
  114|  6.41k|    us_loop_integrate(loop);
  115|       |
  116|       |    /* While we have non-fallthrough polls we shouldn't fall through */
  117|  1.60M|    while (loop->num_polls) {
  ------------------
  |  Branch (117:12): [True: 1.59M, False: 6.41k]
  ------------------
  118|       |        /* Emit pre callback */
  119|  1.59M|        us_internal_loop_pre(loop);
  120|       |
  121|       |        /* Fetch ready polls */
  122|  1.59M|#ifdef LIBUS_USE_EPOLL
  123|  1.59M|        loop->num_ready_polls = epoll_wait(loop->fd, loop->ready_polls, 1024, -1);
  124|       |#else
  125|       |        loop->num_ready_polls = kevent(loop->fd, NULL, 0, loop->ready_polls, 1024, NULL);
  126|       |#endif
  127|       |
  128|       |        /* Iterate ready polls, dispatching them by type */
  129|  8.56M|        for (loop->current_ready_poll = 0; loop->current_ready_poll < loop->num_ready_polls; loop->current_ready_poll++) {
  ------------------
  |  Branch (129:44): [True: 6.96M, False: 1.59M]
  ------------------
  130|  6.96M|            struct us_poll_t *poll = GET_READY_POLL(loop, loop->current_ready_poll);
  ------------------
  |  |   28|  6.96M|#define GET_READY_POLL(loop, index) (struct us_poll_t *) loop->ready_polls[index].data.ptr
  ------------------
  131|       |            /* Any ready poll marked with nullptr will be ignored */
  132|  6.96M|            if (poll) {
  ------------------
  |  Branch (132:17): [True: 6.96M, False: 0]
  ------------------
  133|  6.96M|#ifdef LIBUS_USE_EPOLL
  134|  6.96M|                int events = loop->ready_polls[loop->current_ready_poll].events;
  135|  6.96M|                int error = loop->ready_polls[loop->current_ready_poll].events & (EPOLLERR | EPOLLHUP);
  136|       |#else
  137|       |                /* EVFILT_READ, EVFILT_TIME, EVFILT_USER are all mapped to LIBUS_SOCKET_READABLE */
  138|       |                int events = LIBUS_SOCKET_READABLE;
  139|       |                if (loop->ready_polls[loop->current_ready_poll].filter == EVFILT_WRITE) {
  140|       |                    events = LIBUS_SOCKET_WRITABLE;
  141|       |                }
  142|       |                int error = loop->ready_polls[loop->current_ready_poll].flags & (EV_ERROR | EV_EOF);
  143|       |#endif
  144|       |                /* Always filter all polls by what they actually poll for (callback polls always poll for readable) */
  145|  6.96M|                events &= us_poll_events(poll);
  146|  6.96M|                if (events || error) {
  ------------------
  |  Branch (146:21): [True: 4.83M, False: 2.13M]
  |  Branch (146:31): [True: 2.13M, False: 0]
  ------------------
  147|  6.96M|                    us_internal_dispatch_ready_poll(poll, error, events);
  148|  6.96M|                }
  149|  6.96M|            }
  150|  6.96M|        }
  151|       |        /* Emit post callback */
  152|  1.59M|        us_internal_loop_post(loop);
  153|  1.59M|    }
  154|  6.41k|}
us_internal_loop_update_pending_ready_polls:
  156|  1.76M|void us_internal_loop_update_pending_ready_polls(struct us_loop_t *loop, struct us_poll_t *old_poll, struct us_poll_t *new_poll, int old_events, int new_events) {
  157|  1.76M|#ifdef LIBUS_USE_EPOLL
  158|       |    /* Epoll only has one ready poll per poll */
  159|  1.76M|    int num_entries_possibly_remaining = 1;
  160|       |#else
  161|       |    /* Ready polls may contain same poll twice under kqueue, as one poll may hold two filters */
  162|       |    int num_entries_possibly_remaining = 2;//((old_events & LIBUS_SOCKET_READABLE) ? 1 : 0) + ((old_events & LIBUS_SOCKET_WRITABLE) ? 1 : 0);
  163|       |#endif
  164|       |
  165|       |    /* Todo: for kqueue if we track things in us_change_poll it is possible to have a fast path with no seeking in cases of:
  166|       |    * current poll being us AND we only poll for one thing */
  167|       |
  168|  3.52M|    for (int i = loop->current_ready_poll; i < loop->num_ready_polls && num_entries_possibly_remaining; i++) {
  ------------------
  |  Branch (168:44): [True: 3.47M, False: 52.3k]
  |  Branch (168:73): [True: 1.75M, False: 1.71M]
  ------------------
  169|  1.75M|        if (GET_READY_POLL(loop, i) == old_poll) {
  ------------------
  |  |   28|  1.75M|#define GET_READY_POLL(loop, index) (struct us_poll_t *) loop->ready_polls[index].data.ptr
  ------------------
  |  Branch (169:13): [True: 1.73M, False: 17.3k]
  ------------------
  170|       |
  171|       |            // if new events does not contain the ready events of this poll then remove (no we filter that out later on)
  172|  1.73M|            SET_READY_POLL(loop, i, new_poll);
  ------------------
  |  |   29|  1.73M|#define SET_READY_POLL(loop, index, poll) loop->ready_polls[index].data.ptr = poll
  ------------------
  173|       |
  174|  1.73M|            num_entries_possibly_remaining--;
  175|  1.73M|        }
  176|  1.75M|    }
  177|  1.76M|}
us_poll_resize:
  205|  40.1k|struct us_poll_t *us_poll_resize(struct us_poll_t *p, struct us_loop_t *loop, unsigned int ext_size) {
  206|  40.1k|    int events = us_poll_events(p);
  207|       |
  208|  40.1k|    struct us_poll_t *new_p = realloc(p, sizeof(struct us_poll_t) + ext_size);
  209|  40.1k|    if (p != new_p && events) {
  ------------------
  |  Branch (209:9): [True: 0, False: 40.1k]
  |  Branch (209:23): [True: 0, False: 0]
  ------------------
  210|      0|#ifdef LIBUS_USE_EPOLL
  211|       |        /* Hack: forcefully update poll by stripping away already set events */
  212|      0|        new_p->state.poll_type = us_internal_poll_type(new_p);
  213|      0|        us_poll_change(new_p, loop, events);
  214|       |#else
  215|       |        /* Forcefully update poll by resetting them with new_p as user data */
  216|       |        kqueue_change(loop->fd, new_p->state.fd, 0, events, new_p);
  217|       |#endif
  218|       |
  219|       |        /* This is needed for epoll also (us_change_poll doesn't update the old poll) */
  220|      0|        us_internal_loop_update_pending_ready_polls(loop, p, new_p, events, events);
  221|      0|    }
  222|       |
  223|  40.1k|    return new_p;
  224|  40.1k|}
us_poll_start:
  226|  1.76M|void us_poll_start(struct us_poll_t *p, struct us_loop_t *loop, int events) {
  227|  1.76M|    p->state.poll_type = us_internal_poll_type(p) | ((events & LIBUS_SOCKET_READABLE) ? POLL_TYPE_POLLING_IN : 0) | ((events & LIBUS_SOCKET_WRITABLE) ? POLL_TYPE_POLLING_OUT : 0);
  ------------------
  |  |   27|  1.76M|#define LIBUS_SOCKET_READABLE EPOLLIN
  ------------------
                  p->state.poll_type = us_internal_poll_type(p) | ((events & LIBUS_SOCKET_READABLE) ? POLL_TYPE_POLLING_IN : 0) | ((events & LIBUS_SOCKET_WRITABLE) ? POLL_TYPE_POLLING_OUT : 0);
  ------------------
  |  |   28|  1.76M|#define LIBUS_SOCKET_WRITABLE EPOLLOUT
  ------------------
  |  Branch (227:54): [True: 1.76M, False: 2.32k]
  |  Branch (227:118): [True: 2.32k, False: 1.76M]
  ------------------
  228|       |
  229|  1.76M|#ifdef LIBUS_USE_EPOLL
  230|  1.76M|    struct epoll_event event;
  231|  1.76M|    event.events = events;
  232|  1.76M|    event.data.ptr = p;
  233|  1.76M|    epoll_ctl(loop->fd, EPOLL_CTL_ADD, p->state.fd, &event);
  234|       |#else
  235|       |    kqueue_change(loop->fd, p->state.fd, 0, events, p);
  236|       |#endif
  237|  1.76M|}
us_poll_change:
  239|   752k|void us_poll_change(struct us_poll_t *p, struct us_loop_t *loop, int events) {
  240|   752k|    int old_events = us_poll_events(p);
  241|   752k|    if (old_events != events) {
  ------------------
  |  Branch (241:9): [True: 648k, False: 104k]
  ------------------
  242|       |
  243|   648k|        p->state.poll_type = us_internal_poll_type(p) | ((events & LIBUS_SOCKET_READABLE) ? POLL_TYPE_POLLING_IN : 0) | ((events & LIBUS_SOCKET_WRITABLE) ? POLL_TYPE_POLLING_OUT : 0);
  ------------------
  |  |   27|   648k|#define LIBUS_SOCKET_READABLE EPOLLIN
  ------------------
                      p->state.poll_type = us_internal_poll_type(p) | ((events & LIBUS_SOCKET_READABLE) ? POLL_TYPE_POLLING_IN : 0) | ((events & LIBUS_SOCKET_WRITABLE) ? POLL_TYPE_POLLING_OUT : 0);
  ------------------
  |  |   28|   648k|#define LIBUS_SOCKET_WRITABLE EPOLLOUT
  ------------------
  |  Branch (243:58): [True: 615k, False: 33.2k]
  |  Branch (243:122): [True: 329k, False: 319k]
  ------------------
  244|       |
  245|   648k|#ifdef LIBUS_USE_EPOLL
  246|   648k|        struct epoll_event event;
  247|   648k|        event.events = events;
  248|   648k|        event.data.ptr = p;
  249|   648k|        epoll_ctl(loop->fd, EPOLL_CTL_MOD, p->state.fd, &event);
  250|       |#else
  251|       |        kqueue_change(loop->fd, p->state.fd, old_events, events, p);
  252|       |#endif
  253|       |        /* Set all removed events to null-polls in pending ready poll list */
  254|       |        //us_internal_loop_update_pending_ready_polls(loop, p, p, old_events, events);
  255|   648k|    }
  256|   752k|}
us_poll_stop:
  258|  1.76M|void us_poll_stop(struct us_poll_t *p, struct us_loop_t *loop) {
  259|  1.76M|    int old_events = us_poll_events(p);
  260|  1.76M|    int new_events = 0;
  261|  1.76M|#ifdef LIBUS_USE_EPOLL
  262|  1.76M|    struct epoll_event event;
  263|  1.76M|    epoll_ctl(loop->fd, EPOLL_CTL_DEL, p->state.fd, &event);
  264|       |#else
  265|       |    if (old_events) {
  266|       |        kqueue_change(loop->fd, p->state.fd, old_events, new_events, NULL);
  267|       |    }
  268|       |#endif
  269|       |
  270|       |    /* Disable any instance of us in the pending ready poll list */
  271|  1.76M|    us_internal_loop_update_pending_ready_polls(loop, p, 0, old_events, new_events);
  272|  1.76M|}
us_internal_accept_poll_event:
  274|  3.85M|unsigned int us_internal_accept_poll_event(struct us_poll_t *p) {
  275|  3.85M|#ifdef LIBUS_USE_EPOLL
  276|  3.85M|    int fd = us_poll_fd(p);
  277|  3.85M|    uint64_t buf;
  278|  3.85M|    int read_length = read(fd, &buf, 8);
  279|  3.85M|    (void)read_length;
  280|  3.85M|    return buf;
  281|       |#else
  282|       |    /* Kqueue has no underlying FD for timers or user events */
  283|       |    return 0;
  284|       |#endif
  285|  3.85M|}
us_create_timer:
  289|  12.8k|struct us_timer_t *us_create_timer(struct us_loop_t *loop, int fallthrough, unsigned int ext_size) {
  290|  12.8k|    struct us_poll_t *p = us_create_poll(loop, fallthrough, sizeof(struct us_internal_callback_t) + ext_size);
  291|  12.8k|    int timerfd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC);
  292|  12.8k|    if (timerfd == -1) {
  ------------------
  |  Branch (292:9): [True: 0, False: 12.8k]
  ------------------
  293|      0|      return NULL;
  294|      0|    }
  295|  12.8k|    us_poll_init(p, timerfd, POLL_TYPE_CALLBACK);
  296|       |
  297|  12.8k|    struct us_internal_callback_t *cb = (struct us_internal_callback_t *) p;
  298|  12.8k|    cb->loop = loop;
  299|  12.8k|    cb->cb_expects_the_loop = 0;
  300|  12.8k|    cb->leave_poll_ready = 0;
  301|       |
  302|  12.8k|    return (struct us_timer_t *) cb;
  303|  12.8k|}
us_timer_close:
  325|  12.8k|void us_timer_close(struct us_timer_t *timer) {
  326|  12.8k|    struct us_internal_callback_t *cb = (struct us_internal_callback_t *) timer;
  327|       |
  328|  12.8k|    us_poll_stop(&cb->p, cb->loop);
  329|  12.8k|    close(us_poll_fd(&cb->p));
  330|       |
  331|       |    /* (regular) sockets are the only polls which are not freed immediately */
  332|  12.8k|    us_poll_free((struct us_poll_t *) timer, cb->loop);
  333|  12.8k|}
us_timer_set:
  335|  12.8k|void us_timer_set(struct us_timer_t *t, void (*cb)(struct us_timer_t *t), int ms, int repeat_ms) {
  336|  12.8k|    struct us_internal_callback_t *internal_cb = (struct us_internal_callback_t *) t;
  337|       |
  338|  12.8k|    internal_cb->cb = (void (*)(struct us_internal_callback_t *)) cb;
  339|       |
  340|  12.8k|    struct itimerspec timer_spec = {
  341|  12.8k|        {repeat_ms / 1000, (long) (repeat_ms % 1000) * (long) 1000000},
  342|  12.8k|        {ms / 1000, (long) (ms % 1000) * (long) 1000000}
  343|  12.8k|    };
  344|       |
  345|  12.8k|    timerfd_settime(us_poll_fd((struct us_poll_t *) t), 0, &timer_spec, NULL);
  346|  12.8k|    us_poll_start((struct us_poll_t *) t, internal_cb->loop, LIBUS_SOCKET_READABLE);
  ------------------
  |  |   27|  12.8k|#define LIBUS_SOCKET_READABLE EPOLLIN
  ------------------
  347|  12.8k|}
us_internal_create_async:
  374|  6.41k|struct us_internal_async *us_internal_create_async(struct us_loop_t *loop, int fallthrough, unsigned int ext_size) {
  375|  6.41k|    struct us_poll_t *p = us_create_poll(loop, fallthrough, sizeof(struct us_internal_callback_t) + ext_size);
  376|  6.41k|    us_poll_init(p, eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC), POLL_TYPE_CALLBACK);
  377|       |
  378|  6.41k|    struct us_internal_callback_t *cb = (struct us_internal_callback_t *) p;
  379|  6.41k|    cb->loop = loop;
  380|  6.41k|    cb->cb_expects_the_loop = 1;
  381|  6.41k|    cb->leave_poll_ready = 0;
  382|       |
  383|  6.41k|    return (struct us_internal_async *) cb;
  384|  6.41k|}
us_internal_async_close:
  387|  6.41k|void us_internal_async_close(struct us_internal_async *a) {
  388|  6.41k|    struct us_internal_callback_t *cb = (struct us_internal_callback_t *) a;
  389|       |
  390|  6.41k|    us_poll_stop(&cb->p, cb->loop);
  391|  6.41k|    close(us_poll_fd(&cb->p));
  392|       |
  393|       |    /* (regular) sockets are the only polls which are not freed immediately */
  394|  6.41k|    us_poll_free((struct us_poll_t *) a, cb->loop);
  395|  6.41k|}
us_internal_async_set:
  397|  6.41k|void us_internal_async_set(struct us_internal_async *a, void (*cb)(struct us_internal_async *)) {
  398|  6.41k|    struct us_internal_callback_t *internal_cb = (struct us_internal_callback_t *) a;
  399|       |
  400|  6.41k|    internal_cb->cb = (void (*)(struct us_internal_callback_t *)) cb;
  401|       |
  402|  6.41k|    us_poll_start((struct us_poll_t *) a, internal_cb->loop, LIBUS_SOCKET_READABLE);
  ------------------
  |  |   27|  6.41k|#define LIBUS_SOCKET_READABLE EPOLLIN
  ------------------
  403|  6.41k|}
us_internal_async_wakeup:
  405|  8.15k|void us_internal_async_wakeup(struct us_internal_async *a) {
  406|  8.15k|    uint64_t one = 1;
  407|  8.15k|    int written = write(us_poll_fd((struct us_poll_t *) a), &one, 8);
  408|  8.15k|    (void)written;
  409|  8.15k|}

us_internal_loop_data_init:
   26|  6.41k|    void (*pre_cb)(struct us_loop_t *loop), void (*post_cb)(struct us_loop_t *loop)) {
   27|  6.41k|    loop->data.sweep_timer = us_create_timer(loop, 1, 0);
   28|  6.41k|    loop->data.recv_buf = malloc(LIBUS_RECV_BUFFER_LENGTH + LIBUS_RECV_BUFFER_PADDING * 2);
  ------------------
  |  |   22|  6.41k|#define LIBUS_RECV_BUFFER_LENGTH 524288
  ------------------
                  loop->data.recv_buf = malloc(LIBUS_RECV_BUFFER_LENGTH + LIBUS_RECV_BUFFER_PADDING * 2);
  ------------------
  |  |   26|  6.41k|#define LIBUS_RECV_BUFFER_PADDING 32
  ------------------
   29|  6.41k|    loop->data.ssl_data = 0;
   30|  6.41k|    loop->data.head = 0;
   31|  6.41k|    loop->data.iterator = 0;
   32|  6.41k|    loop->data.closed_head = 0;
   33|  6.41k|    loop->data.low_prio_head = 0;
   34|  6.41k|    loop->data.low_prio_budget = 0;
   35|       |
   36|  6.41k|    loop->data.pre_cb = pre_cb;
   37|  6.41k|    loop->data.post_cb = post_cb;
   38|  6.41k|    loop->data.iteration_nr = 0;
   39|       |
   40|  6.41k|    loop->data.wakeup_async = us_internal_create_async(loop, 1, 0);
   41|  6.41k|    us_internal_async_set(loop->data.wakeup_async, (void (*)(struct us_internal_async *)) wakeup_cb);
   42|  6.41k|}
us_internal_loop_data_free:
   44|  6.41k|void us_internal_loop_data_free(struct us_loop_t *loop) {
   45|       |#ifndef LIBUS_NO_SSL
   46|       |    us_internal_free_loop_ssl_data(loop);
   47|       |#endif
   48|       |
   49|  6.41k|    free(loop->data.recv_buf);
   50|       |
   51|  6.41k|    us_timer_close(loop->data.sweep_timer);
   52|  6.41k|    us_internal_async_close(loop->data.wakeup_async);
   53|  6.41k|}
us_wakeup_loop:
   55|  8.15k|void us_wakeup_loop(struct us_loop_t *loop) {
   56|  8.15k|    us_internal_async_wakeup(loop->data.wakeup_async);
   57|  8.15k|}
us_internal_loop_link:
   59|  25.6k|void us_internal_loop_link(struct us_loop_t *loop, struct us_socket_context_t *context) {
   60|       |    /* Insert this context as the head of loop */
   61|  25.6k|    context->next = loop->data.head;
   62|  25.6k|    context->prev = 0;
   63|  25.6k|    if (loop->data.head) {
  ------------------
  |  Branch (63:9): [True: 19.2k, False: 6.41k]
  ------------------
   64|  19.2k|        loop->data.head->prev = context;
   65|  19.2k|    }
   66|  25.6k|    loop->data.head = context;
   67|  25.6k|}
us_internal_loop_unlink:
   70|  25.6k|void us_internal_loop_unlink(struct us_loop_t *loop, struct us_socket_context_t *context) {
   71|  25.6k|    if (loop->data.head == context) {
  ------------------
  |  Branch (71:9): [True: 12.8k, False: 12.8k]
  ------------------
   72|  12.8k|        loop->data.head = context->next;
   73|  12.8k|        if (loop->data.head) {
  ------------------
  |  Branch (73:13): [True: 6.41k, False: 6.41k]
  ------------------
   74|  6.41k|            loop->data.head->prev = 0;
   75|  6.41k|        }
   76|  12.8k|    } else {
   77|  12.8k|        context->prev->next = context->next;
   78|  12.8k|        if (context->next) {
  ------------------
  |  Branch (78:13): [True: 0, False: 12.8k]
  ------------------
   79|      0|            context->next->prev = context->prev;
   80|      0|        }
   81|  12.8k|    }
   82|  25.6k|}
us_internal_timer_sweep:
   85|  1.32M|void us_internal_timer_sweep(struct us_loop_t *loop) {
   86|  1.32M|    struct us_internal_loop_data_t *loop_data = &loop->data;
   87|       |    /* For all socket contexts in this loop */
   88|  6.63M|    for (loop_data->iterator = loop_data->head; loop_data->iterator; loop_data->iterator = loop_data->iterator->next) {
  ------------------
  |  Branch (88:49): [True: 5.30M, False: 1.32M]
  ------------------
   89|       |
   90|  5.30M|        struct us_socket_context_t *context = loop_data->iterator;
   91|       |
   92|       |        /* Update this context's timestamps (this could be moved to loop and done once) */
   93|  5.30M|        context->global_tick++;
   94|  5.30M|        unsigned char short_ticks = context->timestamp = context->global_tick % 240;
   95|  5.30M|        unsigned char long_ticks = context->long_timestamp = (context->global_tick / 15) % 240;
   96|       |
   97|       |        /* Begin at head */
   98|  5.30M|        struct us_socket_t *s = context->head_sockets;
   99|  5.31M|        while (s) {
  ------------------
  |  Branch (99:16): [True: 151k, False: 5.16M]
  ------------------
  100|       |            /* Seek until end or timeout found (tightest loop) */
  101|   304k|            while (1) {
  ------------------
  |  Branch (101:20): [Folded - Ignored]
  ------------------
  102|       |                /* We only read from 1 random cache line here */
  103|   304k|                if (short_ticks == s->timeout || long_ticks == s->long_timeout) {
  ------------------
  |  Branch (103:21): [True: 7.47k, False: 297k]
  |  Branch (103:50): [True: 0, False: 297k]
  ------------------
  104|  7.47k|                    break;
  105|  7.47k|                }
  106|       |
  107|       |                /* Did we reach the end without a find? */
  108|   297k|                if ((s = s->next) == 0) {
  ------------------
  |  Branch (108:21): [True: 143k, False: 153k]
  ------------------
  109|   143k|                    goto next_context;
  110|   143k|                }
  111|   297k|            }
  112|       |
  113|       |            /* Here we have a timeout to emit (slow path) */
  114|  7.47k|            context->iterator = s;
  115|       |
  116|  7.47k|            if (short_ticks == s->timeout) {
  ------------------
  |  Branch (116:17): [True: 7.47k, False: 0]
  ------------------
  117|  7.47k|                s->timeout = 255;
  118|  7.47k|                context->on_socket_timeout(s);
  119|  7.47k|            }
  120|       |
  121|  7.47k|            if (context->iterator == s && long_ticks == s->long_timeout) {
  ------------------
  |  Branch (121:17): [True: 2.15k, False: 5.31k]
  |  Branch (121:43): [True: 0, False: 2.15k]
  ------------------
  122|      0|                s->long_timeout = 255;
  123|      0|                context->on_socket_long_timeout(s);
  124|      0|            }   
  125|       |
  126|       |            /* Check for unlink / link (if the event handler did not modify the chain, we step 1) */
  127|  7.47k|            if (s == context->iterator) {
  ------------------
  |  Branch (127:17): [True: 2.15k, False: 5.31k]
  ------------------
  128|  2.15k|                s = s->next;
  129|  5.31k|            } else {
  130|       |                /* The iterator was changed by event handler */
  131|  5.31k|                s = context->iterator;
  132|  5.31k|            }
  133|  7.47k|        }
  134|       |        /* We always store a 0 to context->iterator here since we are no longer iterating this context */
  135|  5.30M|        next_context:
  136|  5.30M|        context->iterator = 0;
  137|  5.30M|    }
  138|  1.32M|}
us_internal_handle_low_priority_sockets:
  145|  1.59M|void us_internal_handle_low_priority_sockets(struct us_loop_t *loop) {
  146|  1.59M|    struct us_internal_loop_data_t *loop_data = &loop->data;
  147|  1.59M|    struct us_socket_t *s;
  148|       |
  149|  1.59M|    loop_data->low_prio_budget = MAX_LOW_PRIO_SOCKETS_PER_LOOP_ITERATION;
  150|       |
  151|  1.59M|    for (s = loop_data->low_prio_head; s && loop_data->low_prio_budget > 0; s = loop_data->low_prio_head, loop_data->low_prio_budget--) {
  ------------------
  |  Branch (151:40): [True: 0, False: 1.59M]
  |  Branch (151:45): [True: 0, False: 0]
  ------------------
  152|       |        /* Unlink this socket from the low-priority queue */
  153|      0|        loop_data->low_prio_head = s->next;
  154|      0|        if (s->next) s->next->prev = 0;
  ------------------
  |  Branch (154:13): [True: 0, False: 0]
  ------------------
  155|      0|        s->next = 0;
  156|       |
  157|      0|        us_internal_socket_context_link_socket(s->context, s);
  158|      0|        us_poll_change(&s->p, us_socket_context(0, s)->loop, us_poll_events(&s->p) | LIBUS_SOCKET_READABLE);
  ------------------
  |  |   27|      0|#define LIBUS_SOCKET_READABLE EPOLLIN
  ------------------
  159|       |
  160|      0|        s->low_prio_state = 2;
  161|      0|    }
  162|  1.59M|}
us_internal_free_closed_sockets:
  165|  1.59M|void us_internal_free_closed_sockets(struct us_loop_t *loop) {
  166|       |    /* Free all closed sockets (maybe it is better to reverse order?) */
  167|  1.59M|    if (loop->data.closed_head) {
  ------------------
  |  Branch (167:9): [True: 221k, False: 1.37M]
  ------------------
  168|  1.96M|        for (struct us_socket_t *s = loop->data.closed_head; s; ) {
  ------------------
  |  Branch (168:62): [True: 1.74M, False: 221k]
  ------------------
  169|  1.74M|            struct us_socket_t *next = s->next;
  170|  1.74M|            us_poll_free((struct us_poll_t *) s, loop);
  171|  1.74M|            s = next;
  172|  1.74M|        }
  173|   221k|        loop->data.closed_head = 0;
  174|   221k|    }
  175|  1.59M|}
sweep_timer_cb:
  177|  1.32M|void sweep_timer_cb(struct us_internal_callback_t *cb) {
  178|  1.32M|    us_internal_timer_sweep(cb->loop);
  179|  1.32M|}
us_loop_iteration_number:
  181|  6.41k|long long us_loop_iteration_number(struct us_loop_t *loop) {
  182|  6.41k|    return loop->data.iteration_nr;
  183|  6.41k|}
us_internal_loop_pre:
  186|  1.59M|void us_internal_loop_pre(struct us_loop_t *loop) {
  187|  1.59M|    loop->data.iteration_nr++;
  188|  1.59M|    us_internal_handle_low_priority_sockets(loop);
  189|  1.59M|    loop->data.pre_cb(loop);
  190|  1.59M|}
us_internal_loop_post:
  192|  1.59M|void us_internal_loop_post(struct us_loop_t *loop) {
  193|  1.59M|    us_internal_free_closed_sockets(loop);
  194|  1.59M|    loop->data.post_cb(loop);
  195|  1.59M|}
us_adopt_accepted_socket:
  198|  1.74M|    unsigned int socket_ext_size, char *addr_ip, int addr_ip_length) {
  199|       |#ifndef LIBUS_NO_SSL
  200|       |    if (ssl) {
  201|       |        return (struct us_socket_t *)us_internal_ssl_adopt_accepted_socket((struct us_internal_ssl_socket_context_t *)context, accepted_fd,
  202|       |            socket_ext_size, addr_ip, addr_ip_length);
  203|       |    }
  204|       |#endif
  205|  1.74M|    struct us_poll_t *accepted_p = us_create_poll(context->loop, 0, sizeof(struct us_socket_t) - sizeof(struct us_poll_t) + socket_ext_size);
  206|  1.74M|    us_poll_init(accepted_p, accepted_fd, POLL_TYPE_SOCKET);
  207|  1.74M|    us_poll_start(accepted_p, context->loop, LIBUS_SOCKET_READABLE);
  ------------------
  |  |   27|  1.74M|#define LIBUS_SOCKET_READABLE EPOLLIN
  ------------------
  208|       |
  209|  1.74M|    struct us_socket_t *s = (struct us_socket_t *) accepted_p;
  210|       |
  211|  1.74M|    s->context = context;
  212|  1.74M|    s->timeout = 255;
  213|  1.74M|    s->long_timeout = 255;
  214|  1.74M|    s->low_prio_state = 0;
  215|       |
  216|       |    /* We always use nodelay */
  217|  1.74M|    bsd_socket_nodelay(accepted_fd, 1);
  218|       |
  219|  1.74M|    us_internal_socket_context_link_socket(context, s);
  220|       |
  221|  1.74M|    context->on_open(s, 0, addr_ip, addr_ip_length);
  222|  1.74M|    return s;
  223|  1.74M|}
us_internal_dispatch_ready_poll:
  225|  6.96M|void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error, int events) {
  226|  6.96M|    switch (us_internal_poll_type(p)) {
  ------------------
  |  Branch (226:13): [True: 0, False: 6.96M]
  ------------------
  227|  3.85M|    case POLL_TYPE_CALLBACK: {
  ------------------
  |  Branch (227:5): [True: 3.85M, False: 3.11M]
  ------------------
  228|  3.85M|            struct us_internal_callback_t *cb = (struct us_internal_callback_t *) p;
  229|       |            /* Timers, asyncs should accept (read), while UDP sockets should obviously not */
  230|  3.85M|            if (!cb->leave_poll_ready) {
  ------------------
  |  Branch (230:17): [True: 3.85M, False: 0]
  ------------------
  231|       |                /* Let's just have this macro to silence the CodeQL alert regarding empty function when using libuv */
  232|  3.85M|    #ifndef LIBUS_USE_LIBUV
  233|  3.85M|                us_internal_accept_poll_event(p);
  234|  3.85M|    #endif
  235|  3.85M|            }
  236|  3.85M|            cb->cb(cb->cb_expects_the_loop ? (struct us_internal_callback_t *) cb->loop : (struct us_internal_callback_t *) &cb->p);
  ------------------
  |  Branch (236:20): [True: 1.26M, False: 2.58M]
  ------------------
  237|  3.85M|        }
  238|  3.85M|        break;
  239|  1.22M|    case POLL_TYPE_SEMI_SOCKET: {
  ------------------
  |  Branch (239:5): [True: 1.22M, False: 5.74M]
  ------------------
  240|       |            /* Both connect and listen sockets are semi-sockets
  241|       |             * but they poll for different events */
  242|  1.22M|            if (us_poll_events(p) == LIBUS_SOCKET_WRITABLE) {
  ------------------
  |  |   28|  1.22M|#define LIBUS_SOCKET_WRITABLE EPOLLOUT
  ------------------
  |  Branch (242:17): [True: 2.27k, False: 1.22M]
  ------------------
  243|  2.27k|                struct us_socket_t *s = (struct us_socket_t *) p;
  244|       |
  245|       |                /* It is perfectly possible to come here with an error */
  246|  2.27k|                if (error) {
  ------------------
  |  Branch (246:21): [True: 2.02k, False: 255]
  ------------------
  247|       |                    /* Emit error, close without emitting on_close */
  248|  2.02k|                    s->context->on_connect_error(s, 0);
  249|  2.02k|                    us_socket_close_connecting(0, s);
  250|  2.02k|                } else {
  251|       |                    /* All sockets poll for readable */
  252|    255|                    us_poll_change(p, s->context->loop, LIBUS_SOCKET_READABLE);
  ------------------
  |  |   27|    255|#define LIBUS_SOCKET_READABLE EPOLLIN
  ------------------
  253|       |
  254|       |                    /* We always use nodelay */
  255|    255|                    bsd_socket_nodelay(us_poll_fd(p), 1);
  256|       |
  257|       |                    /* We are now a proper socket */
  258|    255|                    us_internal_poll_set_type(p, POLL_TYPE_SOCKET);
  259|       |
  260|       |                    /* If we used a connection timeout we have to reset it here */
  261|    255|                    us_socket_timeout(0, s, 0);
  262|       |
  263|    255|                    s->context->on_open(s, 1, 0, 0);
  264|    255|                }
  265|  1.22M|            } else {
  266|  1.22M|                struct us_listen_socket_t *listen_socket = (struct us_listen_socket_t *) p;
  267|  1.22M|                struct bsd_addr_t addr;
  268|       |
  269|  1.22M|                LIBUS_SOCKET_DESCRIPTOR client_fd = bsd_accept_socket(us_poll_fd(p), &addr);
  ------------------
  |  |   38|  1.22M|#define LIBUS_SOCKET_DESCRIPTOR int
  ------------------
  270|  1.22M|                if (client_fd == LIBUS_SOCKET_ERROR) {
  ------------------
  |  |   44|  1.22M|#define LIBUS_SOCKET_ERROR -1
  ------------------
  |  Branch (270:21): [True: 1.03M, False: 184k]
  ------------------
  271|       |                    /* Todo: start timer here */
  272|       |
  273|  1.03M|                } else {
  274|       |
  275|       |                    /* Todo: stop timer if any */
  276|       |
  277|  1.74M|                    do {
  278|  1.74M|                        struct us_socket_context_t *context = us_socket_context(0, &listen_socket->s);
  279|       |                        /* See if we want to export the FD or keep it here (this event can be unset) */
  280|  1.74M|                        if (context->on_pre_open == 0 || context->on_pre_open(client_fd) == client_fd) {
  ------------------
  |  Branch (280:29): [True: 1.74M, False: 0]
  |  Branch (280:58): [True: 0, False: 0]
  ------------------
  281|       |
  282|       |                            /* Adopt the newly accepted socket */
  283|  1.74M|                            us_adopt_accepted_socket(0, context,
  284|  1.74M|                                client_fd, listen_socket->socket_ext_size, bsd_addr_get_ip(&addr), bsd_addr_get_ip_length(&addr));
  285|       |
  286|       |                            /* Exit accept loop if listen socket was closed in on_open handler */
  287|  1.74M|                            if (us_socket_is_closed(0, &listen_socket->s)) {
  ------------------
  |  Branch (287:33): [True: 0, False: 1.74M]
  ------------------
  288|      0|                                break;
  289|      0|                            }
  290|       |
  291|  1.74M|                        }
  292|       |
  293|  1.74M|                    } while ((client_fd = bsd_accept_socket(us_poll_fd(p), &addr)) != LIBUS_SOCKET_ERROR);
  ------------------
  |  |   44|  1.74M|#define LIBUS_SOCKET_ERROR -1
  ------------------
  |  Branch (293:30): [True: 1.55M, False: 184k]
  ------------------
  294|   184k|                }
  295|  1.22M|            }
  296|  1.22M|        }
  297|      0|        break;
  298|  1.74k|    case POLL_TYPE_SOCKET_SHUT_DOWN:
  ------------------
  |  Branch (298:5): [True: 1.74k, False: 6.96M]
  ------------------
  299|  1.89M|    case POLL_TYPE_SOCKET: {
  ------------------
  |  Branch (299:5): [True: 1.89M, False: 5.07M]
  ------------------
  300|       |            /* We should only use s, no p after this point */
  301|  1.89M|            struct us_socket_t *s = (struct us_socket_t *) p;
  302|       |
  303|       |            /* Such as epollerr epollhup */
  304|  1.89M|            if (error) {
  ------------------
  |  Branch (304:17): [True: 1.40M, False: 486k]
  ------------------
  305|       |                /* Todo: decide what code we give here */
  306|  1.40M|                s = us_socket_close(0, s, 0, NULL);
  307|  1.40M|                return;
  308|  1.40M|            }
  309|       |
  310|   486k|            if (events & LIBUS_SOCKET_WRITABLE) {
  ------------------
  |  |   28|   486k|#define LIBUS_SOCKET_WRITABLE EPOLLOUT
  ------------------
  |  Branch (310:17): [True: 12.3k, False: 474k]
  ------------------
  311|       |                /* Note: if we failed a write as a socket of one loop then adopted
  312|       |                 * to another loop, this will be wrong. Absurd case though */
  313|  12.3k|                s->context->loop->data.last_write_failed = 0;
  314|       |
  315|  12.3k|                s = s->context->on_writable(s);
  316|       |
  317|  12.3k|                if (us_socket_is_closed(0, s)) {
  ------------------
  |  Branch (317:21): [True: 224, False: 12.1k]
  ------------------
  318|    224|                    return;
  319|    224|                }
  320|       |
  321|       |                /* If we have no failed write or if we shut down, then stop polling for more writable */
  322|  12.1k|                if (!s->context->loop->data.last_write_failed || us_socket_is_shut_down(0, s)) {
  ------------------
  |  Branch (322:21): [True: 3.67k, False: 8.48k]
  |  Branch (322:66): [True: 0, False: 8.48k]
  ------------------
  323|  3.67k|                    us_poll_change(&s->p, us_socket_context(0, s)->loop, us_poll_events(&s->p) & LIBUS_SOCKET_READABLE);
  ------------------
  |  |   27|  3.67k|#define LIBUS_SOCKET_READABLE EPOLLIN
  ------------------
  324|  3.67k|                }
  325|  12.1k|            }
  326|       |
  327|   486k|            if (events & LIBUS_SOCKET_READABLE) {
  ------------------
  |  |   27|   486k|#define LIBUS_SOCKET_READABLE EPOLLIN
  ------------------
  |  Branch (327:17): [True: 479k, False: 7.17k]
  ------------------
  328|       |                /* Contexts may prioritize down sockets that are currently readable, e.g. when SSL handshake has to be done.
  329|       |                 * SSL handshakes are CPU intensive, so we limit the number of handshakes per loop iteration, and move the rest
  330|       |                 * to the low-priority queue */
  331|   479k|                if (s->context->is_low_prio(s)) {
  ------------------
  |  Branch (331:21): [True: 0, False: 479k]
  ------------------
  332|      0|                    if (s->low_prio_state == 2) {
  ------------------
  |  Branch (332:25): [True: 0, False: 0]
  ------------------
  333|      0|                        s->low_prio_state = 0; /* Socket has been delayed and now it's time to process incoming data for one iteration */
  334|      0|                    } else if (s->context->loop->data.low_prio_budget > 0) {
  ------------------
  |  Branch (334:32): [True: 0, False: 0]
  ------------------
  335|      0|                        s->context->loop->data.low_prio_budget--; /* Still having budget for this iteration - do normal processing */
  336|      0|                    } else {
  337|      0|                        us_poll_change(&s->p, us_socket_context(0, s)->loop, us_poll_events(&s->p) & LIBUS_SOCKET_WRITABLE);
  ------------------
  |  |   28|      0|#define LIBUS_SOCKET_WRITABLE EPOLLOUT
  ------------------
  338|      0|                        us_internal_socket_context_unlink_socket(s->context, s);
  339|       |
  340|       |                        /* Link this socket to the low-priority queue - we use a LIFO queue, to prioritize newer clients that are
  341|       |                         * maybe not already timeouted - sounds unfair, but works better in real-life with smaller client-timeouts
  342|       |                         * under high load */
  343|      0|                        s->prev = 0;
  344|      0|                        s->next = s->context->loop->data.low_prio_head;
  345|      0|                        if (s->next) s->next->prev = s;
  ------------------
  |  Branch (345:29): [True: 0, False: 0]
  ------------------
  346|      0|                        s->context->loop->data.low_prio_head = s;
  347|       |
  348|      0|                        s->low_prio_state = 1;
  349|       |
  350|      0|                        break;
  351|      0|                    }
  352|      0|                }
  353|       |
  354|   479k|                int length;
  355|   479k|                read_more:
  356|   479k|                length = bsd_recv(us_poll_fd(&s->p), s->context->loop->data.recv_buf + LIBUS_RECV_BUFFER_PADDING, LIBUS_RECV_BUFFER_LENGTH, 0);
  ------------------
  |  |   26|   479k|#define LIBUS_RECV_BUFFER_PADDING 32
  ------------------
                              length = bsd_recv(us_poll_fd(&s->p), s->context->loop->data.recv_buf + LIBUS_RECV_BUFFER_PADDING, LIBUS_RECV_BUFFER_LENGTH, 0);
  ------------------
  |  |   22|   479k|#define LIBUS_RECV_BUFFER_LENGTH 524288
  ------------------
  357|   479k|                if (length > 0) {
  ------------------
  |  Branch (357:21): [True: 441k, False: 37.7k]
  ------------------
  358|   441k|                    s = s->context->on_data(s, s->context->loop->data.recv_buf + LIBUS_RECV_BUFFER_PADDING, length);
  ------------------
  |  |   26|   441k|#define LIBUS_RECV_BUFFER_PADDING 32
  ------------------
  359|       |
  360|       |                    /* If we filled the entire recv buffer, we need to immediately read again since otherwise a
  361|       |                     * pending hangup event in the same even loop iteration can close the socket before we get
  362|       |                     * the chance to read again next iteration */
  363|   441k|                    if (length == LIBUS_RECV_BUFFER_LENGTH && s && !us_socket_is_closed(0, s)) {
  ------------------
  |  |   22|   882k|#define LIBUS_RECV_BUFFER_LENGTH 524288
  ------------------
  |  Branch (363:25): [True: 0, False: 441k]
  |  Branch (363:63): [True: 0, False: 0]
  |  Branch (363:68): [True: 0, False: 0]
  ------------------
  364|      0|                        goto read_more;
  365|      0|                    }
  366|       |
  367|   441k|                } else if (!length) {
  ------------------
  |  Branch (367:28): [True: 33.4k, False: 4.31k]
  ------------------
  368|  33.4k|                    if (us_socket_is_shut_down(0, s)) {
  ------------------
  |  Branch (368:25): [True: 200, False: 33.2k]
  ------------------
  369|       |                        /* We got FIN back after sending it */
  370|       |                        /* Todo: We should give "CLEAN SHUTDOWN" as reason here */
  371|    200|                        s = us_socket_close(0, s, 0, NULL);
  372|  33.2k|                    } else {
  373|       |                        /* We got FIN, so stop polling for readable */
  374|  33.2k|                        us_poll_change(&s->p, us_socket_context(0, s)->loop, us_poll_events(&s->p) & LIBUS_SOCKET_WRITABLE);
  ------------------
  |  |   28|  33.2k|#define LIBUS_SOCKET_WRITABLE EPOLLOUT
  ------------------
  375|  33.2k|                        s = s->context->on_end(s);
  376|  33.2k|                    }
  377|  33.4k|                } else if (length == LIBUS_SOCKET_ERROR && !bsd_would_block()) {
  ------------------
  |  |   44|  8.62k|#define LIBUS_SOCKET_ERROR -1
  ------------------
  |  Branch (377:28): [True: 4.31k, False: 0]
  |  Branch (377:60): [True: 0, False: 4.31k]
  ------------------
  378|       |                    /* Todo: decide also here what kind of reason we should give */
  379|      0|                    s = us_socket_close(0, s, 0, NULL);
  380|      0|                }
  381|   479k|            }
  382|   486k|        }
  383|   486k|        break;
  384|  6.96M|    }
  385|  6.96M|}
us_loop_integrate:
  388|  6.41k|void us_loop_integrate(struct us_loop_t *loop) {
  389|  6.41k|    us_timer_set(loop->data.sweep_timer, (void (*)(struct us_timer_t *)) sweep_timer_cb, LIBUS_TIMEOUT_GRANULARITY * 1000, LIBUS_TIMEOUT_GRANULARITY * 1000);
  ------------------
  |  |   24|  6.41k|#define LIBUS_TIMEOUT_GRANULARITY 4
  ------------------
                  us_timer_set(loop->data.sweep_timer, (void (*)(struct us_timer_t *)) sweep_timer_cb, LIBUS_TIMEOUT_GRANULARITY * 1000, LIBUS_TIMEOUT_GRANULARITY * 1000);
  ------------------
  |  |   24|  6.41k|#define LIBUS_TIMEOUT_GRANULARITY 4
  ------------------
  390|  6.41k|}
us_loop_ext:
  392|  7.62M|void *us_loop_ext(struct us_loop_t *loop) {
  393|  7.62M|    return loop + 1;
  394|  7.62M|}

us_socket_local_port:
   28|  2.32k|int us_socket_local_port(int ssl, struct us_socket_t *s) {
   29|  2.32k|    struct bsd_addr_t addr;
   30|  2.32k|    if (bsd_local_addr(us_poll_fd(&s->p), &addr)) {
  ------------------
  |  Branch (30:9): [True: 2.32k, False: 0]
  ------------------
   31|  2.32k|        return -1;
   32|  2.32k|    } else {
   33|      0|        return bsd_addr_get_port(&addr);
   34|      0|    }
   35|  2.32k|}
us_socket_shutdown_read:
   46|    852|void us_socket_shutdown_read(int ssl, struct us_socket_t *s) {
   47|       |    /* This syscall is idempotent so no extra check is needed */
   48|    852|    bsd_shutdown_socket_read(us_poll_fd((struct us_poll_t *) s));
   49|    852|}
us_socket_remote_address:
   51|  39.0k|void us_socket_remote_address(int ssl, struct us_socket_t *s, char *buf, int *length) {
   52|  39.0k|    struct bsd_addr_t addr;
   53|  39.0k|    if (bsd_remote_addr(us_poll_fd(&s->p), &addr) || *length < bsd_addr_get_ip_length(&addr)) {
  ------------------
  |  Branch (53:9): [True: 0, False: 39.0k]
  |  Branch (53:54): [True: 0, False: 39.0k]
  ------------------
   54|      0|        *length = 0;
   55|  39.0k|    } else {
   56|  39.0k|        *length = bsd_addr_get_ip_length(&addr);
   57|  39.0k|        memcpy(buf, bsd_addr_get_ip(&addr), *length);
   58|  39.0k|    }
   59|  39.0k|}
us_socket_context:
   61|  9.05M|struct us_socket_context_t *us_socket_context(int ssl, struct us_socket_t *s) {
   62|  9.05M|    return s->context;
   63|  9.05M|}
us_socket_timeout:
   65|  2.02M|void us_socket_timeout(int ssl, struct us_socket_t *s, unsigned int seconds) {
   66|  2.02M|    if (seconds) {
  ------------------
  |  Branch (66:9): [True: 1.96M, False: 63.8k]
  ------------------
   67|  1.96M|        s->timeout = ((unsigned int)s->context->timestamp + ((seconds + 3) >> 2)) % 240;
   68|  1.96M|    } else {
   69|  63.8k|        s->timeout = 255;
   70|  63.8k|    }
   71|  2.02M|}
us_socket_long_timeout:
   73|  40.1k|void us_socket_long_timeout(int ssl, struct us_socket_t *s, unsigned int minutes) {
   74|  40.1k|    if (minutes) {
  ------------------
  |  Branch (74:9): [True: 0, False: 40.1k]
  ------------------
   75|      0|        s->long_timeout = ((unsigned int)s->context->long_timestamp + minutes) % 240;
   76|  40.1k|    } else {
   77|  40.1k|        s->long_timeout = 255;
   78|  40.1k|    }
   79|  40.1k|}
us_socket_flush:
   81|    255|void us_socket_flush(int ssl, struct us_socket_t *s) {
   82|    255|    if (!us_socket_is_shut_down(0, s)) {
  ------------------
  |  Branch (82:9): [True: 255, False: 0]
  ------------------
   83|    255|        bsd_socket_flush(us_poll_fd((struct us_poll_t *) s));
   84|    255|    }
   85|    255|}
us_socket_is_closed:
   87|  6.09M|int us_socket_is_closed(int ssl, struct us_socket_t *s) {
   88|  6.09M|    return s->prev == (struct us_socket_t *) s->context;
   89|  6.09M|}
us_socket_is_established:
   91|  2.32k|int us_socket_is_established(int ssl, struct us_socket_t *s) {
   92|       |    /* Everything that is not POLL_TYPE_SEMI_SOCKET is established */
   93|  2.32k|    return us_internal_poll_type((struct us_poll_t *) s) != POLL_TYPE_SEMI_SOCKET;
   94|  2.32k|}
us_socket_close_connecting:
   97|  2.02k|struct us_socket_t *us_socket_close_connecting(int ssl, struct us_socket_t *s) {
   98|  2.02k|    if (!us_socket_is_closed(0, s)) {
  ------------------
  |  Branch (98:9): [True: 2.02k, False: 0]
  ------------------
   99|  2.02k|        us_internal_socket_context_unlink_socket(s->context, s);
  100|  2.02k|        us_poll_stop((struct us_poll_t *) s, s->context->loop);
  101|  2.02k|        bsd_close_socket(us_poll_fd((struct us_poll_t *) s));
  102|       |
  103|       |        /* Link this socket to the close-list and let it be deleted after this iteration */
  104|  2.02k|        s->next = s->context->loop->data.closed_head;
  105|  2.02k|        s->context->loop->data.closed_head = s;
  106|       |
  107|       |        /* Any socket with prev = context is marked as closed */
  108|  2.02k|        s->prev = (struct us_socket_t *) s->context;
  109|       |
  110|       |        //return s->context->on_close(s, code, reason);
  111|  2.02k|    }
  112|  2.02k|    return s;
  113|  2.02k|}
us_socket_close:
  116|  1.74M|struct us_socket_t *us_socket_close(int ssl, struct us_socket_t *s, int code, void *reason) {
  117|  1.74M|    if (!us_socket_is_closed(0, s)) {
  ------------------
  |  Branch (117:9): [True: 1.74M, False: 0]
  ------------------
  118|  1.74M|        if (s->low_prio_state == 1) {
  ------------------
  |  Branch (118:13): [True: 0, False: 1.74M]
  ------------------
  119|       |            /* Unlink this socket from the low-priority queue */
  120|      0|            if (!s->prev) s->context->loop->data.low_prio_head = s->next;
  ------------------
  |  Branch (120:17): [True: 0, False: 0]
  ------------------
  121|      0|            else s->prev->next = s->next;
  122|       |
  123|      0|            if (s->next) s->next->prev = s->prev;
  ------------------
  |  Branch (123:17): [True: 0, False: 0]
  ------------------
  124|       |
  125|      0|            s->prev = 0;
  126|      0|            s->next = 0;
  127|      0|            s->low_prio_state = 0;
  128|  1.74M|        } else {
  129|  1.74M|            us_internal_socket_context_unlink_socket(s->context, s);
  130|  1.74M|        }
  131|  1.74M|        us_poll_stop((struct us_poll_t *) s, s->context->loop);
  132|  1.74M|        bsd_close_socket(us_poll_fd((struct us_poll_t *) s));
  133|       |
  134|       |        /* Link this socket to the close-list and let it be deleted after this iteration */
  135|  1.74M|        s->next = s->context->loop->data.closed_head;
  136|  1.74M|        s->context->loop->data.closed_head = s;
  137|       |
  138|       |        /* Any socket with prev = context is marked as closed */
  139|  1.74M|        s->prev = (struct us_socket_t *) s->context;
  140|       |
  141|  1.74M|        return s->context->on_close(s, code, reason);
  142|  1.74M|    }
  143|      0|    return s;
  144|  1.74M|}
us_socket_get_native_handle:
  148|  39.0k|void *us_socket_get_native_handle(int ssl, struct us_socket_t *s) {
  149|       |#ifndef LIBUS_NO_SSL
  150|       |    if (ssl) {
  151|       |        return us_internal_ssl_socket_get_native_handle((struct us_internal_ssl_socket_t *) s);
  152|       |    }
  153|       |#endif
  154|       |
  155|  39.0k|    return (void *) (uintptr_t) us_poll_fd((struct us_poll_t *) s);
  156|  39.0k|}
us_socket_write:
  173|   438k|int us_socket_write(int ssl, struct us_socket_t *s, const char *data, int length, int msg_more) {
  174|       |#ifndef LIBUS_NO_SSL
  175|       |    if (ssl) {
  176|       |        return us_internal_ssl_socket_write((struct us_internal_ssl_socket_t *) s, data, length, msg_more);
  177|       |    }
  178|       |#endif
  179|       |
  180|   438k|    if (us_socket_is_closed(ssl, s) || us_socket_is_shut_down(ssl, s)) {
  ------------------
  |  Branch (180:9): [True: 0, False: 438k]
  |  Branch (180:40): [True: 0, False: 438k]
  ------------------
  181|      0|        return 0;
  182|      0|    }
  183|       |
  184|   438k|    int written = bsd_send(us_poll_fd(&s->p), data, length, msg_more);
  185|   438k|    if (written != length) {
  ------------------
  |  Branch (185:9): [True: 429k, False: 9.14k]
  ------------------
  186|   429k|        s->context->loop->data.last_write_failed = 1;
  187|   429k|        us_poll_change(&s->p, s->context->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
  ------------------
  |  |   27|   429k|#define LIBUS_SOCKET_READABLE EPOLLIN
  ------------------
                      us_poll_change(&s->p, s->context->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
  ------------------
  |  |   28|   429k|#define LIBUS_SOCKET_WRITABLE EPOLLOUT
  ------------------
  188|   429k|    }
  189|       |
  190|   438k|    return written < 0 ? 0 : written;
  ------------------
  |  Branch (190:12): [True: 10.6k, False: 427k]
  ------------------
  191|   438k|}
us_socket_ext:
  193|  6.37M|void *us_socket_ext(int ssl, struct us_socket_t *s) {
  194|       |#ifndef LIBUS_NO_SSL
  195|       |    if (ssl) {
  196|       |        return us_internal_ssl_socket_ext((struct us_internal_ssl_socket_t *) s);
  197|       |    }
  198|       |#endif
  199|       |
  200|  6.37M|    return s + 1;
  201|  6.37M|}
us_socket_is_shut_down:
  203|  1.21M|int us_socket_is_shut_down(int ssl, struct us_socket_t *s) {
  204|       |#ifndef LIBUS_NO_SSL
  205|       |    if (ssl) {
  206|       |        return us_internal_ssl_socket_is_shut_down((struct us_internal_ssl_socket_t *) s);
  207|       |    }
  208|       |#endif
  209|       |
  210|  1.21M|    return us_internal_poll_type(&s->p) == POLL_TYPE_SOCKET_SHUT_DOWN;
  211|  1.21M|}
us_socket_shutdown:
  213|   286k|void us_socket_shutdown(int ssl, struct us_socket_t *s) {
  214|       |#ifndef LIBUS_NO_SSL
  215|       |    if (ssl) {
  216|       |        us_internal_ssl_socket_shutdown((struct us_internal_ssl_socket_t *) s);
  217|       |        return;
  218|       |    }
  219|       |#endif
  220|       |
  221|       |    /* Todo: should we emit on_close if calling shutdown on an already half-closed socket?
  222|       |     * We need more states in that case, we need to track RECEIVED_FIN
  223|       |     * so far, the app has to track this and call close as needed */
  224|   286k|    if (!us_socket_is_closed(ssl, s) && !us_socket_is_shut_down(ssl, s)) {
  ------------------
  |  Branch (224:9): [True: 286k, False: 0]
  |  Branch (224:41): [True: 286k, False: 0]
  ------------------
  225|   286k|        us_internal_poll_set_type(&s->p, POLL_TYPE_SOCKET_SHUT_DOWN);
  226|   286k|        us_poll_change(&s->p, s->context->loop, us_poll_events(&s->p) & LIBUS_SOCKET_READABLE);
  ------------------
  |  |   27|   286k|#define LIBUS_SOCKET_READABLE EPOLLIN
  ------------------
  227|   286k|        bsd_shutdown_socket(us_poll_fd((struct us_poll_t *) s));
  228|   286k|    }
  229|   286k|}

_Z4testv:
   11|  6.41k|void test() {
   12|       |	/* ws->getUserData returns one of these */
   13|  6.41k|    struct PerSocketData {
   14|       |        /* Fill with user data */
   15|  6.41k|    };
   16|       |
   17|  6.41k|    {
   18|       |        /* Keep in mind that uWS::SSLApp({options}) is the same as uWS::App() when compiled without SSL support.
   19|       |        * You may swap to using uWS:App() if you don't need SSL */
   20|  6.41k|        auto app = uWS::App({
   21|       |            /* There are example certificates in uWebSockets.js repo */
   22|  6.41k|            .key_file_name = "../misc/key.pem",
   23|  6.41k|            .cert_file_name = "../misc/cert.pem",
   24|  6.41k|            .passphrase = "1234"
   25|  6.41k|        }).ws<PerSocketData>("/empty", {
   26|       |        /* Having no handlers here should not crash */
   27|  6.41k|        }).get("/*", [](auto *res, auto *req) {
   28|  6.41k|            if (req->getHeader("write").length()) {
   29|  6.41k|                res->writeStatus("200 OK")->writeHeader("write", "true")->write("Hello");
   30|  6.41k|                res->write(" world!");
   31|  6.41k|                res->end();
   32|  6.41k|            } else if (req->getQuery().length()) {
   33|  6.41k|                res->close();
   34|  6.41k|            } else {
   35|  6.41k|                res->end("Hello world!");
   36|  6.41k|            }
   37|  6.41k|        }).post("/*", [](auto *res, auto *req) {
   38|  6.41k|            res->onAborted([]() {
   39|       |                /* We might as well use this opportunity to stress the loop a bit */
   40|  6.41k|                uWS::Loop::get()->defer([]() {
   41|       |
   42|  6.41k|                });
   43|  6.41k|            });
   44|  6.41k|            res->onData([res](std::string_view chunk, bool isEnd) {
   45|  6.41k|                if (isEnd) {
   46|  6.41k|                    res->cork([res, chunk]() {
   47|  6.41k|                        res->write("something ahead");
   48|  6.41k|                        res->end(chunk);
   49|  6.41k|                    });
   50|  6.41k|                }
   51|  6.41k|            });
   52|  6.41k|        }).any("/:candy/*", [](auto *res, auto *req) {
   53|  6.41k|            if (req->getParameter(0).length() == 0) {
   54|  6.41k|                free((void *) -1);
   55|  6.41k|            }
   56|       |            /* Some invalid queries */
   57|  6.41k|            req->getParameter(30000);
   58|  6.41k|            req->getParameter((unsigned short) -34234);
   59|  6.41k|            req->getHeader("yhello");
   60|  6.41k|            req->getQuery();
   61|  6.41k|            req->getQuery("assd");
   62|       |
   63|  6.41k|            res->end("done");
   64|  6.41k|        }).ws<PerSocketData>("/*", {
   65|       |            /* Settings */
   66|  6.41k|            .compression = uWS::SHARED_COMPRESSOR,
   67|  6.41k|            .maxPayloadLength = 16 * 1024,
   68|  6.41k|            .idleTimeout = 12,
   69|  6.41k|            .maxBackpressure = 1024,
   70|       |            /* Handlers */
   71|  6.41k|            .open = [](auto *ws) {
   72|       |                /* Open event here, you may access ws->getUserData() which points to a PerSocketData struct */
   73|  6.41k|                ws->getNativeHandle();
   74|  6.41k|                ws->getRemoteAddressAsText();
   75|  6.41k|                us_poll_ext((struct us_poll_t *) ws);
   76|  6.41k|            },
   77|  6.41k|            .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) {
   78|  6.41k|                ws->send(message, opCode, true);
   79|  6.41k|            },
   80|  6.41k|            .drain = [](auto *ws) {
   81|       |                /* Check ws->getBufferedAmount() here */
   82|  6.41k|            },
   83|  6.41k|            .ping = [](auto *ws, std::string_view) {
   84|       |                /* We use this to trigger the async/wakeup feature */
   85|  6.41k|                uWS::Loop::get()->defer([]() {
   86|       |                    /* Do nothing */
   87|  6.41k|                });
   88|  6.41k|            },
   89|  6.41k|            .pong = [](auto *ws, std::string_view) {
   90|       |                /* Not implemented yet */
   91|  6.41k|            },
   92|  6.41k|            .close = [](auto *ws, int code, std::string_view message) {
   93|       |                /* You may access ws->getUserData() here */
   94|  6.41k|            }
   95|  6.41k|        }).listen(9001, [](auto *listenSocket) {
   96|  6.41k|            listen_socket = listenSocket;
   97|  6.41k|        });
   98|       |
   99|       |        /* Here we want to stress the connect feature, since nothing else stresses it */
  100|  6.41k|        struct us_loop_t *loop = (struct us_loop_t *) uWS::Loop::get();
  101|       |        /* This function is stupid */
  102|  6.41k|        us_loop_iteration_number(loop);
  103|  6.41k|        struct us_socket_context_t *client_context = us_create_socket_context(0, loop, 0, {});
  104|  6.41k|        us_socket_context_timestamp(0, client_context);
  105|  6.41k|        client = us_socket_context_connect(0, client_context, "hostname", 5000, "localhost", 0, 0);
  106|       |	    
  107|  6.41k|        if (client) {
  ------------------
  |  Branch (107:13): [True: 2.32k, False: 4.09k]
  ------------------
  108|  2.32k|            us_socket_is_established(0, client);
  109|  2.32k|            us_socket_local_port(0, client);
  110|  2.32k|        }
  111|       |
  112|  6.41k|        us_socket_context_on_connect_error(0, client_context, [](struct us_socket_t *s, int code) {
  113|  6.41k|            client = nullptr;
  114|  6.41k|            return s;
  115|  6.41k|        });
  116|       |
  117|  6.41k|        us_socket_context_on_open(0, client_context, [](struct us_socket_t *s, int is_client, char *ip, int ip_length) {
  118|  6.41k|            us_socket_flush(0, s);
  119|  6.41k|            return s;
  120|  6.41k|        });
  121|       |
  122|  6.41k|        us_socket_context_on_end(0, client_context, [](struct us_socket_t *s) {
  123|       |            /* Someone sent is a FIN, but we can still send data */
  124|  6.41k|            us_socket_write(0, s, "asdadasdasdasdaddfgdfhdfgdfg", 28, false);
  125|  6.41k|            return s;
  126|  6.41k|        });
  127|       |
  128|  6.41k|        us_socket_context_on_data(0, client_context, [](struct us_socket_t *s, char *data, int length) {
  129|  6.41k|            return s;
  130|  6.41k|        });
  131|       |
  132|  6.41k|        us_socket_context_on_writable(0, client_context, [](struct us_socket_t *s) {
  133|       |            /* Let's defer a close here */
  134|  6.41k|            us_socket_shutdown_read(0, s);
  135|  6.41k|            return s;
  136|  6.41k|        });
  137|       |
  138|  6.41k|        us_socket_context_on_close(0, client_context, [](struct us_socket_t *s, int code, void *reason) {
  139|  6.41k|            client = NULL;
  140|  6.41k|            return s;
  141|  6.41k|        });
  142|       |
  143|       |        /* Trigger some context functions */
  144|  6.41k|        app.addServerName("servername", {});
  145|  6.41k|        app.removeServerName("servername");
  146|  6.41k|        app.missingServerName(nullptr);
  147|  6.41k|        app.getNativeHandle();
  148|       |
  149|  6.41k|        app.run();
  150|       |
  151|       |        /* After done we also free the client context */
  152|  6.41k|        us_socket_context_free(0, client_context);
  153|  6.41k|    }
  154|  6.41k|    uWS::Loop::get()->setSilent(true);
  155|  6.41k|    uWS::Loop::get()->free();
  156|  6.41k|}
_Z8teardownv:
  159|  6.36k|void teardown() {
  160|       |	/* If we are called twice there's a bug (it potentially could if
  161|       |	 * all open sockets cannot be error-closed in one epoll_wait call).
  162|       |	 * But we only allow 1k FDs and we have a buffer of 1024 from epoll_wait */
  163|  6.36k|	if (!listen_socket && !client) {
  ------------------
  |  Branch (163:6): [True: 110, False: 6.25k]
  |  Branch (163:24): [True: 0, False: 110]
  ------------------
  164|      0|		exit(-1);
  165|      0|	}
  166|       |
  167|  6.36k|    if (client) {
  ------------------
  |  Branch (167:9): [True: 139, False: 6.23k]
  ------------------
  168|    139|        us_socket_close(0, client, 0, 0);
  169|    139|        client = NULL;
  170|    139|    }
  171|       |
  172|       |	/* We might have open sockets still, and these will be error-closed by epoll_wait */
  173|       |	// us_socket_context_close - close all open sockets created with this socket context
  174|  6.36k|    if (listen_socket) {
  ------------------
  |  Branch (174:9): [True: 6.25k, False: 110]
  ------------------
  175|  6.25k|        us_listen_socket_close(0, listen_socket);
  176|  6.25k|        listen_socket = NULL;
  177|  6.25k|    }
  178|  6.36k|}
EpollHelloWorld.cpp:_ZZ4testvENK4$_10clEP11us_socket_ti:
  112|  2.02k|        us_socket_context_on_connect_error(0, client_context, [](struct us_socket_t *s, int code) {
  113|  2.02k|            client = nullptr;
  114|  2.02k|            return s;
  115|  2.02k|        });
EpollHelloWorld.cpp:_ZZ4testvENK4$_11clEP11us_socket_tiPci:
  117|    255|        us_socket_context_on_open(0, client_context, [](struct us_socket_t *s, int is_client, char *ip, int ip_length) {
  118|    255|            us_socket_flush(0, s);
  119|    255|            return s;
  120|    255|        });
EpollHelloWorld.cpp:_ZZ4testvENK4$_12clEP11us_socket_t:
  122|    971|        us_socket_context_on_end(0, client_context, [](struct us_socket_t *s) {
  123|       |            /* Someone sent is a FIN, but we can still send data */
  124|    971|            us_socket_write(0, s, "asdadasdasdasdaddfgdfhdfgdfg", 28, false);
  125|    971|            return s;
  126|    971|        });
EpollHelloWorld.cpp:_ZZ4testvENK4$_13clEP11us_socket_tPci:
  128|    257|        us_socket_context_on_data(0, client_context, [](struct us_socket_t *s, char *data, int length) {
  129|    257|            return s;
  130|    257|        });
EpollHelloWorld.cpp:_ZZ4testvENK4$_14clEP11us_socket_t:
  132|    852|        us_socket_context_on_writable(0, client_context, [](struct us_socket_t *s) {
  133|       |            /* Let's defer a close here */
  134|    852|            us_socket_shutdown_read(0, s);
  135|    852|            return s;
  136|    852|        });
EpollHelloWorld.cpp:_ZZ4testvENK4$_15clEP11us_socket_tiPv:
  138|    301|        us_socket_context_on_close(0, client_context, [](struct us_socket_t *s, int code, void *reason) {
  139|    301|            client = NULL;
  140|    301|            return s;
  141|    301|        });
EpollHelloWorld.cpp:_ZZ4testvENK3$_0clIN3uWS12HttpResponseILb0EEENS1_11HttpRequestEEEDaPT_PT0_:
   27|  9.75k|        }).get("/*", [](auto *res, auto *req) {
   28|  9.75k|            if (req->getHeader("write").length()) {
  ------------------
  |  Branch (28:17): [True: 699, False: 9.05k]
  ------------------
   29|    699|                res->writeStatus("200 OK")->writeHeader("write", "true")->write("Hello");
   30|    699|                res->write(" world!");
   31|    699|                res->end();
   32|  9.05k|            } else if (req->getQuery().length()) {
  ------------------
  |  Branch (32:24): [True: 976, False: 8.07k]
  ------------------
   33|    976|                res->close();
   34|  8.07k|            } else {
   35|  8.07k|                res->end("Hello world!");
   36|  8.07k|            }
   37|  9.75k|        }).post("/*", [](auto *res, auto *req) {
EpollHelloWorld.cpp:_ZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS1_11HttpRequestEEEDaPT_PT0_:
   37|  4.29k|        }).post("/*", [](auto *res, auto *req) {
   38|  4.29k|            res->onAborted([]() {
   39|       |                /* We might as well use this opportunity to stress the loop a bit */
   40|  4.29k|                uWS::Loop::get()->defer([]() {
   41|       |
   42|  4.29k|                });
   43|  4.29k|            });
   44|  4.29k|            res->onData([res](std::string_view chunk, bool isEnd) {
   45|  4.29k|                if (isEnd) {
   46|  4.29k|                    res->cork([res, chunk]() {
   47|  4.29k|                        res->write("something ahead");
   48|  4.29k|                        res->end(chunk);
   49|  4.29k|                    });
   50|  4.29k|                }
   51|  4.29k|            });
   52|  4.29k|        }).any("/:candy/*", [](auto *res, auto *req) {
EpollHelloWorld.cpp:_ZZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS1_11HttpRequestEEEDaPT_PT0_ENKUlvE_clEv:
   38|  1.16k|            res->onAborted([]() {
   39|       |                /* We might as well use this opportunity to stress the loop a bit */
   40|  1.16k|                uWS::Loop::get()->defer([]() {
   41|       |
   42|  1.16k|                });
   43|  1.16k|            });
EpollHelloWorld.cpp:_ZZZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS1_11HttpRequestEEEDaPT_PT0_ENKUlvE_clEvENKUlvE_clEv:
   40|  1.08k|                uWS::Loop::get()->defer([]() {
   41|       |
   42|  1.08k|                });
EpollHelloWorld.cpp:_ZZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS1_11HttpRequestEEEDaPT_PT0_ENKUlNSt3__117basic_string_viewIcNS9_11char_traitsIcEEEEbE_clESD_b:
   44|  34.9k|            res->onData([res](std::string_view chunk, bool isEnd) {
   45|  34.9k|                if (isEnd) {
  ------------------
  |  Branch (45:21): [True: 3.13k, False: 31.8k]
  ------------------
   46|  3.13k|                    res->cork([res, chunk]() {
   47|  3.13k|                        res->write("something ahead");
   48|  3.13k|                        res->end(chunk);
   49|  3.13k|                    });
   50|  3.13k|                }
   51|  34.9k|            });
EpollHelloWorld.cpp:_ZZZZ4testvENK3$_1clIN3uWS12HttpResponseILb0EEENS1_11HttpRequestEEEDaPT_PT0_ENKUlNSt3__117basic_string_viewIcNS9_11char_traitsIcEEEEbE_clESD_bENKUlvE_clEv:
   46|  3.13k|                    res->cork([res, chunk]() {
   47|  3.13k|                        res->write("something ahead");
   48|  3.13k|                        res->end(chunk);
   49|  3.13k|                    });
EpollHelloWorld.cpp:_ZZ4testvENK3$_2clIN3uWS12HttpResponseILb0EEENS1_11HttpRequestEEEDaPT_PT0_:
   52|  2.02k|        }).any("/:candy/*", [](auto *res, auto *req) {
   53|  2.02k|            if (req->getParameter(0).length() == 0) {
  ------------------
  |  Branch (53:17): [True: 0, False: 2.02k]
  ------------------
   54|      0|                free((void *) -1);
   55|      0|            }
   56|       |            /* Some invalid queries */
   57|  2.02k|            req->getParameter(30000);
   58|  2.02k|            req->getParameter((unsigned short) -34234);
   59|  2.02k|            req->getHeader("yhello");
   60|  2.02k|            req->getQuery();
   61|  2.02k|            req->getQuery("assd");
   62|       |
   63|  2.02k|            res->end("done");
   64|  2.02k|        }).ws<PerSocketData>("/*", {
EpollHelloWorld.cpp:_ZZ4testvENK3$_3clIN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEDaPT_:
   71|  39.0k|            .open = [](auto *ws) {
   72|       |                /* Open event here, you may access ws->getUserData() which points to a PerSocketData struct */
   73|  39.0k|                ws->getNativeHandle();
   74|  39.0k|                ws->getRemoteAddressAsText();
   75|  39.0k|                us_poll_ext((struct us_poll_t *) ws);
   76|  39.0k|            },
EpollHelloWorld.cpp:_ZZ4testvENK3$_4clIN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEDaPT_NSt3__117basic_string_viewIcNS7_11char_traitsIcEEEENS1_6OpCodeE:
   77|  10.0k|            .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) {
   78|  10.0k|                ws->send(message, opCode, true);
   79|  10.0k|            },
EpollHelloWorld.cpp:_ZZ4testvENK3$_5clIN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEDaPT_:
   80|  5.04k|            .drain = [](auto *ws) {
   81|       |                /* Check ws->getBufferedAmount() here */
   82|  5.04k|            },
EpollHelloWorld.cpp:_ZZ4testvENK3$_6clIN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEDaPT_NSt3__117basic_string_viewIcNS7_11char_traitsIcEEEE:
   83|  6.99k|            .ping = [](auto *ws, std::string_view) {
   84|       |                /* We use this to trigger the async/wakeup feature */
   85|  6.99k|                uWS::Loop::get()->defer([]() {
   86|       |                    /* Do nothing */
   87|  6.99k|                });
   88|  6.99k|            },
EpollHelloWorld.cpp:_ZZZ4testvENK3$_6clIN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEDaPT_NSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEENKUlvE_clEv:
   85|  5.51k|                uWS::Loop::get()->defer([]() {
   86|       |                    /* Do nothing */
   87|  5.51k|                });
EpollHelloWorld.cpp:_ZZ4testvENK3$_7clIN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEDaPT_NSt3__117basic_string_viewIcNS7_11char_traitsIcEEEE:
   89|    647|            .pong = [](auto *ws, std::string_view) {
   90|       |                /* Not implemented yet */
   91|    647|            },
EpollHelloWorld.cpp:_ZZ4testvENK3$_8clIN3uWS9WebSocketILb0ELb1EZ4testvE13PerSocketDataEEEEDaPT_iNSt3__117basic_string_viewIcNS7_11char_traitsIcEEEE:
   92|  39.0k|            .close = [](auto *ws, int code, std::string_view message) {
   93|       |                /* You may access ws->getUserData() here */
   94|  39.0k|            }
EpollHelloWorld.cpp:_ZZ4testvENK3$_9clI18us_listen_socket_tEEDaPT_:
   95|  6.41k|        }).listen(9001, [](auto *listenSocket) {
   96|  6.41k|            listen_socket = listenSocket;
   97|  6.41k|        });

set_consumable_data:
   71|  6.41k|void set_consumable_data(const unsigned char *new_data, int new_length) {
   72|  6.41k|	consumable_data = (unsigned char *) new_data;
   73|  6.41k|	consumable_data_length = new_length;
   74|  6.41k|}
consume_byte:
   77|  2.98M|int consume_byte(unsigned char *b) {
   78|  2.98M|	if (consumable_data_length) {
  ------------------
  |  Branch (78:6): [True: 2.97M, False: 4.71k]
  ------------------
   79|  2.97M|		*b = consumable_data[0];
   80|  2.97M|		consumable_data++;
   81|  2.97M|		consumable_data_length--;
   82|  2.97M|		return 0;
   83|  2.97M|	}
   84|  4.71k|	return -1;
   85|  2.98M|}
allocate_fd:
   90|  1.77M|int allocate_fd() {
   91|       |	// this can be massively optimized by having a list of free blocks or the like
   92|   566M|	for (int fd = 0; fd < MAX_FDS; fd++) {
  ------------------
  |  Branch (92:19): [True: 566M, False: 950]
  ------------------
   93|   566M|		if (!fd_to_file[fd]) {
  ------------------
  |  Branch (93:7): [True: 1.77M, False: 565M]
  ------------------
   94|  1.77M|			num_fds++;
   95|  1.77M|			return fd + RESERVED_SYSTEM_FDS;
   96|  1.77M|		}
   97|   566M|	}
   98|    950|	return -1;
   99|  1.77M|}
init_fd:
  102|  1.77M|void init_fd(int fd, int type, struct file *f) {
  103|  1.77M|	if (fd >= RESERVED_SYSTEM_FDS) {
  ------------------
  |  Branch (103:6): [True: 1.77M, False: 0]
  ------------------
  104|  1.77M|		fd_to_file[fd - RESERVED_SYSTEM_FDS] = f;
  105|  1.77M|		fd_to_file[fd - RESERVED_SYSTEM_FDS]->type = type;
  106|  1.77M|		fd_to_file[fd - RESERVED_SYSTEM_FDS]->next = NULL;
  107|  1.77M|		fd_to_file[fd - RESERVED_SYSTEM_FDS]->prev = NULL;
  108|  1.77M|	}
  109|  1.77M|}
map_fd:
  111|  16.1M|struct file *map_fd(int fd) {
  112|  16.1M|	if (fd >= RESERVED_SYSTEM_FDS && fd < MAX_FDS + RESERVED_SYSTEM_FDS) {
  ------------------
  |  Branch (112:6): [True: 16.1M, False: 0]
  |  Branch (112:35): [True: 16.1M, False: 0]
  ------------------
  113|  16.1M|		return fd_to_file[fd - RESERVED_SYSTEM_FDS];
  114|  16.1M|	}
  115|      0|	return NULL;
  116|  16.1M|}
free_fd:
  119|  1.77M|int free_fd(int fd) {
  120|  1.77M|	if (fd >= RESERVED_SYSTEM_FDS && fd < MAX_FDS + RESERVED_SYSTEM_FDS) {
  ------------------
  |  Branch (120:6): [True: 1.77M, False: 0]
  |  Branch (120:35): [True: 1.77M, False: 0]
  ------------------
  121|  1.77M|		if (fd_to_file[fd - RESERVED_SYSTEM_FDS]) {
  ------------------
  |  Branch (121:7): [True: 1.77M, False: 0]
  ------------------
  122|  1.77M|			fd_to_file[fd - RESERVED_SYSTEM_FDS] = 0;
  123|  1.77M|			num_fds--;
  124|  1.77M|			return 0;
  125|  1.77M|		}
  126|  1.77M|	}
  127|       |
  128|      0|	return -1;
  129|  1.77M|}
__wrap_epoll_create1:
  141|  6.41k|int __wrap_epoll_create1(int flags) {
  142|       |
  143|       |	/* Todo: check that we do not allocate more than one epoll FD */
  144|  6.41k|	int fd = allocate_fd();
  145|       |
  146|  6.41k|	if (fd != -1) {
  ------------------
  |  Branch (146:6): [True: 6.41k, False: 0]
  ------------------
  147|  6.41k|		struct epoll_file *ef = (struct epoll_file *)malloc(sizeof(struct epoll_file));
  148|       |
  149|       |		/* Init the epoll_file */
  150|  6.41k|		ef->poll_set_head = NULL;
  151|  6.41k|		ef->poll_set_tail = NULL;
  152|       |
  153|  6.41k|		init_fd(fd, FD_TYPE_EPOLL, (struct file *)ef);
  154|  6.41k|	}
  155|       |
  156|       |#ifdef PRINTF_DEBUG
  157|       |	printf("epoll_create1 returning epfd: %d\n", fd);
  158|       |#endif
  159|       |
  160|  6.41k|	return fd;
  161|  6.41k|}
__wrap_epoll_ctl:
  165|  4.18M|int __wrap_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) {
  166|       |
  167|  4.18M|	struct epoll_file *ef = (struct epoll_file *)map_fd(epfd);
  168|  4.18M|	if (!ef) {
  ------------------
  |  Branch (168:6): [True: 0, False: 4.18M]
  ------------------
  169|      0|		return -1;
  170|      0|	}
  171|       |
  172|  4.18M|	struct file *f = (struct file *)map_fd(fd);
  173|  4.18M|	if (!f) {
  ------------------
  |  Branch (173:6): [True: 0, False: 4.18M]
  ------------------
  174|      0|		return -1;
  175|      0|	}
  176|       |
  177|       |	/* We add new polls in the head */
  178|  4.18M|	if (op == EPOLL_CTL_ADD) {
  ------------------
  |  Branch (178:6): [True: 1.76M, False: 2.41M]
  ------------------
  179|       |		// if there is a head already
  180|  1.76M|		if (ef->poll_set_head) {
  ------------------
  |  Branch (180:7): [True: 1.76M, False: 6.41k]
  ------------------
  181|  1.76M|			ef->poll_set_head->prev = f;
  182|       |
  183|       |			// then it will be our next
  184|  1.76M|			f->next = ef->poll_set_head;
  185|  1.76M|		} else {
  186|       |			// if there was no head then we became the tail also
  187|  6.41k|			ef->poll_set_tail = f;
  188|  6.41k|		}
  189|       |
  190|       |		// we are now the head in any case
  191|  1.76M|		ef->poll_set_head = f;
  192|       |
  193|  1.76M|		f->epev = *event;
  194|       |
  195|  2.41M|	} else if (op == EPOLL_CTL_MOD) {
  ------------------
  |  Branch (195:13): [True: 648k, False: 1.76M]
  ------------------
  196|       |		/* Modifying is simply changing the file itself */
  197|   648k|		f->epev = *event;
  198|  1.76M|	} else if (op == EPOLL_CTL_DEL) {
  ------------------
  |  Branch (198:13): [True: 1.76M, False: 0]
  ------------------
  199|       |
  200|  1.76M|		if (f->prev) {
  ------------------
  |  Branch (200:7): [True: 721k, False: 1.04M]
  ------------------
  201|   721k|			f->prev->next = f->next;
  202|  1.04M|		} else {
  203|  1.04M|			ef->poll_set_head = f->next;
  204|  1.04M|		}
  205|       |
  206|  1.76M|		if (f->next) {
  ------------------
  |  Branch (206:7): [True: 1.76M, False: 6.41k]
  ------------------
  207|  1.76M|			f->next->prev = f->prev;
  208|  1.76M|		} else {
  209|       |			// tail ska vara vår.prev
  210|  6.41k|			ef->poll_set_tail = f->prev;
  211|  6.41k|		}
  212|       |
  213|       |		// a file that is not in the list should be reset to NULL
  214|  1.76M|		f->prev = NULL;
  215|  1.76M|		f->next = NULL;
  216|  1.76M|	}
  217|       |
  218|       |	/* You have to poll for errors and hangups */
  219|  4.18M|	f->epev.events |= EPOLLERR | EPOLLHUP;
  220|       |
  221|  4.18M|	return 0;
  222|  4.18M|}
__wrap_epoll_wait:
  226|  1.59M|               int maxevents, int timeout) {
  227|       |	//printf("epoll_wait: %d\n", 0);
  228|       |
  229|       |#ifdef PRINTF_DEBUG
  230|       |	printf("Calling epoll_wait\n");
  231|       |#endif
  232|       |
  233|  1.59M|	struct epoll_file *ef = (struct epoll_file *)map_fd(epfd);
  234|  1.59M|	if (!ef) {
  ------------------
  |  Branch (234:6): [True: 0, False: 1.59M]
  ------------------
  235|      0|		return -1;
  236|      0|	}
  237|       |
  238|  1.59M|	if (consumable_data_length) {
  ------------------
  |  Branch (238:6): [True: 1.59M, False: 6.36k]
  ------------------
  239|       |
  240|  1.59M|		int ready_events = 0;
  241|       |
  242|  11.0M|		for (struct file *f = ef->poll_set_head; f; f = f->next) {
  ------------------
  |  Branch (242:44): [True: 9.45M, False: 1.59M]
  ------------------
  243|       |
  244|       |
  245|       |			/* Consume one fuzz byte, AND it with the event */
  246|  9.45M|			if (!consumable_data_length) {
  ------------------
  |  Branch (246:8): [True: 530, False: 9.45M]
  ------------------
  247|       |				// break if we have no data
  248|    530|				break;
  249|    530|			}
  250|       |
  251|       |			// here we have the main condition that drives everything
  252|  9.45M|			int ready_event = consumable_data[0] & f->epev.events;
  253|       |
  254|       |			// consume the byte
  255|  9.45M|			consumable_data_length--;
  256|  9.45M|			consumable_data++;
  257|       |
  258|  9.45M|			if (ready_event) {
  ------------------
  |  Branch (258:8): [True: 6.92M, False: 2.52M]
  ------------------
  259|  6.92M|				if (ready_events < maxevents) {
  ------------------
  |  Branch (259:9): [True: 6.92M, False: 0]
  ------------------
  260|  6.92M|					events[ready_events] = f->epev;
  261|       |
  262|       |					// todo: the event should be masked by the byte, not everything it wants shold be given all the time!
  263|  6.92M|					events[ready_events++].events = ready_event;
  264|  6.92M|				} else {
  265|       |					// we are full, break
  266|      0|					break;
  267|      0|				}
  268|  6.92M|			}
  269|       |
  270|  9.45M|		}
  271|       |
  272|  1.59M|		return ready_events;
  273|       |
  274|  1.59M|	} else {
  275|       |
  276|       |#ifdef PRINTF_DEBUG
  277|       |		printf("Calling teardown\n");
  278|       |#endif
  279|  6.36k|		teardown();
  280|       |
  281|       |		// after shutting down the listen socket we clear the whole list (the bug in epoll_ctl remove)
  282|       |		// so the below loop doesn't work - we never close anything more than the listen socket!
  283|       |
  284|       |		/* You don't really need to emit teardown, you could simply emit error on every poll */
  285|       |
  286|  6.36k|		int ready_events = 0;
  287|       |
  288|       |#ifdef PRINTF_DEBUG
  289|       |		printf("Emitting error on every remaining FD\n");
  290|       |#endif
  291|  67.3k|		for (struct file *f = ef->poll_set_head; f; f = f->next) {
  ------------------
  |  Branch (291:44): [True: 61.0k, False: 6.36k]
  ------------------
  292|       |
  293|  61.0k|			if (f->type == FD_TYPE_SOCKET) {
  ------------------
  |  Branch (293:8): [True: 41.9k, False: 19.1k]
  ------------------
  294|       |
  295|  41.9k|				if (ready_events < maxevents) {
  ------------------
  |  Branch (295:9): [True: 41.9k, False: 0]
  ------------------
  296|  41.9k|					events[ready_events] = f->epev;
  297|       |
  298|       |					// todo: the event should be masked by the byte, not everything it wants shold be given all the time!
  299|  41.9k|					events[ready_events++].events = EPOLLERR | EPOLLHUP;
  300|  41.9k|				} else {
  301|       |					// we are full, break
  302|      0|					break;
  303|      0|				}
  304|       |
  305|  41.9k|			}
  306|  61.0k|		}
  307|       |
  308|       |#ifdef PRINTF_DEBUG
  309|       |		printf("Ready events: %d\n", ready_events);
  310|       |#endif
  311|       |
  312|  6.36k|		return ready_events;
  313|  6.36k|	}
  314|  1.59M|}
__wrap_read:
  332|  4.33M|int __wrap_read(int fd, void *buf, size_t count) {
  333|       |
  334|  4.33M|	if (fd < RESERVED_SYSTEM_FDS) {
  ------------------
  |  Branch (334:6): [True: 0, False: 4.33M]
  ------------------
  335|      0|		return __real_read(fd, buf, count);
  336|      0|	}
  337|       |
  338|       |#ifdef PRINTF_DEBUG
  339|       |	printf("Wrapped read\n");
  340|       |#endif
  341|       |
  342|       |	/* Let's try and clear the buffer first */
  343|       |	//memset(buf, 0, count);
  344|       |
  345|  4.33M|	struct file *f = map_fd(fd);
  346|  4.33M|	if (!f) {
  ------------------
  |  Branch (346:6): [True: 0, False: 4.33M]
  ------------------
  347|      0|		return -1;
  348|      0|	}
  349|       |
  350|  4.33M|	errno = 0;
  351|       |
  352|  4.33M|	if (f->type == FD_TYPE_SOCKET) {
  ------------------
  |  Branch (352:6): [True: 479k, False: 3.85M]
  ------------------
  353|       |
  354|   479k|		if (!consumable_data_length) {
  ------------------
  |  Branch (354:7): [True: 4.31k, False: 474k]
  ------------------
  355|  4.31k|			errno = EWOULDBLOCK;
  356|  4.31k|			return -1;
  357|   474k|		} else {
  358|   474k|			int data_available = (unsigned char) consumable_data[0];
  359|   474k|			consumable_data_length--;
  360|   474k|			consumable_data++;
  361|       |
  362|   474k|			if (consumable_data_length < data_available) {
  ------------------
  |  Branch (362:8): [True: 5.17k, False: 469k]
  ------------------
  363|  5.17k|				data_available = consumable_data_length;
  364|  5.17k|			}
  365|       |
  366|   474k|			if (count < data_available) {
  ------------------
  |  Branch (366:8): [True: 0, False: 474k]
  ------------------
  367|      0|				data_available = count;
  368|      0|			}
  369|       |
  370|   474k|			memcpy(buf, consumable_data, data_available);
  371|       |
  372|   474k|			consumable_data_length -= data_available;
  373|   474k|			consumable_data += data_available;
  374|       |
  375|   474k|			return data_available;
  376|   474k|		}
  377|   479k|	}
  378|       |
  379|  3.85M|	if (f->type == FD_TYPE_EVENT) {
  ------------------
  |  Branch (379:6): [True: 1.26M, False: 2.58M]
  ------------------
  380|  1.26M|		memset(buf, 1, 8);
  381|  1.26M|		return 8;
  382|  1.26M|	}
  383|       |
  384|  2.58M|	if (f->type == FD_TYPE_TIMER) {
  ------------------
  |  Branch (384:6): [True: 2.58M, False: 0]
  ------------------
  385|  2.58M|		memset(buf, 1, 8);
  386|  2.58M|		return 8;
  387|  2.58M|	}
  388|       |
  389|      0|	return -1;
  390|  2.58M|}
__wrap_recv:
  393|   479k|int __wrap_recv(int sockfd, void *buf, size_t len, int flags) {
  394|   479k|	return __wrap_read(sockfd, buf, len);
  395|   479k|}
__wrap_send:
  397|   438k|int __wrap_send(int sockfd, const void *buf, size_t len, int flags) {
  398|       |
  399|   438k|	if (consumable_data_length) {
  ------------------
  |  Branch (399:6): [True: 427k, False: 10.6k]
  ------------------
  400|       |		/* We can send len scaled by the 1 byte */
  401|   427k|		unsigned char scale = consumable_data[0];
  402|   427k|		consumable_data++;
  403|   427k|		consumable_data_length--;
  404|       |
  405|   427k|		int written = float(scale) / 255.0f * len;
  406|       |
  407|   427k|		if (written == 0) {
  ------------------
  |  Branch (407:7): [True: 276k, False: 151k]
  ------------------
  408|   276k|			errno = EWOULDBLOCK;
  409|   276k|		} else {
  410|   151k|			errno = 0;
  411|   151k|		}
  412|       |
  413|   427k|		return written;
  414|   427k|	} else {
  415|  10.6k|		return -1;
  416|  10.6k|	}
  417|   438k|}
__wrap_bind:
  424|  8.59k|int __wrap_bind() {
  425|  8.59k|	return 0;
  426|  8.59k|}
__wrap_setsockopt:
  428|  1.75M|int __wrap_setsockopt() {
  429|  1.75M|	return 0;
  430|  1.75M|}
__wrap_fcntl:
  433|  3.50M|int __wrap_fcntl(int fd, int cmd, ... /* arg */) {
  434|  3.50M|	if (fd < RESERVED_SYSTEM_FDS) {
  ------------------
  |  Branch (434:6): [True: 8.14k, False: 3.49M]
  ------------------
  435|  8.14k|		va_list args;
  436|  8.14k|		va_start(args, cmd);
  437|  8.14k|		int ret = __real_fcntl(fd, cmd, args);
  438|  8.14k|		va_end(args);
  439|  8.14k|		return ret;
  440|  8.14k|	}
  441|       |
  442|  3.49M|	return 0;
  443|  3.50M|}
__wrap_getaddrinfo:
  448|  15.1k|                       struct addrinfo **res) {
  449|       |	//printf("Wrapped getaddrinfo\n");
  450|       |
  451|  15.1k|	struct addrinfo default_hints = {};
  452|       |
  453|  15.1k|	if (!hints) {
  ------------------
  |  Branch (453:6): [True: 2.32k, False: 12.8k]
  ------------------
  454|  2.32k|		hints = &default_hints;
  455|  2.32k|	}
  456|       |
  457|  15.1k|	unsigned char b;
  458|  15.1k|	if (consume_byte(&b)) {
  ------------------
  |  Branch (458:6): [True: 25, False: 15.1k]
  ------------------
  459|     25|		return -1;
  460|     25|	}
  461|       |
  462|       |	/* This one should be thread_local */
  463|  15.1k|	static /*thread_local*/ struct addrinfo ai;
  464|  15.1k|	ai.ai_flags = hints->ai_flags;
  465|  15.1k|	ai.ai_socktype = hints->ai_socktype;
  466|  15.1k|	ai.ai_protocol = hints->ai_protocol;
  467|       |
  468|  15.1k|	if (b > 127) {
  ------------------
  |  Branch (468:6): [True: 2.10k, False: 13.0k]
  ------------------
  469|  2.10k|		ai.ai_family = AF_INET;//hints->ai_family;
  470|  13.0k|	} else {
  471|  13.0k|		ai.ai_family = AF_INET6;//hints->ai_family;
  472|  13.0k|	}
  473|       |
  474|       |	/* This one is for generating the wrong family (maybe invalid?) */
  475|  15.1k|	if (b == 0) {
  ------------------
  |  Branch (475:6): [True: 4.31k, False: 10.8k]
  ------------------
  476|  4.31k|		ai.ai_family = hints->ai_family;
  477|  4.31k|	}
  478|       |
  479|  15.1k|	ai.ai_next = NULL;
  480|  15.1k|	ai.ai_canonname = NULL; // fel
  481|       |
  482|       |	// these should depend on inet6 or inet */
  483|  15.1k|	ai.ai_addrlen = 4; // fel
  484|  15.1k|	ai.ai_addr = NULL; // ska peka på en sockaddr!
  485|       |
  486|       |	// we need to return an addrinfo with family AF_INET6
  487|       |
  488|  15.1k|	*res = &ai;
  489|  15.1k|	return 0;
  490|  15.1k|}
__wrap_freeaddrinfo:
  492|  15.1k|int __wrap_freeaddrinfo() {
  493|  15.1k|	return 0;
  494|  15.1k|}
__wrap_getpeername:
  497|  39.0k|int __wrap_getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
  498|       |
  499|  39.0k|	struct file *f = map_fd(sockfd);
  500|  39.0k|	if (!f) {
  ------------------
  |  Branch (500:6): [True: 0, False: 39.0k]
  ------------------
  501|      0|		return -1;
  502|      0|	}
  503|       |
  504|       |	// todo: this could fail with -1 also (consume a byte)?
  505|       |
  506|  39.0k|	if (f->type == FD_TYPE_SOCKET) {
  ------------------
  |  Branch (506:6): [True: 39.0k, False: 0]
  ------------------
  507|       |
  508|  39.0k|		struct socket_file *sf = (struct socket_file *) f;
  509|       |
  510|  39.0k|		if (addr) {
  ------------------
  |  Branch (510:7): [True: 39.0k, False: 0]
  ------------------
  511|  39.0k|			memcpy(addr, &sf->addr, sf->len);
  512|  39.0k|			*addrlen = sf->len;
  513|  39.0k|		}
  514|       |
  515|  39.0k|		return 0;
  516|  39.0k|	}
  517|       |
  518|      0|	return -1;
  519|  39.0k|}
__wrap_accept4:
  521|  2.96M|int __wrap_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
  522|       |	/* We must end with -1 since we are called in a loop */
  523|       |
  524|  2.96M|	unsigned char b;
  525|  2.96M|	if (consume_byte(&b)) {
  ------------------
  |  Branch (525:6): [True: 4.67k, False: 2.95M]
  ------------------
  526|  4.67k|		return -1;
  527|  4.67k|	}
  528|       |
  529|       |	/* This rule might change, anything below 10 is accepted */
  530|  2.95M|	if (b < 10) {
  ------------------
  |  Branch (530:6): [True: 1.74M, False: 1.21M]
  ------------------
  531|       |
  532|  1.74M|		int fd = allocate_fd();
  533|  1.74M|		if (fd != -1) {
  ------------------
  |  Branch (533:7): [True: 1.74M, False: 950]
  ------------------
  534|       |
  535|       |			/* Allocate the file */
  536|  1.74M|			struct socket_file *sf = (struct socket_file *) malloc(sizeof(struct socket_file));
  537|       |
  538|       |			/* Init the file */
  539|       |
  540|       |			/* Here we need to create a socket FD and return */
  541|  1.74M|			init_fd(fd, FD_TYPE_SOCKET, (struct file *)sf);
  542|       |
  543|       |			/* We need to provide an addr */
  544|       |
  545|       |			/* Begin by setting it to an empty in6 address */
  546|  1.74M|			memset(&sf->addr, 0, sizeof(struct sockaddr_in6));
  547|  1.74M|			sf->len = sizeof(struct sockaddr_in6);
  548|  1.74M|			sf->addr.in6.sin6_family = AF_INET6;
  549|       |
  550|       |			/* Opt-in to ipv4 */
  551|  1.74M|			if (b < 5) {
  ------------------
  |  Branch (551:8): [True: 728k, False: 1.01M]
  ------------------
  552|   728k|				memset(&sf->addr, 0, sizeof(struct sockaddr_in6));
  553|   728k|				sf->len = sizeof(struct sockaddr_in);
  554|   728k|				sf->addr.in.sin_family = AF_INET;
  555|   728k|			}
  556|       |
  557|  1.74M|			if (addr) {
  ------------------
  |  Branch (557:8): [True: 1.74M, False: 0]
  ------------------
  558|       |				/* Copy from socket to addr */
  559|  1.74M|				memcpy(addr, &sf->addr, sf->len);
  560|  1.74M|			}
  561|  1.74M|		}
  562|       |
  563|  1.74M|		return fd;
  564|  1.74M|	}
  565|       |
  566|  1.21M|	return -1;
  567|  2.95M|}
__wrap_listen:
  569|  6.27k|int __wrap_listen() {
  570|       |	/* Listen consumes one byte and fails on -1 */
  571|  6.27k|	unsigned char b;
  572|  6.27k|	if (consume_byte(&b)) {
  ------------------
  |  Branch (572:6): [True: 10, False: 6.26k]
  ------------------
  573|     10|		return -1;
  574|     10|	}
  575|       |
  576|  6.26k|	if (b) {
  ------------------
  |  Branch (576:6): [True: 6.25k, False: 2]
  ------------------
  577|  6.25k|		return 0;
  578|  6.25k|	}
  579|       |
  580|      2|	return -1;
  581|  6.26k|}
__wrap_socket:
  584|  12.6k|int __wrap_socket(int domain, int type, int protocol) {
  585|       |
  586|       |	/* Only accept valid families */
  587|  12.6k|	if (domain != AF_INET && domain != AF_INET6) {
  ------------------
  |  Branch (587:6): [True: 11.0k, False: 1.60k]
  |  Branch (587:27): [True: 4.06k, False: 6.99k]
  ------------------
  588|  4.06k|		return -1;
  589|  4.06k|	}
  590|       |
  591|  8.59k|	int fd = allocate_fd();
  592|       |
  593|  8.59k|	if (fd != -1) {
  ------------------
  |  Branch (593:6): [True: 8.59k, False: 0]
  ------------------
  594|  8.59k|		struct socket_file *sf = (struct socket_file *)malloc(sizeof(struct socket_file));
  595|       |
  596|       |		/* Init the file */
  597|       |
  598|  8.59k|		init_fd(fd, FD_TYPE_SOCKET, (struct file *)sf);
  599|  8.59k|	}
  600|       |
  601|       |#ifdef PRINTF_DEBUG
  602|       |	printf("socket returning fd: %d\n", fd);
  603|       |#endif
  604|       |
  605|  8.59k|	return fd;
  606|  12.6k|}
__wrap_shutdown:
  608|   287k|int __wrap_shutdown() {
  609|       |	//printf("Wrapped shutdown\n");
  610|   287k|	return 0;
  611|   287k|}
__wrap_timerfd_create:
  619|  12.8k|int __wrap_timerfd_create(int clockid, int flags) {
  620|       |
  621|  12.8k|	int fd = allocate_fd();
  622|       |
  623|  12.8k|	if (fd != -1) {
  ------------------
  |  Branch (623:6): [True: 12.8k, False: 0]
  ------------------
  624|  12.8k|		struct timer_file *tf = (struct timer_file *)malloc(sizeof(struct timer_file));
  625|       |
  626|       |		/* Init the file */
  627|       |
  628|       |
  629|  12.8k|		init_fd(fd, FD_TYPE_TIMER, (struct file *)tf);
  630|       |
  631|  12.8k|	}
  632|       |
  633|       |#ifdef PRINTF_DEBUG
  634|       |	printf("timerfd_create returning fd: %d\n", fd);
  635|       |#endif
  636|       |
  637|  12.8k|	return fd;
  638|  12.8k|}
__wrap_timerfd_settime:
  642|  12.8k|                    struct itimerspec *old_value) {
  643|       |	//printf("timerfd_settime: %d\n", fd);
  644|  12.8k|	return 0;
  645|  12.8k|}
__wrap_eventfd:
  653|  6.41k|int __wrap_eventfd() {
  654|       |
  655|  6.41k|	int fd = allocate_fd();
  656|       |
  657|  6.41k|	if (fd != -1) {
  ------------------
  |  Branch (657:6): [True: 6.41k, False: 0]
  ------------------
  658|  6.41k|		struct event_file *ef = (struct event_file *)malloc(sizeof(struct event_file));
  659|       |
  660|       |		/* Init the file */
  661|       |
  662|  6.41k|		init_fd(fd, FD_TYPE_EVENT, (struct file *)ef);
  663|       |
  664|       |		//printf("eventfd: %d\n", fd);
  665|  6.41k|	}
  666|       |
  667|       |#ifdef PRINTF_DEBUG
  668|       |	printf("eventfd returning fd: %d\n", fd);
  669|       |#endif
  670|       |
  671|  6.41k|	return fd;
  672|  6.41k|}
__wrap_close:
  678|  1.77M|int __wrap_close(int fd) {
  679|       |
  680|  1.77M|	if (fd < RESERVED_SYSTEM_FDS) {
  ------------------
  |  Branch (680:6): [True: 0, False: 1.77M]
  ------------------
  681|      0|		return __real_close(fd);
  682|      0|	}
  683|       |
  684|  1.77M|	struct file *f = map_fd(fd);
  685|       |
  686|  1.77M|	if (!f) {
  ------------------
  |  Branch (686:6): [True: 0, False: 1.77M]
  ------------------
  687|      0|		return -1;
  688|      0|	}
  689|       |
  690|  1.77M|	if (f->type == FD_TYPE_EPOLL) {
  ------------------
  |  Branch (690:6): [True: 6.41k, False: 1.76M]
  ------------------
  691|       |#ifdef PRINTF_DEBUG
  692|       |		printf("Closing epoll FD: %d\n", fd);
  693|       |#endif
  694|       |
  695|  6.41k|		free(f);
  696|       |
  697|  6.41k|		return free_fd(fd);
  698|       |
  699|  1.76M|	} else if (f->type == FD_TYPE_TIMER) {
  ------------------
  |  Branch (699:13): [True: 12.8k, False: 1.75M]
  ------------------
  700|       |#ifdef PRINTF_DEBUG
  701|       |		printf("Closing timer fd: %d\n", fd);
  702|       |#endif
  703|       |
  704|  12.8k|		free(f);
  705|       |
  706|  12.8k|		return free_fd(fd);
  707|  1.75M|	} else if (f->type == FD_TYPE_EVENT) {
  ------------------
  |  Branch (707:13): [True: 6.41k, False: 1.74M]
  ------------------
  708|       |#ifdef PRINTF_DEBUG
  709|       |		printf("Closing event fd: %d\n", fd);
  710|       |#endif
  711|       |
  712|  6.41k|		free(f);
  713|       |
  714|  6.41k|		return free_fd(fd);
  715|  1.74M|	} else if (f->type == FD_TYPE_SOCKET) {
  ------------------
  |  Branch (715:13): [True: 1.74M, False: 0]
  ------------------
  716|       |#ifdef PRINTF_DEBUG
  717|       |		printf("Closing socket fd: %d\n", fd);
  718|       |#endif
  719|       |
  720|       |		// we should call epoll_ctl remove here
  721|       |
  722|  1.74M|		free(f);
  723|       |
  724|  1.74M|		int ret = free_fd(fd);
  725|       |
  726|       |#ifdef PRINTF_DEBUG
  727|       |		printf("Ret: %d\n", ret);
  728|       |#endif
  729|       |
  730|       |		//free(-1);
  731|  1.74M|		return ret;
  732|  1.74M|	}
  733|       |
  734|      0|	return -1;
  735|  1.77M|}
LLVMFuzzerTestOneInput:
  737|  6.41k|int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  738|  6.41k|	set_consumable_data(data, size);
  739|       |
  740|  6.41k|	test();
  741|       |
  742|  6.41k|	if (num_fds) {
  ------------------
  |  Branch (742:6): [True: 0, False: 6.41k]
  ------------------
  743|      0|		printf("ERROR! Cannot leave open FDs after test!\n");
  744|      0|	}
  745|       |
  746|  6.41k|	return 0;
  747|  6.41k|}

