void HttpSocket<isServer>::onData(uS::Socket s, char *data, int length) { HttpSocket httpSocket(s); HttpSocket::Data *httpData = httpSocket.getData(); httpSocket.cork(true); if (httpData->contentLength) { httpData->missedDeadline = false; if (httpData->contentLength >= length) { getGroup<isServer>(s)->httpDataHandler(httpData->outstandingResponsesTail, data, length, httpData->contentLength -= length); return; } else { getGroup<isServer>(s)->httpDataHandler(httpData->outstandingResponsesTail, data, httpData->contentLength, 0); data += httpData->contentLength; length -= httpData->contentLength; httpData->contentLength = 0; } } if (FORCE_SLOW_PATH || httpData->httpBuffer.length()) { if (httpData->httpBuffer.length() + length > MAX_HEADER_BUFFER_SIZE) { httpSocket.onEnd(s); return; } httpData->httpBuffer.reserve(httpData->httpBuffer.length() + length + WebSocketProtocol<uWS::CLIENT>::CONSUME_POST_PADDING); httpData->httpBuffer.append(data, length); data = (char *) httpData->httpBuffer.data(); length = httpData->httpBuffer.length(); } char *end = data + length; char *cursor = data; *end = '\r'; Header headers[MAX_HEADERS]; do { char *lastCursor = cursor; if ((cursor = getHeaders(cursor, end, headers, MAX_HEADERS))) { HttpRequest req(headers); if (isServer) { headers->valueLength = std::max<int>(0, headers->valueLength - 9); httpData->missedDeadline = false; if (req.getHeader("upgrade", 7)) { if (getGroup<SERVER>(s)->httpUpgradeHandler) { getGroup<SERVER>(s)->httpUpgradeHandler(HttpSocket<isServer>(s), req); } else { Header secKey = req.getHeader("sec-websocket-key", 17); Header extensions = req.getHeader("sec-websocket-extensions", 24); Header subprotocol = req.getHeader("sec-websocket-protocol", 22); if (secKey.valueLength == 24) { bool perMessageDeflate; httpSocket.upgrade(secKey.value, extensions.value, extensions.valueLength, subprotocol.value, subprotocol.valueLength, &perMessageDeflate); getGroup<SERVER>(s)->removeHttpSocket(s); s.enterState<WebSocket<SERVER>>(new WebSocket<SERVER>::Data(perMessageDeflate, httpData)); getGroup<SERVER>(s)->addWebSocket(s); s.cork(true); getGroup<SERVER>(s)->connectionHandler(WebSocket<SERVER>(s), req); s.cork(false); delete httpData; } else { httpSocket.onEnd(s); } } return; } else { if (getGroup<SERVER>(s)->httpRequestHandler) { HttpResponse *res = HttpResponse::allocateResponse(httpSocket, httpData); if (httpData->outstandingResponsesTail) { httpData->outstandingResponsesTail->next = res; } else { httpData->outstandingResponsesHead = res; } httpData->outstandingResponsesTail = res; Header contentLength; if (req.getMethod() != HttpMethod::METHOD_GET && (contentLength = req.getHeader("content-length", 14))) { httpData->contentLength = atoi(contentLength.value); size_t bytesToRead = std::min<int>(httpData->contentLength, end - cursor); getGroup<SERVER>(s)->httpRequestHandler(res, req, cursor, bytesToRead, httpData->contentLength -= bytesToRead); cursor += bytesToRead; } else { getGroup<SERVER>(s)->httpRequestHandler(res, req, nullptr, 0, 0); } if (s.isClosed() || s.isShuttingDown()) { return; } } else { httpSocket.onEnd(s); return; } } } else { if (req.getHeader("upgrade", 7)) { s.enterState<WebSocket<CLIENT>>(new WebSocket<CLIENT>::Data(false, httpData)); httpSocket.cancelTimeout(); httpSocket.setUserData(httpData->httpUser); getGroup<CLIENT>(s)->addWebSocket(s); s.cork(true); getGroup<CLIENT>(s)->connectionHandler(WebSocket<CLIENT>(s), req); s.cork(false); if (!(s.isClosed() || s.isShuttingDown())) { WebSocketProtocol<CLIENT> *kws = (WebSocketProtocol<CLIENT> *) ((WebSocket<CLIENT>::Data *) s.getSocketData()); kws->consume(cursor, end - cursor, s); } delete httpData; } else { httpSocket.onEnd(s); } return; } } else { if (!httpData->httpBuffer.length()) { if (length > MAX_HEADER_BUFFER_SIZE) { httpSocket.onEnd(s); } else { httpData->httpBuffer.append(lastCursor, end - lastCursor); } } return; } } while(cursor != end); httpSocket.cork(false); httpData->httpBuffer.clear(); }