Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: [Packet] Crash après réception d'une chaîne de 16 caractères ou plus  (Lu 1561 fois)

0 Membres et 1 Invité sur ce sujet

mazoute

  • Newbie
  • *
  • Messages: 1
    • Voir le profil
Bonjour,

Je travaille actuellement sur un projet en C++ (langage dans lequel je suis loin d'être un expert) qui comporte un chat utilisant des sockets TCP.
Je fais face depuis quelques jours à un bug dont je ne peux déterminer la source (problème de conception ? bug SFML ?).
Je n'ai pas trouvé de bug à ce sujet concernant sfml-network sur le github.

Pour faire simple, j'utilise des structures qui représentent les données que j'envoie. J'ai implémenté les surcharges d'opérateurs adéquates pour l'insertion et l'extraction dans les sf::Packet.

A la connexion le client envoie ses identifiants, sous forme de 2 std::string (username et password). Sauf que, si l'une des chaînes dépasse 16 caractères, le serveur plante après avoir reçu et extrait les données correctement.

Le plus bizarre, c'est que le bug apparait avec la SFML 2.1, mais pas avec la 2.0.

J'ai réduit tout mon projet à un bout de code de ~180 lignes. (Je peux pas faire plus minimal que ça je pense). Comporte les côtés client & serveur.

Vous remarquerez que les surcharges des 2 opérateurs diffèrent. En effet, à l'envoi j'insère un identifiant qui permettra au serveur de savoir que c'est un "AuthPacket" et pas autre chose (un message dans le chat, un message privé, etc..).
Pour l'extraction, cet identifiant n'apparaît pas puisque le serveur l'extrait du sf::Packet juste avant.

Donc le serveur plante après le if(){} "reading auth datas"

#include <iostream>
#include <sstream>
#include <vector>
#include <SFML/Network.hpp>
#define NET_PORT                11111
#define PACKET_AUTH             5

#define CLIENT_USERNAME "username"
#define CLIENT_SHA1PWD  "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8"

// ----------------
// -- PROTOTYPES --
// ----------------
void Client();
void Server();

// -------------
// -- STRUCTS --
// -------------
struct AuthPacket
{
        AuthPacket(std::string user = "", std::string sha1password = "")
        : user(user), sha1password(sha1password)
        {}

        std::string user, sha1password;
};

// ----------------------------------------------
// -- SURCHARGES OPERATEUR LIEES AU sf::PACKET --
// ----------------------------------------------
// Serveur: Réception
sf::Packet& operator >> (sf::Packet& packet, AuthPacket& authPacket)
{
        return packet  >> authPacket.user >> authPacket.sha1password;
}


// Client: Envoi
sf::Packet& operator << (sf::Packet& packet, const AuthPacket authPacket)
{
        return packet << (sf::Uint32) PACKET_AUTH << authPacket.user << authPacket.sha1password;
}



// ----------
// -- MAIN --
// ----------
int main(int argc, char** argv)
{

        std::cout << "'c' to start a client / 's' to start a server: ";
        std::string input;
        std::cin >> input;

        if(input == "s")
                Server();
        else if(input == "c")
                Client();

        while(1){}
        exit(EXIT_SUCCESS);
}

// -------------
// -- METHODS --
// -------------
void Server() {
        // clients
        std::vector<std::shared_ptr<sf::TcpSocket>> clients;

        // sfml network stuff
        sf::TcpListener listener;
        sf::SocketSelector selector;
        sf::Socket::Status status = listener.listen(NET_PORT);


        if(status != sf::Socket::Status::Done) {
                exit(EXIT_FAILURE);
        }

        selector.add(listener);

        // main loop
        while(true)
        {

                if(selector.wait(sf::Time(sf::microseconds(50))))
                {

                        // check server socket
                        if(selector.isReady(listener))
                        {
                                std::shared_ptr<sf::TcpSocket> client = std::make_shared<sf::TcpSocket>();
                                if(listener.accept(*client) == sf::Socket::Done)
                                {
                                        std::cout << "New client connected" << std::endl;
                                        selector.add(*client);
                                        clients.push_back(client);
                                }
                        }

                        // check clients sockets
                        for(unsigned int i = 0; i < clients.size(); i++)
                        {
                                std::shared_ptr<sf::TcpSocket> client = clients[i];
                                sf::Packet packet;

                                // client message
                                if (selector.isReady(*client))
                                {
                                        sf::Socket::Status status = client->receive(packet);

                                        // packet status : OK
                                        if(status == sf::Socket::Status::Done)
                                        {
                                                std::cout << "Received packet" << std::endl;

                                                // packet code ?
                                                sf::Uint32 packetCode;
                                                if(packet >> packetCode) {
                                                        std::cout << "< Packet code: "<< packetCode << std::endl;

                                                        // packet code == AUTH
                                                        if(packetCode == (sf::Uint32) PACKET_AUTH)
                                                        {
                                                                // reading auth datas
                                                                AuthPacket authPacket;
                                                                if(packet >> authPacket)
                                                                {
                                                                        std::cout << "< Packet content: " << authPacket.user << " / " << authPacket.sha1password << std::endl;
                                                                }
                                                        }
                                                }

                                        } // -- eof if(status == sf::Socket::Status::Done)
                                        else {
                                                selector.remove(*client);
                                        }

                                } // -- eof if (selector.isReady(*client))

                        } // -- eof clients loop

                } // -- eof if(selector.wait(sf::Time(sf::microseconds(50))))

        } // -- eof main loop
}

void Client() {
        sf::Socket::Status status = sf::Socket::Error;
        sf::TcpSocket socket;

        // connection attempt
        if (status == sf::Socket::Disconnected || status == sf::Socket::Error)
        {
                        socket.disconnect();
                        socket.setBlocking(false);
                        unsigned int max_retry = 50;
                        unsigned int attempt = 0;
                        while(true) {
                                status = socket.connect("127.0.0.1", NET_PORT);
                                if(status == sf::Socket::Status::Done)
                                        break;
                                sf::sleep(sf::seconds(1));
                        }

        }

        // connection OK
        if(status == sf::Socket::Status::Done)
        {
                // sending auth packet
                AuthPacket authPacket(CLIENT_USERNAME, CLIENT_SHA1PWD);
                sf::Packet packet;
                std::cout << "> Packet content: "<<  authPacket.user << " / " << authPacket.sha1password << std::endl;

                packet << authPacket;
                std::cout << "- Sent packet with status: " << socket.send(packet) << std::endl;


                socket.disconnect();

        }
}
 

Merci aux devs courageux qui oseront s'attaquer à mon problème!  :D