0

After failing to get any help in the SFML forums, I've decided to see if anyone here can be of any help. I have an application which updates itself through a TCP connection to a server application. This works perfectly fine, except for one specific packet transmission, in which the packet is somehow changed. The server sends a packet containing the number 1:

pack << sf::Uint8(1);
ClientSocket.Send(pack);

(Where pack is of type sf::Packet and ClientSocket is of type sf::SocketTCP)

Stepping through with my debugger does in fact confirm that these lines are executed, and that the next Receive call in my client is the next few lines:

sock.Receive(pack);
sf::Uint8 conf;
pack >> conf;

(Where pack is once again an sf::Packet, and sock is a SocketTCP)

However, somehow in my client, conf is showing up as having a value of zero (my debugger confirms this) and it acts as so (the next line switches depending on the value). I am running both applications on the same machine, and they are both reading each other as "127.0.0.1", so the packets (if I understand correctly) aren't going through my router, or really ever leaving my machine. Any ideas on why my packets are being corrupted?

For the record, in case it's any help, I'm using SFML 1.6 and my application in being run on a Debian Squeeze Linux machine.

EDIT: Per request, here is some more code from my application.

First, the portion of my client specifically relating to this updater:

cout << "Connecting to update server." << endl;
sf::IpAddress server = sf::IpAddress::LocalHost;
sf::TcpSocket sock;
if (sock.connect(server, PORT, sf::seconds(20.0f)) != sf::Socket::Done)
    return false;

cout << "Connected. Searching for updates for updater." << endl;

sf::Packet pack;
std::string lastUpdate = getLastUpdate();

#ifdef __WXGTK__
pack << "uupdate" << lastUpdate << sf::Uint8(1);
#elif defined(__WXMSW__)
pack << "uupdate" << lastUpdate << sf::Uint8(2);
#elif defined(__WXOSX__)
pack << "uupdate" << lastUpdate << sf::Uint8(3);
#endif

sock.send(pack);

pack.clear();

sock.receive(pack); //THIS IS THE PART WHERE IT BREAKS
sf::Int32 conf;
pack >> conf;

if (conf == 1) { //There is an update!
    cout << "Update found!" << endl;

    pack << "begin" << sf::Uint32(512);
    sock.send(pack);

    pack.clear();

    sock.receive(pack);
    pack >> conf;

    if (conf == 0) { //No errors
        wxFileOutputStream* out = new wxFileOutputStream(wxString(UPDATER, StrConv).append(".temp"));

        char* data = new char[512];
        while (data != chara("done") && data != chara("error")) {
            sock.receive(pack);
            sf::Int32 size;
            pack >> size;
            data = const_cast<char*>((const char*)pack.getData());

            out->Write(data, size);
        }
        out->Close();
        if (data == chara("done"))
            wxCopyFile(wxString(UPDATER, StrConv).append(".temp"), wxString(UPDATER, StrConv));
        wxRemoveFile(wxString(UPDATER, StrConv).append(".temp"));
    }
}

cout << "Updater is up-to-date. Executing updater." << endl;

sock.disconnect();

bool success;
if (wxTheApp->argc == 1)
    success = wxExecute(wxT(UPDATER));
else
    success = wxExecute(wxString(UPDATER, StrConv).append(wxTheApp->argv[1]));

return success;

And then the portion of the server relating to these updates:

    //ClientSocket has already been initalised by way of a TcpListener
cout << "Checking for updater patches for client at " << ClientAddress.toString() << endl;

std::string lastUpdate;
pack >> lastUpdate;
sf::Uint8 os;
pack >> os;

//Check last time updater was changed
struct tm* clock;
struct stat attribs;
if (os == 1)
stat("Linux/Updater", &attribs);
else if (os == 2)
stat("Windows/Updater.exe", &attribs);
else if (os == 3)
stat("Mac/Updater", &attribs);
clock = gmtime(&(attribs.st_mtime));
time_t lastWrite = mktime(clock);

time_t clientUpdate = stringToNumber<time_t>(lastUpdate.c_str());

if (lastWrite > clientUpdate) {
    cout << "Found updater patches for client at " << ClientAddress.toString() << endl;

    pack << sf::Int32(1);
    ClientSocket->send(pack); //THIS IS THE PART WHERE IT BREAKS

    pack.clear();

    ClientSocket->receive(pack);
    std::string mes;
    pack >> mes;

    if (mes != "begin") {
        cerr << "Client at " << ClientAddress.toString() << " sent unrecognised message: " << mes << ". Ending conversation." << endl;
        ClientSocket->disconnect();
        return false;
    }

    sf::Uint32 size;
    pack >> size;

    cout << "Beginning to send updater patch to " << ClientAddress.toString() << endl;

    ifstream in;

    if (os == 1)
        in.open(chara("Linux/Updater"), ios_base::in | ios_base::binary);
    else if (os == 2)
        in.open(chara("Windows/Updater.exe"), ios_base::in | ios_base::binary);
    else if (os == 3)
        in.open(chara("Mac/Updater"), ios_base::in | ios_base::binary);

    if (in.fail()) {
        pack << sf::Uint8(1);
        ClientSocket->send(pack);
        cerr << "Failed to open updater at request of " << ClientAddress.toString() << ". Closing connection." << endl;
        ClientSocket->disconnect();
        return false;
    }

    pack << sf::Uint8(0);
    ClientSocket->send(pack);

    pack.clear();

    //Get length of file
    in.seekg(0, ios::end);
    int length = in.tellg();
    in.seekg(0, ios::end);

    char* buf = new char[size];

    for (unsigned int i = 0; i < length / size; i++) { //Read and send every `size`-sized block we can
        in.read(buf, size);
        pack << sf::Int32(size) << buf;
        ClientSocket->send(pack);
    }

    in.read(buf, length % size);
    pack << sf::Int32(length % size) << buf;
    ClientSocket->send(pack);

    pack.clear();

    pack << "done";
    ClientSocket->send(pack);

    pack.clear();
} else {
    pack << sf::Int8(0);
    ClientSocket->send(pack);
}

EDIT: I know it's been almost a month since there have been any posts on here, but I'm still having issues with this. I'm at wit's end on how to solve this.

Morgan Patch
  • 336
  • 6
  • 20
  • Are you sure you are reading this packet and not leftovers from the last one? – Daniel Sep 03 '12 at 18:10
  • Yes. I'm using blocking sockets, and I have guaranteed that each Send call on the server matches with exactly one Receive call on the client (and vice-versa). I have also seen that my client does hang on the Receive call shown above until the server makes the Send call shown above. Not to mention that the packet before that one didn't have a 0 in it anywhere. – Morgan Patch Sep 03 '12 at 18:15
  • Try changing the data type/value to see if it's everything or just uint8. – Daniel Sep 03 '12 at 18:18
  • Maybe I am somehow reading values from the previous packet. I changed it to `Uint16` and continued to get 0, but then I changed it to `Int32` and am now getting 7 instead. I don't see why though. The last thing done on the client side was to send a packet, not receive one, and `sf::SocketTCP::Send(sf::Packet)` is supposed to empty the packet of all data, I believe... – Morgan Patch Sep 03 '12 at 18:42
  • After just having dug through the SFML source code, it would appear that this is not the case: `Send(sf::Packet)` does _not_ clear the packet. So it seems that I'm still reading the old data in the packet instead of the data that was just sent. I'll try adding some calls to `sf::Packet::Clear()` and see if that fixes it. – Morgan Patch Sep 03 '12 at 18:47
  • Scratch that. Even after adding a call to `Clear()` immediately prior to the `sock.Receive()`, I still get the inaccurate values. So that wasn't the problem. – Morgan Patch Sep 03 '12 at 18:55
  • Can you show us the code where you create your Packet and what you do next after you receive your packet? Because the problem is not in the code you have here. – Apprentice Queue Sep 04 '12 at 00:51

2 Answers2

1

This is not really an answer but I can't add a comment on the question so...

SFML 1.6 is not maintained and if there is an issue with SFML itself it might already be solved in version 2.0. You can download the RC here.

Hiura
  • 3,500
  • 2
  • 20
  • 39
  • I'll be able to post more code as Apprentice Queue asked tomorrow, but for now I would like to make the comment that I have updated to 2.0, and I am still seeing the same problems. As I said, I'll post more code tomorrow. – Morgan Patch Sep 07 '12 at 04:37
  • @Apprentice, I have added the source code in, hopefully it can solve the problem. – Morgan Patch Sep 08 '12 at 05:25
0

So, turns out the problem was rather simple. You know how I added lots of pack.clear() lines in? Turns out I forgot to add one between receiving the original data and sending the original data on the server. So my packet still had data left over from the first call to sock.receive(pack) (which was a few lines above the start of the code from the server posted above). It took me this long to see that. Put in a call to pack.clear() and the problem went away.

Morgan Patch
  • 336
  • 6
  • 20