void CommunicationManager::readOrder(Client* client, sf::Packet packet) { //On récupère la première partie du packet std::string firstPart; if(packet >> firstPart) { if(strcmp(firstPart.data(), "ping") == 0) { //Si c'est un ping, on renvoie pong en réponse std::cout << "ping" << std::endl; packet.clear(); packet << "pong"; client->socket().send(packet); } if(strcmp(firstPart.data(), "chat") == 0) { //Si c'est un chat, on récupère la deuxieme partie //et on la relaie aux autres joueurs std::string secondPart; packet >> secondPart; for (std::list<Client*>::iterator it = m_clients.begin(); it != m_clients.end(); ++it) sendChatMessage((*it), secondPart); } if(firstPart.compare("myNameIs") == 0) packet >> client->m_name; }
SocketStatus NetworkManager::receive(sf::Packet& PacketToReceive) { // initialize pendingPacket std::vector<char> myPendingPacket; myPendingPacket.clear(); // We start by getting the size of the incoming packet sf::Uint32 PacketSize = 0; std::size_t Received = 0; PacketSize =receiveB<sf::Uint32>(); PacketSize = ntohl(PacketSize); // Then loop until we receive all the packet data char Buffer[1024]; while (myPendingPacket.size() < PacketSize) { // Receive a chunk of data std::size_t SizeToGet = std::min(static_cast<std::size_t>(PacketSize - myPendingPacket.size()), sizeof(Buffer)); SocketStatus Status = Receive(Buffer, SizeToGet, Received); if (Status != Done) { throw std::runtime_error("Network : receive packet : receive of information didn't worked"); } // Append it into the packet if (Received > 0) { myPendingPacket.resize(myPendingPacket.size() + Received); char* Begin = &myPendingPacket[0] + myPendingPacket.size() - Received; memcpy(Begin, Buffer, Received); } } // We have received all the datas : we can copy it to the user packet, and clear our internal packet PacketToReceive.Clear(); if (!myPendingPacket.empty()) PacketToReceive.OnReceive(&myPendingPacket[0], myPendingPacket.size()); return Done; }
void PhatChat::Server::Client::handlePacket ( sf::Packet packet ) { unsigned char operationCodeValue = 0 ; packet >> operationCodeValue ; PhatChat::OperationCode operationCode = static_cast <PhatChat::OperationCode> ( operationCodeValue ) ; if ( operationCode == PhatChat::OperationCode::PING ) { PhatChat::PingPacket pingPacket ( PhatChat::PingPacket::decode ( packet ) ) ; std::cout << "Received ping packet with value " << pingPacket.getValue ( ) << "!" << std::endl ; sf::Packet newPacket ( PhatChat::PongPacket ( pingPacket.getValue ( ) ).encode ( ) ) ; this->socket.send ( newPacket ) ; } else if ( operationCode == PhatChat::OperationCode::PONG ) { PhatChat::PongPacket pongPacket = PhatChat::PongPacket::decode ( packet ) ; std::cout << "Received pong packet with value " << pongPacket.getValue ( ) << "!" << std::endl ; } else if ( operationCode == PhatChat::OperationCode::REQUEST_USERNAME ) { PhatChat::RequestUsernamePacket requestUsernamePacket = PhatChat::RequestUsernamePacket::decode ( packet ) ; this->setUsername ( requestUsernamePacket.getUsername ( ) ) ; } else if ( operationCode == PhatChat::OperationCode::MESSAGE ) { PhatChat::MessagePacket messagePacket = PhatChat::MessagePacket::decode ( packet ) ; std::string username = this->username.empty ( ) ? messagePacket.getUsername ( ) : this->username ; std::cout << "Received message from " << username << " saying \"" << messagePacket.getMessage ( ) << "\"!" << std::endl ; if ( * messagePacket.getMessage ( ).begin ( ) == '/' ) this->handleCommand ( messagePacket.getMessage ( ) ) ; else { messagePacket.setUsername ( username ) ; for ( auto client : this->clientManager ) { packet = messagePacket.encode ( ) ; client->getSocket ( ).send ( packet ) ; } } } else std::cout << "Operation code is unknown! Skip " << packet.getDataSize ( ) << " bytes." << std::endl ; }
SocketStatus NetworkManager::send(sf::Packet& PacketToSend) { // Get the data to send from the packet std::size_t DataSize = 0; const char* Data = PacketToSend.OnSend(DataSize); // Send the packet size sf::Uint32 PacketSize = htonl(static_cast<unsigned long>(DataSize)); send<sf::Uint32>(PacketSize); // Send the packet data if (PacketSize > 0) return Send(Data,DataSize); else return Done; }
bool MasterEntityList::getChangedEntities(sf::Packet& packet) { bool anyChanged = false; packet << Packet::EntityUpdate; // Get deleted entities if (!deletedEnts.empty()) { std::cout << "Deleted entity IDs: "; for (auto& entId: deletedEnts) { std::cout << entId << " "; packet << entId << -1; anyChanged = true; } std::cout << std::endl; deletedEnts.clear(); } // Get changed entities if (entCount > 0) { for (auto& ent: ents) { if (ent != nullptr && ent->hasChanged()) { ent->getData(packet); ent->setChanged(false); anyChanged = true; } if (packet.getDataSize() >= sf::UdpSocket::MaxDatagramSize - 256) break; } /*if (anyChanged) cout << "getChangedEntities()\n";*/ return anyChanged; } else return false; }
void Connection::prepSend(Protocol proto, const sf::Packet& rData, sf::Packet& data) { data << static_cast<int32_t>(proto); data << ++m_lastSendRecieve[proto].first; data.append(rData.getData(), rData.getDataSize()); }
void PacketBroker::receive(sf::Packet& packet, Protocol protocol) { using namespace sf; if (protocol == Protocol::TCP) { if (Globals::Networking->ReceiveSafe(packet) != Socket::Status::Done) return; } else { PacketHandler::RemoteAddress remoteAddress; if (Globals::Networking->ReceiveFast(packet, remoteAddress) != Socket::Status::Done) return; if (!Globals::Networking->isConnectedAddress(remoteAddress)) return; ushort sequence = 0; packet >> sequence; // TODO: Rejection threshold if (sequence == 0 || sequence <= lastSequence) { PrintDebug(">> Received out of order packet. Rejecting."); lastSequence = sequence % USHRT_MAX; return; } lastSequence = sequence % USHRT_MAX; } PlayerNumber pnum = -1; if (netStat) addBytesReceived(packet.getDataSize()); while (!packet.endOfPacket()) { MessageID newType; packet >> newType; // TODO: Re-implement packet loop failsafe using read offset. switch (newType) { case MessageID::None: PrintDebug("\a>> Reached end of packet."); break; case MessageID::Count: PrintDebug(">> Received message count?! Malformed packet warning!"); break; case MessageID::N_Disconnect: PrintDebug(">> Received disconnect request from client."); Globals::Networking->Disconnect(); break; case MessageID::N_Ready: { MessageID waitID; packet >> waitID; auto it = waitRequests.find(waitID); if (it != waitRequests.end()) { it->second = true; } else { waitRequests[waitID] = true; } break; } case MessageID::N_PlayerNumber: packet >> pnum; break; // TODO: verification that this is from the host case MessageID::N_SetPlayer: { PlayerNumber changed; packet >> changed; SetPlayerNumber(changed); break; } case MessageID::S_KeepAlive: receivedKeepalive = Millisecs(); packet.seekRead(sizeof(ushort), SEEK_CUR); break; default: { if (newType < MessageID::N_END) { packet.clear(); break; } ushort length; packet >> length; AddTypeReceived(newType, length, protocol == Protocol::TCP); if (pnum >= 0) { if (receiveSystem(newType, pnum, packet)) break; if (pnum != playerNum) { if (!writePlayer) inPlayer.Copy(Player[pnum]); if (receivePlayer(newType, pnum, packet)) { if (GameState >= GameState::Ingame) { writePlayer = false; PlayerObject::WritePlayer(Player[pnum], &inPlayer); } break; } } if (receiveMenu(newType, pnum, packet)) break; } if (runMessageHandler(newType, pnum, packet)) break; PrintDebug("\t\t[P%d] Skipping %d bytes for id %02d", pnum, length, newType); packet.seekRead(length, SEEK_CUR); break; } } } }
void NetPlayClient::Send(sf::Packet& packet) { ENetPacket* epac = enet_packet_create(packet.getData(), packet.getDataSize(), ENET_PACKET_FLAG_RELIABLE); enet_peer_send(m_server, 0, epac); }
void Manager::send(const Client &client, const sf::Packet &packet) { assert(client.getPeer()); ENetPacket *netPacket = enet_packet_create(packet.getData(), packet.getDataSize(), 0); enet_peer_send(client.getPeer(), 0, netPacket); }
void Manager::broadcast(const sf::Packet &packet) { assert(_host); ENetPacket *netPacket = enet_packet_create(packet.getData(), packet.getDataSize(), 0); enet_host_broadcast(_host, 0, netPacket); }
// called from ---NETPLAY--- thread unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player) { MessageId mid; packet >> mid; INFO_LOG(NETPLAY, "Got client message: %x", mid); // don't need lock because this is the only thread that modifies the players // only need locks for writes to m_players in this thread switch (mid) { case NP_MSG_CHAT_MESSAGE: { std::string msg; packet >> msg; // send msg to other clients sf::Packet spac; spac << (MessageId)NP_MSG_CHAT_MESSAGE; spac << player.pid; spac << msg; SendToClients(spac, player.pid); } break; case NP_MSG_PAD_DATA: { // if this is pad data from the last game still being received, ignore it if (player.current_game != m_current_game) break; sf::Packet spac; spac << static_cast<MessageId>(NP_MSG_PAD_DATA); while (!packet.endOfPacket()) { PadMapping map; packet >> map; // If the data is not from the correct player, // then disconnect them. if (m_pad_map.at(map) != player.pid) { return 1; } GCPadStatus pad; packet >> pad.button >> pad.analogA >> pad.analogB >> pad.stickX >> pad.stickY >> pad.substickX >> pad.substickY >> pad.triggerLeft >> pad.triggerRight >> pad.isConnected; if (m_host_input_authority) { m_last_pad_status[map] = pad; if (!m_first_pad_status_received[map]) { m_first_pad_status_received[map] = true; SendFirstReceivedToHost(map, true); } } else { spac << map << pad.button << pad.analogA << pad.analogB << pad.stickX << pad.stickY << pad.substickX << pad.substickY << pad.triggerLeft << pad.triggerRight << pad.isConnected; } } if (!m_host_input_authority) SendToClients(spac, player.pid); } break; case NP_MSG_PAD_HOST_POLL: { PadMapping pad_num; packet >> pad_num; sf::Packet spac; spac << static_cast<MessageId>(NP_MSG_PAD_DATA); if (pad_num < 0) { for (size_t i = 0; i < m_pad_map.size(); i++) { if (m_pad_map[i] == -1) continue; const GCPadStatus& pad = m_last_pad_status[i]; spac << static_cast<PadMapping>(i) << pad.button << pad.analogA << pad.analogB << pad.stickX << pad.stickY << pad.substickX << pad.substickY << pad.triggerLeft << pad.triggerRight << pad.isConnected; } } else if (m_pad_map.at(pad_num) != -1) { const GCPadStatus& pad = m_last_pad_status[pad_num]; spac << pad_num << pad.button << pad.analogA << pad.analogB << pad.stickX << pad.stickY << pad.substickX << pad.substickY << pad.triggerLeft << pad.triggerRight << pad.isConnected; } SendToClients(spac); } break; case NP_MSG_WIIMOTE_DATA: { // if this is Wiimote data from the last game still being received, ignore it if (player.current_game != m_current_game) break; PadMapping map = 0; u8 size; packet >> map >> size; std::vector<u8> data(size); for (size_t i = 0; i < data.size(); ++i) packet >> data[i]; // If the data is not from the correct player, // then disconnect them. if (m_wiimote_map.at(map) != player.pid) { return 1; } // relay to clients sf::Packet spac; spac << (MessageId)NP_MSG_WIIMOTE_DATA; spac << map; spac << size; for (const u8& byte : data) spac << byte; SendToClients(spac, player.pid); } break; case NP_MSG_PONG: { const u32 ping = (u32)m_ping_timer.GetTimeElapsed(); u32 ping_key = 0; packet >> ping_key; if (m_ping_key == ping_key) { player.ping = ping; } sf::Packet spac; spac << (MessageId)NP_MSG_PLAYER_PING_DATA; spac << player.pid; spac << player.ping; SendToClients(spac); } break; case NP_MSG_START_GAME: { packet >> player.current_game; } break; case NP_MSG_STOP_GAME: { if (!m_is_running) break; m_is_running = false; // tell clients to stop game sf::Packet spac; spac << (MessageId)NP_MSG_STOP_GAME; std::lock_guard<std::recursive_mutex> lkp(m_crit.players); SendToClients(spac); } break; case NP_MSG_GAME_STATUS: { u32 status; packet >> status; m_players[player.pid].game_status = static_cast<PlayerGameStatus>(status); // send msg to other clients sf::Packet spac; spac << static_cast<MessageId>(NP_MSG_GAME_STATUS); spac << player.pid; spac << status; SendToClients(spac); } break; case NP_MSG_IPL_STATUS: { bool status; packet >> status; m_players[player.pid].has_ipl_dump = status; } break; case NP_MSG_TIMEBASE: { u64 timebase = Common::PacketReadU64(packet); u32 frame; packet >> frame; if (m_desync_detected) break; std::vector<std::pair<PlayerId, u64>>& timebases = m_timebase_by_frame[frame]; timebases.emplace_back(player.pid, timebase); if (timebases.size() >= m_players.size()) { // we have all records for this frame if (!std::all_of(timebases.begin(), timebases.end(), [&](std::pair<PlayerId, u64> pair) { return pair.second == timebases[0].second; })) { int pid_to_blame = -1; for (auto pair : timebases) { if (std::all_of(timebases.begin(), timebases.end(), [&](std::pair<PlayerId, u64> other) { return other.first == pair.first || other.second != pair.second; })) { // we are the only outlier pid_to_blame = pair.first; break; } } sf::Packet spac; spac << (MessageId)NP_MSG_DESYNC_DETECTED; spac << pid_to_blame; spac << frame; SendToClients(spac); m_desync_detected = true; } m_timebase_by_frame.erase(frame); } } break; case NP_MSG_MD5_PROGRESS: { int progress; packet >> progress; sf::Packet spac; spac << static_cast<MessageId>(NP_MSG_MD5_PROGRESS); spac << player.pid; spac << progress; SendToClients(spac); } break; case NP_MSG_MD5_RESULT: { std::string result; packet >> result; sf::Packet spac; spac << static_cast<MessageId>(NP_MSG_MD5_RESULT); spac << player.pid; spac << result; SendToClients(spac); } break; case NP_MSG_MD5_ERROR: { std::string error; packet >> error; sf::Packet spac; spac << static_cast<MessageId>(NP_MSG_MD5_ERROR); spac << player.pid; spac << error; SendToClients(spac); } break; case NP_MSG_SYNC_SAVE_DATA: { MessageId sub_id; packet >> sub_id; switch (sub_id) { case SYNC_SAVE_DATA_SUCCESS: { if (m_start_pending) { m_save_data_synced_players++; if (m_save_data_synced_players >= m_players.size() - 1) { m_dialog->AppendChat(GetStringT("All players synchronized.")); StartGame(); } } } break; case SYNC_SAVE_DATA_FAILURE: { m_dialog->AppendChat( StringFromFormat(GetStringT("%s failed to synchronize.").c_str(), player.name.c_str())); m_dialog->OnSaveDataSyncFailure(); m_start_pending = false; } break; default: PanicAlertT( "Unknown SYNC_SAVE_DATA message with id:%d received from player:%d Kicking player!", sub_id, player.pid); return 1; } } break; default: PanicAlertT("Unknown message with id:%d received from player:%d Kicking player!", mid, player.pid); // unknown message, kick the client return 1; } return 0; }
void NetPlayServer::Send(ENetPeer* socket, const sf::Packet& packet) { ENetPacket* epac = enet_packet_create(packet.getData(), packet.getDataSize(), ENET_PACKET_FLAG_RELIABLE); enet_peer_send(socket, 0, epac); }