SFML community forums

Help => Network => Topic started by: Lolilolight on June 14, 2014, 11:26:56 am

Title: Trouble while receiving data. (TCP mode)
Post by: Lolilolight on June 14, 2014, 11:26:56 am
Hi,
I'm trying to send encrypted packet, it works perfectly when i put and extract data from a packet (without sending it with a TCPSocket)

But when I want to send the encrypted data with a TCP Socket, sometimes the data sent and the data received are not the same!

I'm always forced to launch the server again when it happens.

And sometimes the ports doesn't close immediately after it crashes, I must wait for a few minutes.

Here is a case where it crashe :

The encrypted data that I send (for example) is like this :

2????-;??c?Sg?#&IRB?5_p;???

And the data that I receive is like that :

2���-;��c�Sg�#&IRB�5_��p;���

There are too much data so, I think I should report this as an issue.
Title: Re: Trouble while receiving data. (TCP mode)
Post by: Ixrec on June 14, 2014, 11:34:06 am
Please show a complete and minimal code example that reproduces the problem.  Otherwise it's impossible to know whether it's a mistake in your code or a real issue with sf::Packet.
Title: Re: Trouble while receiving data. (TCP mode)
Post by: Laurent on June 14, 2014, 02:36:35 pm
Do you do it on purpose? I mean, posting vague questions and blaming SFML. Everytime you open a new discussion, we tell you to provide a complete and minimal example that reproduces the problem. Everytime we tell you to stop blaming SFML and have a look at your own code first. And you're still ignoring us. Next time I won't be so patient.
Title: Re: Trouble while receiving data. (TCP mode)
Post by: Lolilolight on June 14, 2014, 03:18:12 pm
Here is the code, when I connect to the first time it works, but the second time it crash :

The server :

#include "odfaeg/Network/network.h"

using namespace odfaeg;
using namespace sf;
int main() {
    SocketSelector selector;
    TcpListener listener;
    listener.listen(9999);
    selector.add(listener);
    TcpSocket socket;
    bool running = true;
    std::vector<TcpSocket*> clients;
    std::vector<TcpSocket*>::iterator it;
    bool keyReceived = false, pbKeyReceived = false;
    while (running) {
        if (selector.wait()) {
            if (selector.isReady(listener)) {
                TcpSocket *client = new TcpSocket();
                if (listener.accept(*client) == Socket::Done) {
                    std::cout<<"connect"<<std::endl;
                    selector.add(*client);
                    clients.push_back(client);
                }
            }
            for (it = clients.begin(); it != clients.end();it++) {
                TcpSocket& client = **it;

                if (selector.isReady(client)) {
                    if (keyReceived && pbKeyReceived) {
                        SymEncPacket packet;
                        if (client.receive(packet) == Socket::Done) {

                            std::string message;
                            packet>>message;
                            std::cout<<"received : "<<message<<std::endl;
                        } else {
                            std::cout<<"disconnect"<<std::endl;
                            selector.remove(client);
                            it = clients.erase(it);
                            delete &client;
                            it--;
                        }
                    } else if (!keyReceived) {
                        Packet packet;
                        if (client.receive(packet) == Socket::Done) {
                            std::string message;
                            packet>>message;
                            if (message == "GETKEY") {
                                unsigned char* out = NULL;
                                int length = Rsa::getCertificate(&out);
                                string key ((char*) out, length);
                                std::cout<<"key : "<<key<<std::endl;
                                Packet resp;
                                resp<<key;
                                client.send(resp);
                                keyReceived = true;
                            }
                        } else {
                            selector.remove(client);
                            it = clients.erase(it);
                            delete &client;
                            it--;
                        }
                    } else {
                        EncryptedPacket packet;
                        if (client.receive(packet) == Socket::Done) {
                            std::string message;
                            packet>>message;
                            packet.clear();
                            if (message == "GETPBKEY") {
                                message = std::string(AES_ENC::getKey())+"-"+std::string(AES_ENC::getIv());
                                std::cout<<"message : "<<message<<std::endl;
                                packet<<message;
                                client.send(packet);
                                pbKeyReceived = true;
                            }
                        } else {
                            selector.remove(client);
                            it = clients.erase(it);
                            delete &client;
                            it--;
                        }
                    }
                }
            }

        }
    }
}
 

The client :

#include "odfaeg/Network/network.h"
int main() {  
    TcpSocket socket;
    socket.connect(IpAddress::LocalHost, 9999);
    Packet packet;
    std::string message = "GETKEY";
    packet<<message;
    socket.send(packet);
    packet.clear();
    if (socket.receive(packet) == Socket::Done) {
        message = "";
        packet>>message;
        std::cout<<"message : "<<message<<std::endl;
        Rsa::setCertificate(reinterpret_cast<const unsigned char*>(message.c_str()), message.length());
        message = "GETPBKEY";
        EncryptedPacket req;
        req<<message;
        socket.send(req);
    }
    EncryptedPacket ep;
    if (socket.receive(ep) == Socket::Done) {
        message = "";
        ep>>message;
        std::cout<<"message : "<<message<<std::endl;;
        std::vector<string> parts = split(message, "-");
        AES_ENC::setKey(const_cast<char*>(parts[0].c_str()));
        AES_ENC::setIv(const_cast<char*>(parts[1].c_str()));
    }
    return 0;
}
 


Openssl works well, but, when I want to send packet it crash :

Code: [Select]
#0 0x7ffff6e50a30 __cxa_throw() (/usr/lib/x86_64-linux-gnu/libstdc++.so.6:??)
#1 0x7ffff6e50f8d operator new(unsigned long) () (/usr/lib/x86_64-linux-gnu/libstdc++.so.6:??)
#2 0x7ffff7bd3682 std::vector<char, std::allocator<char> >::_M_fill_insert(__gnu_cxx::__normal_iterator<char*, std::vector<char, std::allocator<char> > >, unsigned long, char const&) () (/usr/local/lib/libsfml-network.so.2:??)
#3 0x7ffff7bd324d sf::Packet::append(void const*, unsigned long) () (/usr/local/lib/libsfml-network.so.2:??)
#4 0x4376ad odfaeg::SymEncPacket::onReceive(this=0x7fffffffe2b0, data=<optimized out>, dataSize=<optimized out>) (/home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Network/symEncPacket.cpp:17)
#5 0x7ffff7bd4af4 sf::TcpSocket::receive(sf::Packet&) () (/usr/local/lib/libsfml-network.so.2:??)
#6 0x434fef main() (/home/laurent/Développement/Projets-c++/ODFAEG-DEMO-SERVER/main.cpp:35)

It seems that the socket is not erased from the std::vector, but why ?
Title: Re: Trouble while receiving data. (TCP mode)
Post by: Lolilolight on June 14, 2014, 03:38:36 pm
Ok I've found why, i've just forgotten to reset my boolean vars keyReceived and pbKeyReceived to false when the client disconnect.

Now I'll look for the other bug.
Title: Re: Trouble while receiving data. (TCP mode)
Post by: Nexus on June 14, 2014, 03:50:56 pm
Why don't you spend 5 minutes on using a debugger before posting here?

Apart from that, your code is not complete. It includes ODFAEG headers, so how do we know what's right and wrong? Why do you constantly ignore everything we say?
Title: Re: Trouble while receiving data. (TCP mode)
Post by: Lolilolight on June 14, 2014, 04:17:29 pm
Here is a source code with repoduce the bug :
First of all odfaeg is not a problem, it encrypt and decrypt everything well, here is the code of the encryptions class that I wrote :

#include "../../../include/odfaeg/Network/rsa.h"
#include <stdlib.h>
#include <iostream>
namespace odfaeg {
int Rsa::size = 0;
X509* Rsa::x = X509_new();
EVP_PKEY* Rsa::evp_pkey = EVP_PKEY_new();
BIO* Rsa::pub = BIO_new(BIO_s_mem());
size_t Rsa::pub_len = 0;
char* Rsa::pub_key = NULL;
RSA* Rsa::keypair = generateKeys(2048);
int Rsa::getCertificate (unsigned char **out) {
    int len= i2d_X509(x, out);
    return len;
}

void Rsa::setCertificate(const unsigned char* in, int length) {
    x = d2i_X509(NULL,&in,length);
    evp_pkey = X509_get_pubkey(x);
    keypair = EVP_PKEY_get1_RSA(evp_pkey);
    PEM_write_bio_RSAPublicKey(pub, keypair);
    pub_len = BIO_pending(pub);
    free(pub_key);
    pub_key = (char*)malloc(pub_len + 1);
    BIO_read(pub, pub_key, pub_len);
    pub_key[pub_len] = '\0';
}
int Rsa::encryptWithPrKey (const char *data, size_t dataSize, char **encData) {
    *encData = new char[RSA_size(keypair)];
    int encDataLen = RSA_private_encrypt(dataSize, (unsigned char*) data, (unsigned char*)*encData, keypair, RSA_PKCS1_PADDING);
    if (encDataLen == -1) {
        char* err = (char*) malloc(130);
        ERR_load_crypto_strings();
        ERR_error_string(ERR_get_error(), err);
        fprintf(stderr, "Error encrypting message: %s\n", err);
        free(err);
        return FAILURE;
    }
    return encDataLen;
}
int Rsa::decryptWithPrKey (const char *encData, size_t dataSize, char **data) {
    char *msg = new char[dataSize];
    int dataLen = RSA_private_decrypt(RSA_size(keypair), (unsigned char*) encData, (unsigned char*)msg, keypair, RSA_PKCS1_OAEP_PADDING);
    if (dataLen == -1) {
        char* err = (char*) malloc(130);
        ERR_load_crypto_strings();
        ERR_error_string(ERR_get_error(), err);
        fprintf(stderr, "Error encrypting message: %s\n", err);
        free(err);
    }
    *data = new char[dataLen+1];
    memcpy(*data, msg, dataLen);
    (*data)[dataLen] = '\0';
    delete[] msg;
    return dataLen;
}
int Rsa::encryptWithPbKey (const char *data, size_t dataSize, char **encData) {
    *encData = new char[RSA_size(keypair)];
    int encDataLen = RSA_public_encrypt(dataSize, (unsigned char*) data, (unsigned char*) *encData, keypair, RSA_PKCS1_OAEP_PADDING);
    if (encDataLen == -1) {
        char* err = (char*) malloc(130);
        ERR_load_crypto_strings();
        ERR_error_string(ERR_get_error(), err);
        fprintf(stderr, "Error encrypting message: %s\n", err);
        free(err);
        return FAILURE;
    }
    return encDataLen;
}
int Rsa::decryptWithPbKey (const char *encData, size_t dataSize, char **data) {
    char *msg = new char[dataSize];
    int dataLen = RSA_public_decrypt(RSA_size(keypair), (unsigned char*) encData, (unsigned char*) msg, keypair, RSA_PKCS1_PADDING);
    if (dataLen == -1) {
        char* err = (char*) malloc(130);

        ERR_load_crypto_strings();
        ERR_error_string(ERR_get_error(), err);
        fprintf(stderr, "Error encrypting message: %s\n", err);
        free(err);
        return FAILURE;
    }
    *data = new char[dataLen+1];
    memcpy(*data, msg, dataLen);
    (*data)[dataLen] = '\0';
    delete[] msg;
    return dataLen;
}
}
 
#include "../../../include/odfaeg/Network/aes.h"
namespace odfaeg {
using namespace std;
int AES_ENC::size = 0;
unsigned char* AES_ENC::key = new unsigned char[32];
unsigned char* AES_ENC::iv = new unsigned char[32];
unsigned char* AES_ENC::aesSalt = new unsigned char[8];
EVP_CIPHER_CTX* AES_ENC::e_ctx = new EVP_CIPHER_CTX;
EVP_CIPHER_CTX* AES_ENC::d_ctx = new EVP_CIPHER_CTX;
unsigned char* AES_ENC::aesPass = generateKey(256);

int AES_ENC::encrypt(const char* data, size_t dataSize, char **encData) {
    int blockLen  = 0;
    int encDataLen  = 0;
    *encData = new char[dataSize + AES_BLOCK_SIZE];
    if (!EVP_EncryptInit_ex(e_ctx,  EVP_aes_256_cbc(), nullptr, key, iv))
        return FAILURE;
    if (!EVP_EncryptUpdate(e_ctx, (unsigned char*) *encData, &blockLen, (unsigned char*) data, (int) dataSize))
        return FAILURE;
    encDataLen += blockLen;
    if(!EVP_EncryptFinal_ex(e_ctx, (unsigned char*) (*encData+encDataLen), &blockLen)) {
        return FAILURE;
    }
    EVP_CIPHER_CTX_cleanup(e_ctx);
    return encDataLen + blockLen;
}
int AES_ENC::decrypt(const char* encData, size_t dataSize, char **data) {
    int dataLen   = 0;
    int blockLen = 0;
    *data = new char[dataSize+AES_BLOCK_SIZE];
    if (!EVP_DecryptInit_ex(d_ctx, EVP_aes_256_cbc(), nullptr, key, iv))
        return FAILURE;
    if (!EVP_DecryptUpdate(d_ctx, (unsigned char*) *data, &blockLen, (unsigned char*) encData, (int) dataSize))
        return FAILURE;
    dataLen += blockLen;
    if (!EVP_DecryptFinal_ex(d_ctx, (unsigned char*) (*data+dataLen), &blockLen)) {
        return FAILURE;
    }
    dataLen += blockLen;
    EVP_CIPHER_CTX_cleanup(d_ctx);
    return dataLen;
}
void AES_ENC::setKey(char* sKey) {
   strncpy((char*) key, sKey, size / 8);
}
void AES_ENC::setIv(char* sIv) {
   strncpy((char*) iv, sIv, size / 8);
}
char* AES_ENC::getKey() {
   return (char*) key;
}
char* AES_ENC::getIv() {
   return (char*) iv;
}
}
 

Here is the redefinition of the sf::Packet :

#include "../../../include/odfaeg/Network/symEncPacket.h"
namespace odfaeg {
using namespace std;
using namespace sf;

const void* SymEncPacket::onSend (size_t& dataSize) {
    char* buffer = "";
    dataSize = AES_ENC::encrypt(static_cast<const char*> (getData()), getDataSize(), &buffer);  
    return &buffer[0];
}
void SymEncPacket::onReceive (const void* data, size_t dataSize) {
    char* buffer = "";
    std::size_t dstSize = 0;    
    dstSize = AES_ENC::decrypt(static_cast<const char*> (data), dataSize, &buffer);
    append(&buffer[0], dstSize);
}
}
 

#include "../../../include/odfaeg/Network/encryptedPacket.h"
#include "../../../include/odfaeg/Network/network.h"
namespace odfaeg {
using namespace std;
using namespace sf;

const void* EncryptedPacket::onSend (size_t& dataSize) {
    char* buffer = NULL;
    if (Network::getCliInstance().isRunning())
        dataSize = Rsa::encryptWithPbKey(static_cast<const char*> (getData()), getDataSize(), &buffer);
    else
        dataSize = Rsa::encryptWithPrKey(static_cast<const char*> (getData()), getDataSize(), &buffer);
    return &buffer[0];
}
void EncryptedPacket::onReceive (const void* data, size_t dataSize) {
    char* buffer = NULL;
    int newDataSize = 0;
    if (Network::getCliInstance().isRunning())
        newDataSize = Rsa::decryptWithPbKey(static_cast<const char*> (data), dataSize, &buffer);
    else
        newDataSize = Rsa::decryptWithPrKey(static_cast<const char*> (data), dataSize, &buffer);
    append(&buffer[0], newDataSize);
}
}
 

It extract and put data in packets very well, the problem is when I want to send the packet with the sf::TcpSocket :

The server :

int main() {
    Network::startSrv(10000, 10001);
    /*MyServerAppli app;
    return app.exec();*/

    SocketSelector selector;
    TcpListener listener;
    listener.listen(9999);
    selector.add(listener);
    TcpSocket socket;
    bool running = true;
    std::vector<TcpSocket*> clients;
    std::vector<TcpSocket*>::iterator it;
    bool keyReceived = false, pbKeyReceived = false;
    while (running) {
        if (selector.wait()) {
            if (selector.isReady(listener)) {
                TcpSocket *client = new TcpSocket();
                if (listener.accept(*client) == Socket::Done) {
                    std::cout<<"connect"<<std::endl;
                    selector.add(*client);
                    clients.push_back(client);
                }
            }
            for (it = clients.begin(); it != clients.end();it++) {
                TcpSocket& client = **it;

                if (selector.isReady(client)) {

                    if (keyReceived && pbKeyReceived) {
                        SymEncPacket packet;
                        if (client.receive(packet) == Socket::Done) {

                            std::string message;
                            packet>>message;
                            std::cout<<"received : "<<message<<std::endl;
                            packet.clear();
                            message = "SENDRESOURCES";
                            packet<<message;
                            client.send(packet);
                        } else {
                            std::cout<<"disconnect"<<std::endl;
                            selector.remove(client);
                            it = clients.erase(it);
                            delete &client;
                            it--;
                            keyReceived = pbKeyReceived = false;
                        }
                    } else if (!keyReceived) {
                        Packet packet;
                        if (client.receive(packet) == Socket::Done) {
                            std::string message;
                            packet>>message;
                            if (message == "GETKEY") {
                                unsigned char* out = NULL;
                                int length = Rsa::getCertificate(&out);
                                string key ((char*) out, length);
                                Packet resp;
                                resp<<key;
                                client.send(resp);
                                keyReceived = true;
                            }
                        } else {
                            selector.remove(client);
                            it = clients.erase(it);
                            delete &client;
                            it--;
                            keyReceived = pbKeyReceived = false;
                        }
                    } else {
                        EncryptedPacket packet;
                        if (client.receive(packet) == Socket::Done) {
                            std::string message;
                            packet>>message;
                            packet.clear();
                            if (message == "GETPBKEY") {
                                message = std::string(AES_ENC::getKey())+"-"+std::string(AES_ENC::getIv());
                                packet<<message;
                                client.send(packet);
                                pbKeyReceived = true;
                            }
                        } else {
                            selector.remove(client);
                            it = clients.erase(it);
                            delete &client;
                            it--;
                            keyReceived = pbKeyReceived = false;
                        }
                    }
                }
            }

        }
    }
}
 

The client :

int main() {  
    Network::startCli(10000, 10001, sf::IpAddress::LocalHost);
    TcpSocket socket;
    socket.connect(IpAddress::LocalHost, 9999);
    Packet packet;
    std::string message = "GETKEY";
    packet<<message;
    socket.send(packet);
    packet.clear();
    if (socket.receive(packet) == Socket::Done) {
        message = "";
        packet>>message;        
        Rsa::setCertificate(reinterpret_cast<const unsigned char*>(message.c_str()), message.length());
        message = "GETPBKEY";
        EncryptedPacket req;
        req<<message;
        socket.send(req);
    }
    EncryptedPacket ep;
    if (socket.receive(ep) == Socket::Done) {
        message = "";
        ep>>message;      
        std::vector<string> parts = split(message, "-");
        AES_ENC::setKey(const_cast<char*>(parts[0].c_str()));
        AES_ENC::setIv(const_cast<char*>(parts[1].c_str()));
        SymEncPacket sep;
        message = "GETRESOURCES";
        sep<<message;
        message = "";
        sep>>message;
        std::cout<<message<<std::endl;
        socket.send(sep);
    }
    SymEncPacket sep;
    if (socket.receive(sep) == Socket::Done) {
        message = "";
        sep>>message;
        std::cout<<message<<std::endl;
    }
    return 0;
}
 

Sometimes the message is not transfered correctly, it seems that SFML fails to send some special caracters.
Title: Re: Trouble while receiving data. (TCP mode)
Post by: Ixrec on June 14, 2014, 04:22:26 pm
What are these "special characters" you think it's failing on?  Is there any reason you can't produce a minimal SFML-only example that fails to send those particular characters?  Until we see one this is far more likely to be an odfaeg error than anything else.
Title: Re: Trouble while receiving data. (TCP mode)
Post by: Nexus on June 14, 2014, 04:40:46 pm
First of all odfaeg is not a problem
Then exclude it from your code! Nobody cares about encryption if the problem lies totally elsewhere.

Write only one main() function that contains all the code. Include only SFML headers. That is minimal.
Title: Re: Trouble while receiving data. (TCP mode)
Post by: Lolilolight on June 14, 2014, 04:50:42 pm
Ok so I'll try to find the char that SFML fail to send, and make a minimal souce code.
Title: Re: Trouble while receiving data. (TCP mode)
Post by: Lolilolight on June 14, 2014, 06:05:19 pm
I've found the bug, apparently it was because I reallocated the buffer :

#include "../../../include/odfaeg/Network/symEncPacket.h"
namespace odfaeg {
using namespace std;
using namespace sf;

const void* SymEncPacket::onSend (size_t& dataSize) {
    char* buffer;
    dataSize = AES_ENC::encrypt(static_cast<const char*> (getData()), getDataSize(), &buffer);
    return &buffer[0];
}
void SymEncPacket::onReceive (const void* data, size_t dataSize) {
    char* buffer;
    std::size_t dstSize;
    dstSize = AES_ENC::decrypt(static_cast<const char*> (data), dataSize, &buffer);
    append(&buffer[0], dstSize);
}
}
 

So I've just declared the vars without initializing them and it works.
Title: Re: Trouble while receiving data. (TCP mode)
Post by: zsbzsb on June 14, 2014, 06:13:02 pm
And once again...................... ODFAEG WAS THE PROBLEM

Next time don't post here unless you exclude your library and have something with pure SFML that has an issue.
Title: Re: Trouble while receiving data. (TCP mode)
Post by: Lolilolight on June 14, 2014, 06:57:51 pm
it was the new here which didn't erased the old data very well :

int blockLen  = 0;
    int encDataLen  = 0;
    *encData = new char[dataSize + AES_BLOCK_SIZE];
 

so I'm not sure that ODFAEG was the problem.

Title: Re: Trouble while receiving data. (TCP mode)
Post by: Lolilolight on June 14, 2014, 08:02:37 pm
It's not over yet.

It seems that sometimes the packet is null when I received the data in a std::thread, did I do something wrong ?

void SrkServer::run () {
    running = true;
    while (running) {

        if (selector.wait()) {
            lock_guard<recursive_mutex> locker (rec_mutex);
            if (selector.isReady(listener)) {
                std::cout<<"client connected"<<std::endl;
                TcpSocket *client = new TcpSocket();
                if (listener.accept(*client) == Socket::Done) {
                    selector.add(*client);
                    clients.push_back(client);
                    Network::addUser(*client, udpSocket);
                } else {
                    delete client;
                }
            }
            if (selector.isReady(udpSocket)) {
                SymEncPacket packet;
                string request;
                IpAddress sender;
                short unsigned int port;
                if (udpSocket.receive(packet, sender, port) == Socket::Done) {
                    packet>>request;
                    User* user = Network::getUser(sender);
                    if (user != NULL) {
                        if (user->getRemotePortUDP() != port)
                            user->setRemotePortUDP(port);
                        Network::addRequest (user, request);
                    } else {
                        cout<<"this message don't provide from a valid client!"<<endl;
                    }
                }
            }
            vector<TcpSocket*>::iterator it;
            for (it = clients.begin(); it != clients.end();it++) {
                TcpSocket& client = **it;
                if (selector.isReady(client)) {
                    bool pbKeyRsaSend = Network::hasPbKeyRsa(client.getRemoteAddress());
                    bool pbKeySend = Network::hasPbKey(client.getRemoteAddress());
                    User* user = Network::getUser(client.getRemoteAddress());
                    if (pbKeySend && pbKeyRsaSend && user != nullptr) {
                        SymEncPacket packet;
                        if (client.receive(packet) == Socket::Done) {
                            std::string request;
                            packet>>request;
                            Network::addRequest (user, request);
                        } else {
                            Network::removeUser(client.getRemoteAddress());
                            selector.remove(client);
                            it = clients.erase(it);
                            delete *it;
                            it--;
                        }

                    } else if (!pbKeyRsaSend && !pbKeySend || user != nullptr && !user->isUsingSecuredConnexion()) {
                        Packet packet;
                        if (client.receive(packet) == Socket::Done) {
                            std::string request;
                            packet>>request;
                            if (request == "GetPbKeyRsa") {
                                std::cout<<"send pb key rsa"<<std::endl;
                                user->setUseSecuredConnexion(true);
                                Network::sendPbKeyRsa(*user);
                            } else {
                                Network::addRequest (user, request);
                            }
                        } else {
                            Network::removeUser(client.getRemoteAddress());
                            selector.remove(client);
                            it = clients.erase(it);
                            delete *it;
                            it--;
                        }

                    } else if (pbKeyRsaSend && !pbKeySend && user != nullptr && user->isUsingSecuredConnexion()) {
                        EncryptedPacket packet;
                        if (client.receive(packet) == Socket::Done) {
                            std::string request;
                            packet>>request;
                            if (request == "GetPbKey") {
                                 std::cout<<"send pb key"<<std::endl;
                                 Network::sendPbKey(*user);
                            } else {
                                Network::removeUser(client.getRemoteAddress());
                                selector.remove(client);
                                it = clients.erase(it);
                                delete *it;
                                it--;
                            }
                        }
                    } else {
                        Network::removeUser(client.getRemoteAddress());
                        selector.remove(client);
                        it = clients.erase(it);
                        delete *it;
                        it--;
                    }
                }
            }
        }
    }
}
 

Here is what the debugger tells me :

Code: [Select]
#0 0x7ffff6e50a30 __cxa_throw() (/usr/lib/x86_64-linux-gnu/libstdc++.so.6:??)
#1 0x7ffff6e50f8d operator new(unsigned long) () (/usr/lib/x86_64-linux-gnu/libstdc++.so.6:??)
#2 0x7ffff7bd3682 std::vector<char, std::allocator<char> >::_M_fill_insert(__gnu_cxx::__normal_iterator<char*, std::vector<char, std::allocator<char> > >, unsigned long, char const&) () (/usr/local/lib/libsfml-network.so.2:??)
#3 0x7ffff7bd324d sf::Packet::append(void const*, unsigned long) () (/usr/local/lib/libsfml-network.so.2:??)
#4 0x447698 odfaeg::SymEncPacket::onReceive(this=0x7ffff2532e50, data=<optimized out>, dataSize=<optimized out>) (/home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Network/symEncPacket.cpp:15)
#5 0x7ffff7bd4af4 sf::TcpSocket::receive(sf::Packet&) () (/usr/local/lib/libsfml-network.so.2:??)
#6 0x44bd08 odfaeg::SrkServer::run(this=0x822250) (/home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Network/srkserveur.cpp:87)
#7 0x7ffff6ea3bf0 ??() (/usr/lib/x86_64-linux-gnu/libstdc++.so.6:??)
#8 0x7ffff62fa182 start_thread(arg=0x7ffff2533700) (pthread_create.c:312)
#9 0x7ffff660b30d clone() (../sysdeps/unix/sysv/linux/x86_64/clone.S:111)
Title: Re: Trouble while receiving data. (TCP mode)
Post by: Lolilolight on June 14, 2014, 09:47:01 pm
The bug comes from openssl finally, sometimes this function fails :
if (!EVP_DecryptFinal_ex(d_ctx, (unsigned char*) (*data)+dataLen, &blockLen))
        return FAILURE;
 

So it returned an invalid size and it crashed....
Title: Re: Trouble while receiving data. (TCP mode)
Post by: binary1248 on June 15, 2014, 04:18:27 am
I really have to ask you: how long do you try to solve your problems before you come and post here? Between your first post and your last where you allegedly solved your problem (from what I understand) only half a day elapsed. Don't you think that trying to solve your problem on your own a bit longer would save us all these useless threads? I can take days if not weeks to solve some problems depending on how hard it is to solve them, but at least I don't spam forums with double and triple posts with bits of code that are useless to everybody else. And more importantly, I actually take what is posted by others into consideration, since it might help solve the problem faster.

I suggest to everybody who cares for the well being of this forum to ignore all of these "help requests" for at least a day before starting another pointless discussion that doesn't benefit anybody, least the thread starter. Don't even dare to double or triple post within the day with useless information or risk getting the thread locked. Even newcomers understand this and use the edit function.
Title: Re: Trouble while receiving data. (TCP mode)
Post by: Jesper Juhl on June 15, 2014, 09:35:27 pm
I think you should read this: http://stackoverflow.com/questions/5665698/evp-decryptfinal-ex-error-on-openssl

Ohh and BTW, @binary1248 : I agree 100%.
Title: Wrong bytes at the end of the packet ???
Post by: Lolilolight on June 18, 2014, 02:28:46 pm
I've printed the bytes values and the size of the encrypted packet and there are the same at both sides. (on the server and on the client, but openssl is still returning me an error sometimes, not at every execution)

Code: [Select]
data :
216 231 40 108 97 250 69 90 79 179 226 104 216 120 124 170 73 216 119 66 205 158 123 249 153 34 30 51 177 223 26 141 size : 32

data :
103 199 125 199 210 194 147 59 76 111 21 78 116 198 211 6 size : 16

Error encrypting message: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
data :
57 208 110 186 16 229 111 96 137 204 150 177 138 59 73 22 size : 16

Error encrypting message: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
data :
10 223 62 4 158 180 44 217 31 151 22 151 215 245 94 120 size : 16

Error encrypting message: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
data :
142 220 144 37 30 193 223 130 100 217 65 212 237 32 248 242 105 18 140 65 88 52 32 66 103 41 20 202 107 113 83 203 size : 32

This problem happens only when I send and receive data with sockets.

Is it possible that SFML wipes out some null bytes at the end of the packet when receiving data through a socket ???

And I can't find a forum, where can I get some help with openssl ?

Especially for those functions :

unsigned char* AES_ENC::encrypt(const unsigned char* data, int dataSize, int* newSize) {
    int cLen = dataSize+AES_BLOCK_SIZE;
    int fLen = 0;
    unsigned char *encData = (unsigned char*) malloc(cLen);
    if (!EVP_EncryptInit_ex(e_ctx, EVP_aes_256_cbc(), nullptr, key, iv))
        return nullptr;
    if (!EVP_EncryptUpdate(e_ctx, encData, &cLen, (unsigned char*) data, dataSize))
        return nullptr;
    if(!EVP_EncryptFinal_ex(e_ctx, encData+cLen, &fLen)) {
        return nullptr;
    }
    *newSize = cLen + fLen;
    return encData;
}
unsigned char* AES_ENC::decrypt(const unsigned char* encData, int dataSize, int* newSize) {
    int pLen = dataSize;
    int fLen = 0;
    unsigned char *data = (unsigned char*) malloc(pLen);
    if (!EVP_DecryptInit_ex(d_ctx, EVP_aes_256_cbc(), nullptr, key, iv))
        return nullptr;
    if (!EVP_DecryptUpdate(d_ctx, data, &pLen, (unsigned char*) encData, dataSize))
        return nullptr;
    if (!EVP_DecryptFinal_ex(d_ctx, data+pLen, &fLen)) {
        char* err = (char*) malloc(130);
        ERR_load_crypto_strings();
        ERR_error_string(ERR_get_error(), err);
        fprintf(stderr, "Error encrypting message: %s\n", err);
        free(err);
        return nullptr;
    }
    *newSize = pLen + fLen;
    return data;
}
 
Title: Re: Trouble while receiving data. (TCP mode)
Post by: Lolilolight on June 19, 2014, 11:59:20 am
Hmmm it seems that SFML doesn't gives me the right bytes and the right size in the onSend function :
const void* SymEncPacket::onSend (size_t& dataSize) {
 unsigned char* buffer;
    std::cout<<"data : "<<std::endl;
    for (unsigned int i = 0; i < sizeof (static_cast<const unsigned char*> (getData())); i++) {
        std::cout<<(int) static_cast<const unsigned char*> (getData())[i]<<std::endl;
    }
    std::cout<<std::endl<<"data size : "<<dataSize<<std::endl;
    buffer = AES_ENC::encrypt(static_cast<const unsigned char*> (getData()), getDataSize(), (int*) &dataSize);
    std::cout<<"data : "<<std::endl;
    for (unsigned int i = 0; i < dataSize; i++) {
        std::cout<<(int) buffer[i]<<" ";
    }
    std::cout<<std::endl;
    std::cout<<"size : "<<dataSize<<std::endl;
    return &buffer[0];
}
 

I try to send the message "hello world!" and here it's what it gives me:
 Network::startCli(10000, 10001, sf::IpAddress::LocalHost);
    std::string text = "Hello world!";
    SymEncPacket packet;
    packet<<text;
    Network::sendTcpPacket(packet);
 

Code: [Select]
data :
0
0
0
12
72
101
108
108
dataSize : 0

Why SFML gives me a dataSize of 0, and why it add me null bytes at the begining of the packet ???

It happens before I encrypt the data so the decryption fails at the server-side.

Title: Re: Trouble while receiving/sending data. (TCP mode)
Post by: Lolilolight on June 19, 2014, 12:07:35 pm
I've find for the size :
unsigned char* buffer;
    std::cout<<"data : "<<std::endl;
    for (unsigned int i = 0; i < getDataSize(); i++) {
        std::cout<<(int) static_cast<const unsigned char*> (getData())[i]<<std::endl;
    }
    std::cout<<std::endl<<"data size : "<<getDataSize()<<std::endl;
 

But it's still wrong, it gives me a size of 16 and add 3 '0' at the beginning of the packet, or the right size should be 13 (12 + the null byte) not 16!
Title: Re: Trouble while receiving data. (TCP mode)
Post by: Laurent on June 19, 2014, 02:17:55 pm
sf::Packet has its own internal protocol and adds bytes wherever it needs to. So you're not supposed to try to interpret the data once it is inside a sf::Packet. So, don't waste your time on that and check if you have an actual issue.
Title: Re: Trouble while receiving data. (TCP mode)
Post by: Lolilolight on July 09, 2014, 09:59:58 am
Mmm I haven't an actual issue yet, but, it seems that in some cases SFML doesn't add the right number of bytes, so, the OpenSSL padding is not good and it crash.

And most surprising : if I don't initialize the dst size to 0, it always crash :
void SymEncPacket::onReceive (const void* data, size_t dataSize) {
    unsigned char* buffer;
    std::size_t dstSize = 0;
    /*std::cout<<"data : "<<std::endl;
    for (unsigned int i = 0; i < dataSize; i++) {
        std::cout<<(int) static_cast<const unsigned char*>(data)[i]<<" ";
    }
    std::cout<<"size : "<<dataSize<<std::endl;
    std::cout<<std::endl;*/

    buffer = AES_ENC::decrypt(reinterpret_cast<const unsigned char*> (data), dataSize, (int*) &dstSize);
    /*std::cout<<"data : "<<std::endl;
    for (unsigned int i = 0; i < dstSize; i++)
        std::cout<<(int) buffer[i]<<" ";*/

    //std::cout<<std::endl<<"data size : "<<dstSize<<std::endl;
    append(&buffer[0], dstSize);
}
 
Title: Re: Trouble while receiving data. (TCP mode)
Post by: Lolilolight on August 09, 2014, 06:37:42 pm
And it seems it's when I'm sending long TCP messages that I've sometimes a crash...

So, I think I'll check in the source code the place where you split and reconstitute your data.
Title: Re: Trouble while receiving data. (TCP mode)
Post by: Laurent on August 09, 2014, 07:11:18 pm
Quote
So, I think I'll check in the source code the place where you split and reconstitute your data.
I don't. It's done at lower-level by the TCP layer.
Title: Re: Trouble while receiving data. (TCP mode)
Post by: binary1248 on August 09, 2014, 07:38:19 pm
It's done at lower-level by the TCP layer.
You mean IP (http://en.wikipedia.org/wiki/IP_fragmentation) right? ;D Unless Nagle's algorithm is enabled, TCP will send a segment that is as large as the data you pass to send() (within the limits of course). Fragmentation is normally taken care of by IP if the segment is larger than the MTU the path supports. TCP doesn't and shouldn't care about packet sizes. It does its window scaling based on other factors.
Title: Re: Trouble while receiving data. (TCP mode)
Post by: Laurent on August 09, 2014, 07:56:29 pm
Arf. I thought it was TCP because UDP, which is based on IP too (right?), doesn't use fragmentation.
Title: Re: Trouble while receiving data. (TCP mode)
Post by: binary1248 on August 09, 2014, 08:13:20 pm
Actually... UDP "uses" fragmentation... like any other transport (layer 4) protocol. It doesn't implement it itself, but like TCP, it can rely on IP taking care of it. The fact that a 60000 byte UDP datagram doesn't arrive at its destination has less to do with the fact that it isn't properly fragmented than with the fact that many internet routers just drop traffic that is oversized (the standard only requires that compliant devices try their best to reassemble packets up to a size of 576 bytes). IPv6 even requires path MTU discovery so that fragmentation is left to the sender to perform in its entirety, so your NIC will end up sending out many IPv6 packets when you send a 60000 byte UDP datagram.