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

Author Topic: TcpSocket::Avail()?  (Read 2876 times)

0 Members and 1 Guest are viewing this topic.

VPellen

  • Newbie
  • *
  • Posts: 14
    • View Profile
TcpSocket::Avail()?
« on: March 09, 2012, 01:32:50 pm »
A method to check how many bytes of data are sitting in a TCP stream, waiting to be read.

My knowledge of TCP is a bit rusty: Is this one of those things that TCP "natively" supports? Are you able to, at any time, poll a TCP socket and find out how much data is sitting there, waiting to be read? Or is it one of those things that's dealt with on a far lower OS/hardware layer, and so the only way to implement it would be to create some kind of mid-layer buffer hodgepodge which would defeat the purpose of having the function in the first place?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
TcpSocket::Avail()?
« Reply #1 on: March 09, 2012, 01:55:04 pm »
It's not directly supported, I woudln't be able to implement it with a simple socket call.

In fact I only see two ways of doing it (don't know which one is the "correct" one):
- internally reading everything from the socket into a buffer, and working on this buffer
- using lower-level, OS-specific functions

But why would you want to check the amount of bytes available, without actually reading them?
Laurent Gomila - SFML developer

VPellen

  • Newbie
  • *
  • Posts: 14
    • View Profile
TcpSocket::Avail()?
« Reply #2 on: March 09, 2012, 02:16:16 pm »
Mainly premature optimization woes (I know, I know), but also for convenience. If you're expecting a specific number of bytes on a socket read, it's easier to do it in one go when you know all the bytes are going to be there. Thumbing through the network documentation, I noticed you keep a "Pending Packet" struct in the TCP Socket. It's that kind of thing: You wouldn't have to hold that data if you knew how much to expect.

The first solution, (internally reading everything into a buffer) is, from what I gather, what you already do for packets, which is a nice convenience, but doesn't offer the optimization benefits of not having to do a read unless you know the data's there.

If the only way the functionality could be implemented is with OS-specific calls, don't bother - I just wondered if there was a quick-and-easy solution, but apparently not.

Oh, and while we're on the subject - That pending packet in the TCP library. What happens if it receives a packet size of 0xFFFFFFFF? Does it just keep reading in data until the heap bursts? Or does it try to preallocate a gig of data in one sweep and then crash instantly? Or is there a third option?

If none of the above makes sense, assume that I'm not as educated as I think I am.

VPellen

  • Newbie
  • *
  • Posts: 14
    • View Profile
TcpSocket::Avail()?
« Reply #3 on: March 09, 2012, 03:12:07 pm »
I skimmed the source, and apparently the answer to:
Quote
Does it just keep reading in data until the heap bursts?

.. is a resounding "Yes".

New feature request:

TcpSocket::SetMaxPacketSize()

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
TcpSocket::Avail()?
« Reply #4 on: March 10, 2012, 05:29:17 pm »
Why should there be a max packet size? If a client is able to send a huge packet, there's no reason why the server wouldn't be able to receive it.

And if you're talking about security: there's none in sf::Packet, it's purely a convenience class. If you want to make your network code robust (against, for example, external attacks) then don't use them.
Laurent Gomila - SFML developer

VPellen

  • Newbie
  • *
  • Posts: 14
    • View Profile
TcpSocket::Avail()?
« Reply #5 on: March 10, 2012, 08:09:31 pm »
Because as far as I can tell, 99% of the security issues that sf::Packets have could be solved by allowing the server to dictate a max packet size.

As far as I can tell, all Receive(Packet) does is serve as a useful method of buffering network input so you can grab it all in one go. Its only(?) security flaw is the potential for memory leaks.

The exploit itself is simple, and you probably know it - Send a packet size of N, and then send N-1 bytes of garbage. The data gets stored in the temporary packet buffer, but because the server never receives a complete packet, the temporary packet just sits there taking up space. And this isn't really a problem with SFML's packets, it's a problem with any kind of buffered network input.

The real problem comes from the question of how much space the temporary packet can take up.

In practice, that's going to be the largest possible packet size, minus one. In the case of sf::Packets, the largest possible packet size on the server end is 2^32 (I think), or 4 gigs of data. That's a hell of a memory leak.

But if it were possible to dictate a maximum packet size, you'd be able to limit the size of the potential memory leak. If you set a maximum packet size of, say, 100 bytes, and the client tries to send a packet size of more than that, you can just cut him off. He can still cause a memory leak - It's just limited to 99 bytes. (Well, probably more like 128 if my knowledge of std::vectors is correct).

If you feel it's unnecessary or otherwise too much trouble to implement, that's fine - Honestly, I'll probably implement my own data handling anyway to maximize performance. But the ability to set a limit on incoming packet size would probably solve the single biggest security issue that sf::Packets have.

So, that's my sales pitch. Either way, I'm immensely appreciative of SFML. Makes my life far, far easier. Cheers.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
TcpSocket::Avail()?
« Reply #6 on: March 10, 2012, 09:48:31 pm »
You're right. But I won't do anything now ;)

First, if I want to fix security issues, I'll probably ask for more feedback, since network security is not something that I usually work with.

And as you can see on the task tracker, sf::Packet will be rewritten in the future, so I may come up with a different design, and thus different solutions.

Thank you very much for your feedback.
Laurent Gomila - SFML developer