Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: TCP Send raw packet bugs/Design flaws (Unresolved)  (Read 5214 times)

0 Members and 1 Guest are viewing this topic.

fredrick

  • Newbie
  • *
  • Posts: 20
    • View Profile
TCP Send raw packet bugs/Design flaws (Unresolved)
« on: April 20, 2015, 10:40:46 pm »
Quote
Socket::Status TcpSocket::send(const void* data, std::size_t size, std::size_t& sent)
{
    // Check the parameters
    if (!data || (size == 0))
    {
        err() << "Cannot send data over the network (no data to send)" << std::endl;
        return Error;
    }

    // Loop until every byte has been sent
    int result = 0;
    for (sent = 0; sent < size; sent += result)
    {
        // Send a chunk of data
        result = ::send(getHandle(), static_cast<const char*>(data) + sent, size - sent, flags);

        // Check for errors
        if (result < 0)
        {
            Status status = priv::SocketImpl::getErrorStatus();

            if ((status == NotReady) && sent)
                return Partial;

            return status;
        }
    }

    return Done;
}

Should be:

Quote
Socket::Status TcpSocket::send(const void* data, const std::size_t size, std::size_t& sent)
{
    // Check the parameters
    if (!data || (size == 0))
    {
        err() << "Cannot send data over the network (no data to send)" << std::endl;
        return Error;
    }

     if (sent >= size)
    {
        err() << "Cannot send data, size error"  << std::endl;
        return Error;
    }

    // Loop until every byte has been sent
    int result = 0;
    for (; sent < size; sent += result)
    {
        // Send a chunk of data
        result = ::send(getHandle(), static_cast<const char*>(data) + sent, size - sent, flags);

        // Check for errors
        if (result < 0)
        {
            Status status = priv::SocketImpl::getErrorStatus();

            if ((status == NotReady) && sent)
                return Partial;

            return status;
        }
    }

    return Done;
}

You may need to check where this "send()" is called internally and update as needed to utilize "resume"
« Last Edit: April 27, 2015, 12:40:46 pm by fredrick »

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: TCP Send raw packet bugs
« Reply #1 on: April 20, 2015, 10:49:58 pm »
Do you even understand what the sent parameter is for? It is a non-const reference for a reason.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

fredrick

  • Newbie
  • *
  • Posts: 20
    • View Profile
Re: TCP Send raw packet bugs
« Reply #2 on: April 20, 2015, 10:51:10 pm »
Yes i do, and setting a ref back to value 0 in the for loop makes zero sense

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: TCP Send raw packet bugs
« Reply #3 on: April 20, 2015, 10:56:51 pm »
Yes i do, and setting a ref back to value 0 in the for loop makes zero sense
Well... I guess you don't, because sent is an output parameter and that is the only reason why a parameter would be a non-const reference.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

fredrick

  • Newbie
  • *
  • Posts: 20
    • View Profile
Re: TCP Send raw packet bugs
« Reply #4 on: April 20, 2015, 11:00:12 pm »
And lets say you got a partial write to socket before "not ready"... what do you then do? There is no way to finish the last bytes on the outside without shifting the data before you call  send again...

dabbertorres

  • Hero Member
  • *****
  • Posts: 506
    • View Profile
    • website/blog
Re: TCP Send raw packet bugs
« Reply #5 on: April 20, 2015, 11:05:58 pm »
"sent" is so you can give it a variable to store how many bytes were sent. So you can see that data.

It's acting like a second return variable.

It's not meant to use the value you give it. It doesn't even expect you to give it a value.

fredrick

  • Newbie
  • *
  • Posts: 20
    • View Profile
Re: TCP Send raw packet bugs
« Reply #6 on: April 20, 2015, 11:09:30 pm »
I now understand the original intention, but for non blocking sockets the current send function has little value for "not ready" as the caller needs to make sure next time that the remaining bytes is in the "0" position, this is not a good design.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: TCP Send raw packet bugs
« Reply #7 on: April 20, 2015, 11:12:54 pm »
What do you mean exactly? What would be good design instead?

In the Partial case, the caller knows how many bytes have been sent yet, and can pass the remaining data correspondingly... I don't see the problem.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

fredrick

  • Newbie
  • *
  • Posts: 20
    • View Profile
Re: TCP Send raw packet bugs
« Reply #8 on: April 20, 2015, 11:17:19 pm »
Problem is at line 225 TcpSocket.cpp (this threw me off originally) but now this is a  new bug if the current statement is the intention

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: TCP Send raw packet bugs
« Reply #9 on: April 20, 2015, 11:20:44 pm »
Can you please describe the problem clearly? And answer my question how a good design would look?
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

fredrick

  • Newbie
  • *
  • Posts: 20
    • View Profile
Re: TCP Send raw packet bugs
« Reply #10 on: April 20, 2015, 11:26:30 pm »
Sure,

A) Bug:

Socket::Status TcpSocket::send(const void* data, std::size_t size) at line 220 when returning not ready will not return with written as it does not have a ref.

Edit: The user in this case does not really know how much was written to socket before it returned "not Ready", this function should be avoided at all cost in its current implementation, warning is not good enugh

B) Better design :

Return written size to the caller domain (lib user) for all send functions (important for non blocking only),
user can then call send again with the same stack variable until "Done".


I have forked the socket portion of the library so i no longer rely on how you fix it, just wanted to let you know that there is at least one bug in the current implementation (ignoring lack of consts)
« Last Edit: April 20, 2015, 11:32:24 pm by fredrick »

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: TCP Send raw packet bugs
« Reply #11 on: April 21, 2015, 11:15:39 am »
Quote
And lets say you got a partial write to socket before "not ready"... what do you then do? There is no way to finish the last bytes on the outside without shifting the data before you call  send again...

What? This makes no sense because if you get a partial response then you call send again with the pointer to your data just incremented to the new position.

Quote
A) Bug:

Socket::Status TcpSocket::send(const void* data, std::size_t size) at line 220 when returning not ready will not return with written as it does not have a ref.

Read the implementation again, the send() overload that doesn't include the sent overload will return Partial if only part of the data was sent. The only difference between the two functions is that one doesn't give the user the byte count that was sent. And there is no way to eliminate this function or change the signature without breaking the API.

Quote
B) Better design :

Return written size to the caller domain (lib user) for all send functions (important for non blocking only),
user can then call send again with the same stack variable until "Done".

The sent byte count can't be returned in all functions, it is done where appropriate. There is no issue here other than with your mindset.

Quote
I have forked the socket portion of the library so i no longer rely on how you fix it

Mind linking to your repo then?
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

fredrick

  • Newbie
  • *
  • Posts: 20
    • View Profile
Re: TCP Send raw packet bugs
« Reply #12 on: April 21, 2015, 03:30:07 pm »
Quote from: zsbzsb
Quote
And lets say you got a partial write to socket before "not ready"... what do you then do? There is no way to finish the last bytes on the outside without shifting the data before you call  send again...

What? This makes no sense because if you get a partial response then you call send again with the pointer to your data just incremented to the new position.

I don't understand what you mean with "no sense", let me try to clarify :

I have already covered this but in summary: Instead of letting user deciding the pointer arithmetic and calling send again, they call send until its "Done" or break on "Error/Disconnect" with the updated ref  "sent" variable. This is cleaner and safer than casting user data structure to const char * on the outside.

Quote from: zsbzsb
Quote
A) Bug:

Socket::Status TcpSocket::send(const void* data, std::size_t size) at line 220 when returning not ready will not return with written as it does not have a ref.

Read the implementation again, the send() overload that doesn't include the sent overload will return Partial if only part of the data was sent. The only difference between the two functions is that one doesn't give the user the byte count that was sent. And there is no way to eliminate this function or change the signature without breaking the API.

I understand breaking the API is not a good solution, though that does not mean the current "send" implementation is a good design, that's why the send variant without the &sent for non blocking socket should be avoided at all costs in its current form, printing a warning and call it "good enough" is ridiculous . To maintain compatibility you can have a "secure" variant with the added prefix(es) or postfix(es) to send()



Quote from: zsbzsb
Quote
B) Better design :

Return written size to the caller domain (lib user) for all send functions (important for non blocking only),
user can then call send again with the same stack variable until "Done".

The sent byte count can't be returned in all functions, it is done where appropriate. There is no issue here other than with your mindset.

As an public library, as answered above this is not good enough from an objective position, has nothing to do with my mindset, grow up and take some responsibilities.


Quote from: zsbzsb
Quote
I have forked the socket portion of the library so i no longer rely on how you fix it

Mind linking to your repo then?

I have no link for it, its also ported to amalgamation so i am not sure how useful it is.