WebSocket::WebSocket(const SocketClient::SharedPtr& client) : mClient(client) { wslay_event_callbacks callbacks = { wslayRecvCallback, wslaySendCallback, 0, // genmask_callback 0, // on_frame_recv_start_callback 0, // on_frame_recv_callback 0, // on_frame_recv_end_callback wslayOnMsgRecvCallback }; wslay_event_context_server_init(&mCtx, &callbacks, this); client->readyRead().connect([this](const SocketClient::SharedPtr& client, Buffer&& buf) { if (buf.isEmpty()) return; mBuffers.push_back(std::move(buf)); if (wslay_event_recv(mCtx) < 0) { // close socket client->close(); mClient.reset(); mError(this); } }); client->disconnected().connect([this](const SocketClient::SharedPtr& client) { mClient.reset(); mDisconnected(this); }); }
void Connection::onDataAvailable(const SocketClient::SharedPtr &client, Buffer&& buf) { auto that = shared_from_this(); while (true) { if (!buf.isEmpty()) mBuffers.push(std::forward<Buffer>(buf)); unsigned int available = mBuffers.size(); if (!available) break; if (!mPendingRead) { if (available < static_cast<int>(sizeof(uint32_t))) break; union { unsigned char b[sizeof(uint32_t)]; int pending; }; const int read = mBuffers.read(b, 4); assert(read == 4); mPendingRead = pending; assert(mPendingRead > 0); available -= read; } assert(mPendingRead >= 0); if (available < static_cast<unsigned int>(mPendingRead)) break; StackBuffer<1024 * 16> buffer(mPendingRead); const int read = mBuffers.read(buffer.buffer(), mPendingRead); assert(read == mPendingRead); mPendingRead = 0; Message::MessageError error; std::shared_ptr<Message> message = Message::create(mVersion, buffer, read, &error); if (message) { if (message->messageId() == FinishMessage::MessageId) { mFinishStatus = std::static_pointer_cast<FinishMessage>(message)->status(); mFinished(that, mFinishStatus); } else { newMessage()(message, that); } } else if (mErrorHandler) { mErrorHandler(client, std::move(error)); } else { ::error() << "Unable to create message from data" << error.type << error.text << read; } if (!message) client->close(); } }