void QSocketSession::findByteOrder() { float i = 3.1415; if (theIsMaster) { sendChunk((uchar *)&i, 4); if (!waitForAck(1000, &theSameByteOrder) || !isOpen()) { qWarning("*** ERROR: Handshake failed: Didn't receive ack. Closing link."); close(); return; } } else { float remotei; if (!receiveChunk((uchar *)&remotei, 4, 1000) || !isOpen()) { qWarning("*** ERROR: Handshake failed: Didn't receive remote bit pattern. Closing link."); close(); return; } float rremotei; uint &t = *((uint *)&rremotei); t = bswap_32(*((uint *)&remotei)); if (remotei == i) theSameByteOrder = true; else if (rremotei == i) theSameByteOrder = false; else qWarning("*** CRITICAL: Two hosts have neither same nor opposite byte order. (%f or %f should be %f)", remotei, rremotei, i); ack(theSameByteOrder); } }
QByteArray QSocketSession::receiveString() { int l = safeReceiveWord<uint32_t>(); QByteArray s(l, ' '); receiveChunk((uchar *)s.data(), l); return s; }
void QSocketSession::handshake() { if (MESSAGES) qDebug("Handshaking... (isOpen()=%d)", isOpen()); ack(); if (!waitForAck(1000) || !isOpen()) { qWarning("*** ERROR: Handshake failed: Didn't receive ack. Closing link."); close(); return; } if (MESSAGES) qDebug("Got ack!"); for (bool know = false; !know;) { uchar mi = rand() & 255; sendByte(mi); uchar i; if (!receiveChunk((uchar *)&i, 1, 1000) || !isOpen()) { qWarning("*** ERROR: Handshake failed: Didn't receive random. Closing link."); close(); return; } if (mi != i) { theIsMaster = mi > i; know = true; } else { if (MESSAGES) qDebug("Doh! Number clash (%d = %d)", mi, i); } } findByteOrder(); }
void QSocketSession::safeReceiveWordArray(int32_t *t, uint32_t size) { receiveChunk((uchar *)t, 4 * size); if (!theSameByteOrder) for (uint32_t i = 0; i < size; i++) t[i] = bswap_32(t[i]); }
uint32_t QSocketSession::safeReceiveWord() { union { int32_t i; uint32_t t; uchar c[4]; } d; receiveChunk(d.c, 4); if (!theSameByteOrder) d.i = bswap_32(d.i); return d.t; }
void QSocketSession::safeReceiveWordArray(float *t, uint32_t size) { int32_t *array = (int32_t *)t; receiveChunk((uchar *)array, 4 * size); if (!theSameByteOrder) for (uint32_t i = 0; i < size; i++) array[i] = bswap_32(array[i]); }
void Client::processMessage(ENetEvent& event) { std::string packetContents = std::string(reinterpret_cast<char*>(event.packet->data), event.packet->dataLength); uint32_t packetType = Packet::deserializePacketType(packetContents); switch (packetType) { case Packet::FromServerPacketContents::ChatMessageFromServerPacket: receiveChatMessage(packetContents); break; case Packet::FromServerPacketContents::InitialPlayerDataFromServerPacket: receiveInitialPlayerData(packetContents); break; case Packet::FromServerPacketContents::PlayerDisconnectedFromServerPacket: receivePlayerDisconnected(packetContents); break; case Packet::FromServerPacketContents::PlayerMoveFromServerPacket: receivePlayerMove(packetContents); break; case Packet::FromServerPacketContents::InitialPlayerDataFinishedFromServerPacket: m_initialPlayersReceivedFinished = true; break; case Packet::FromServerPacketContents::ChunkFromServerPacket: receiveChunk(packetContents); break; case Packet::QuickBarInventoryItemFromServerPacket: receiveQuickBarInventoryItem(packetContents); break; case Packet::QuickBarInventoryItemCountChangedFromServerPacket: receiveQuickBarInventoryItemCountChanged(packetContents); break; case Packet::ItemSpawnedFromServerPacket: receiveItemSpawned(packetContents); break; case Packet::WorldTimeChangedFromServerPacket: receiveWorldTimeChanged(packetContents); break; case Packet::InitialVegetationSpawningFromServerPacket: receiveInitialVegetationSpawning(packetContents); break; default: Debug::assertf(false, "Client failure, unhandled packet type received from server, it needs implemented apparently."); } enet_packet_destroy(event.packet); }
bool QSocketSession::waitForAck(bool *ackType) { uchar c = 0; while (isOpen() && c != 1 && c != 2) receiveChunk(&c, 1); if (c != 1 && c != 2) return false; if (ackType) *ackType = c; return true; }
void NodeVersionLoader::receiveData(std::uint64_t size) { auto self = shared_from_this(); checkThread(); state = State::ReceivingData; remainingBytes = size; lastReceiveTime = boost::posix_time::second_clock::local_time(); setWatchDogTimer(); receiveChunk(); }
bool QSocketSession::waitForAck(uint timeOut, bool *ackType) { uchar c = 0; while (isOpen() && c != 1 && c != 2) if (!receiveChunk(&c, 1, timeOut)) { if (MESSAGES) qWarning("*** INFO: Connection error - Timeout while waiting for Ack."); return false; } if (c != 1 && c != 2) return false; if (ackType) *ackType = c; return true; }
void NodeVersionLoader::receiveChunk() { auto self = shared_from_this(); checkThread(); auto& item = currentDownloadItem(); auto chunkSize = static_cast<std::size_t> (std::min<std::uint64_t>(readBuffer.size(), static_cast<std::uint64_t>(remainingBytes))); if (chunkSize == 0) { // Done! BOOST_LOG_SEV(log, LogLevel::Info) << "Download completed."; auto ver = item.version; { std::lock_guard<std::mutex> lock(downloadQueueMutex); downloadQueue.pop_front(); // note: `item` is a dangling reference now } file.reset(); timer.cancel(); onVersionDownloaded(ver); log.setChannel(std::string("(none)")); state = State::Waiting; timer.expires_from_now(boost::posix_time::seconds(1)); timer.async_wait([this, self] (const error_code& error) { if (error) { return; } if (disposed) { BOOST_LOG_SEV(log, LogLevel::Debug) << "Retry timer aborted.: Disposed."; return; } state = State::Idle; checkQueue(); }); return; } asio::async_read(socket, asio::buffer(readBuffer.data(), chunkSize), [this, self, &item, chunkSize](const error_code& error, std::size_t) { checkThread(); if (disposed) { downloadCancelled(); return; } if (error) { downloadFailed(error.message()); return; } lastReceiveTime = boost::posix_time::second_clock::local_time(); try { file->write(readBuffer.data(), chunkSize); } catch (...) { downloadFailed("Failed to write to the downloaded file.: " + boost::current_exception_diagnostic_information()); return; } remainingBytes -= static_cast<std::uint64_t>(chunkSize); receiveChunk(); }); }