void HttpSocket<isServer>::upgrade(const char *secKey, const char *extensions, size_t extensionsLength, const char *subprotocol, size_t subprotocolLength, bool *perMessageDeflate) { uS::SocketData::Queue::Message *messagePtr; if (isServer) { *perMessageDeflate = false; std::string extensionsResponse; if (extensionsLength) { Group<isServer> *group = getGroup<isServer>(*this); ExtensionsNegotiator<uWS::SERVER> extensionsNegotiator(group->extensionOptions); extensionsNegotiator.readOffer(std::string(extensions, extensionsLength)); extensionsResponse = extensionsNegotiator.generateOffer(); if (extensionsNegotiator.getNegotiatedOptions() & PERMESSAGE_DEFLATE) { *perMessageDeflate = true; } } unsigned char shaInput[] = "XXXXXXXXXXXXXXXXXXXXXXXX258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; memcpy(shaInput, secKey, 24); unsigned char shaDigest[SHA_DIGEST_LENGTH]; SHA1(shaInput, sizeof(shaInput) - 1, shaDigest); char upgradeBuffer[1024]; memcpy(upgradeBuffer, "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: ", 97); base64(shaDigest, upgradeBuffer + 97); memcpy(upgradeBuffer + 125, "\r\n", 2); size_t upgradeResponseLength = 127; if (extensionsResponse.length()) { memcpy(upgradeBuffer + upgradeResponseLength, "Sec-WebSocket-Extensions: ", 26); memcpy(upgradeBuffer + upgradeResponseLength + 26, extensionsResponse.data(), extensionsResponse.length()); memcpy(upgradeBuffer + upgradeResponseLength + 26 + extensionsResponse.length(), "\r\n", 2); upgradeResponseLength += 26 + extensionsResponse.length() + 2; } if (subprotocolLength) { memcpy(upgradeBuffer + upgradeResponseLength, "Sec-WebSocket-Protocol: ", 24); memcpy(upgradeBuffer + upgradeResponseLength + 24, subprotocol, subprotocolLength); memcpy(upgradeBuffer + upgradeResponseLength + 24 + subprotocolLength, "\r\n", 2); upgradeResponseLength += 24 + subprotocolLength + 2; } static char stamp[] = "Sec-WebSocket-Version: 13\r\nWebSocket-Server: uWebSockets\r\n\r\n"; memcpy(upgradeBuffer + upgradeResponseLength, stamp, sizeof(stamp) - 1); upgradeResponseLength += sizeof(stamp) - 1; messagePtr = allocMessage(upgradeResponseLength, upgradeBuffer); } else { messagePtr = allocMessage(getData()->httpBuffer.length(), getData()->httpBuffer.data()); getData()->httpBuffer.clear(); } bool wasTransferred; if (write(messagePtr, wasTransferred)) { if (!wasTransferred) { freeMessage(messagePtr); } else { messagePtr->callback = nullptr; } } else { freeMessage(messagePtr); } }
bool HTTPSocket<isServer>::upgrade(const char *secKey, const char *extensions, size_t extensionsLength, const char *subprotocol, size_t subprotocolLength) { if (isServer) { unsigned char shaInput[] = "XXXXXXXXXXXXXXXXXXXXXXXX258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; memcpy(shaInput, secKey, 24); unsigned char shaDigest[SHA_DIGEST_LENGTH]; SHA1(shaInput, sizeof(shaInput) - 1, shaDigest); char upgradeBuffer[1024]; memcpy(upgradeBuffer, "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: ", 97); base64(shaDigest, upgradeBuffer + 97); memcpy(upgradeBuffer + 125, "\r\n", 2); size_t upgradeResponseLength = 127; if (extensionsLength) { memcpy(upgradeBuffer + upgradeResponseLength, "Sec-WebSocket-Extensions: ", 26); memcpy(upgradeBuffer + upgradeResponseLength + 26, extensions, extensionsLength); memcpy(upgradeBuffer + upgradeResponseLength + 26 + extensionsLength, "\r\n", 2); upgradeResponseLength += 26 + extensionsLength + 2; } if (subprotocolLength) { memcpy(upgradeBuffer + upgradeResponseLength, "Sec-WebSocket-Protocol: ", 24); memcpy(upgradeBuffer + upgradeResponseLength + 24, subprotocol, subprotocolLength); memcpy(upgradeBuffer + upgradeResponseLength + 24 + subprotocolLength, "\r\n", 2); upgradeResponseLength += 24 + subprotocolLength + 2; } static char stamp[] = "Sec-WebSocket-Version: 13\r\nServer: uWebSockets\r\n\r\n"; memcpy(upgradeBuffer + upgradeResponseLength, stamp, sizeof(stamp) - 1); upgradeResponseLength += sizeof(stamp) - 1; uS::SocketData::Queue::Message *messagePtr = allocMessage(upgradeResponseLength, upgradeBuffer); bool wasTransferred; if (write(messagePtr, wasTransferred)) { if (!wasTransferred) { freeMessage(messagePtr); } else { messagePtr->callback = nullptr; } } else { onEnd(*this); return false; } } else { std::string upgradeHeaderBuffer = std::string("GET /") + getData()->path + " HTTP/1.1\r\n" "Upgrade: websocket\r\n" "Connection: Upgrade\r\n" "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n" "Host: " + getData()->host + "\r\n" "Sec-WebSocket-Version: 13\r\n\r\n"; uS::SocketData::Queue::Message *messagePtr = allocMessage(upgradeHeaderBuffer.length(), upgradeHeaderBuffer.data()); bool wasTransferred; if (write(messagePtr, wasTransferred)) { if (!wasTransferred) { freeMessage(messagePtr); } else { messagePtr->callback = nullptr; } } else { onEnd(*this); return false; } } return true; }