void SslSocket::handshakeInternal() { qDebug() << "start handshake, state is" << d->state; int result = gnutls_handshake(d->session); qDebug() << "shake result" << gnutls_strerror(result) << result; if (result == 0) { qDebug() << "handshake completed"; d->state = Encrypted; emit handshakeComplete(); } else if (gnutls_error_is_fatal(result)) { qDebug() << "fatal error in handshake"; emit error(); d->socket->disconnect(); d->state = Disconnected; } }
// Accept connection from server and initiate the SSL handshake void Server::acceptConnection() { QSslSocket *socket = server.nextPendingConnection(); assert(socket); // QSslSocket emits the encrypted() signal after the encrypted connection is established connect(socket, SIGNAL(encrypted()), this, SLOT(handshakeComplete())); // Report any SSL errors that occur connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(sslErrors(const QList<QSslError> &))); connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(connectionFailure())); socket->setPrivateKey(key); socket->setLocalCertificate(certificate); socket->setPeerVerifyMode(QSslSocket::VerifyNone); socket->startServerEncryption(); }
bool WebSocketFramer::checkHandshakeResponse(http::Response& response) { assert(_mode == ws::ClientSide); assert(_headerState == 1); if (response.getStatus() == http::StatusCode::SwitchingProtocols) { // Complete handshake or throw completeHandshake(response); // Success _headerState++; assert(handshakeComplete()); return true; } else if (response.getStatus() == http::StatusCode::Unauthorized) assert(0 && "authentication not implemented"); else throw std::runtime_error("WebSocket error: Cannot upgrade to WebSocket connection: " + response.getReason()); //, ws::ErrorNoHandshake // Need to resend request return false; }
UInt64 WebSocketFramer::readFrame(BitReader& frame, char*& payload) { assert(handshakeComplete()); UInt64 limit = frame.limit(); size_t offset = frame.position(); //assert(offset == 0); // Read the frame header char header[MAX_HEADER_LENGTH]; BitReader headerReader(header, MAX_HEADER_LENGTH); frame.get(header, 2); UInt8 lengthByte = static_cast<UInt8>(header[1]); int maskOffset = 0; if (lengthByte & FRAME_FLAG_MASK) maskOffset += 4; lengthByte &= 0x7f; if (lengthByte + 2 + maskOffset < MAX_HEADER_LENGTH) frame.get(header + 2, lengthByte + maskOffset); else frame.get(header + 2, MAX_HEADER_LENGTH - 2); // Reserved fields frame.skip(2); // Parse frame header UInt8 flags; char mask[4]; headerReader.getU8(flags); headerReader.getU8(lengthByte); _frameFlags = flags; UInt64 payloadLength = 0; int payloadOffset = 2; if ((lengthByte & 0x7f) == 127) { UInt64 l; headerReader.getU64(l); if (l > limit) throw std::runtime_error(util::format("WebSocket error: Insufficient buffer for payload size %" I64_FMT "u", l)); //, ws::ErrorPayloadTooBig payloadLength = l; payloadOffset += 8; } else if ((lengthByte & 0x7f) == 126) { UInt16 l; headerReader.getU16(l); if (l > limit) throw std::runtime_error(util::format("WebSocket error: Insufficient buffer for payload size %u", unsigned(l))); //, ws::ErrorPayloadTooBig payloadLength = l; payloadOffset += 2; } else { UInt8 l = lengthByte & 0x7f; if (l > limit) throw std::runtime_error(util::format("WebSocket error: Insufficient buffer for payload size %u", unsigned(l))); //, ws::ErrorPayloadTooBig payloadLength = l; } if (lengthByte & FRAME_FLAG_MASK) { headerReader.get(mask, 4); payloadOffset += 4; } if (payloadLength > limit) //length) throw std::runtime_error("WebSocket error: Incomplete frame received"); //, ws::ErrorIncompleteFrame // Get a reference to the start of the payload payload = reinterpret_cast<char*>(const_cast<char*>(frame.begin() + (offset + payloadOffset))); // Unmask the payload if required if (lengthByte & FRAME_FLAG_MASK) { auto p = reinterpret_cast<char*>(payload); //frame.data()); for (UInt64 i = 0; i < payloadLength; i++) { p[i] ^= mask[i % 4]; } } // Update frame length to include payload plus header frame.seek(std::size_t(offset + payloadOffset + payloadLength)); //frame.limit(offset + payloadOffset + payloadLength); //int frameLength = (offset + payloadOffset); //assert(frame.position() == (offset + payloadOffset)); return payloadLength; }
// Accept connection from server and initiate the SSL handshake void Server::acceptConnection() { if (sockets.empty() == false) std::cout << "Server is mad efor 1 connection also. Need to update to handle multiple connections" << std::endl; QSslSocket *socket = dynamic_cast<QSslSocket *>(server.nextPendingConnection()); assert(socket); // Report any SSL errors that occur connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(sslErrors(const QList<QSslError> &))); connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(connectionFailure())); // QSslSocket emits the encrypted() signal after the encrypted connection is established #define _USE_ENCRYPTION #ifdef _USE_ENCRYPTION connect(socket, SIGNAL(encrypted()), this, SLOT(handshakeComplete())); socket->setPrivateKey(key); socket->setLocalCertificate(certificate); socket->setPeerVerifyMode(QSslSocket::VerifyNone); socket->startServerEncryption(); #else connect(socket, SIGNAL(disconnected()), this, SLOT(connectionClosed())); connect(socket, SIGNAL(readyRead()), this, SLOT(receiveMessage())); sockets.push_back(socket); std::cout << "Accepted connection from " << socket->peerAddress().toString().toStdString() << ":" << socket->peerPort() << " .Encrypted : " << socket->isEncrypted() << std::endl; #endif }