Am I missing data?

This is a discussion on Am I missing data? within the Networking/Device Communication forums, part of the General Programming Boards category; It's kind of weird the previous topic was on this subject as well.
Anyway, I wrote a SOCKS4 proxy which ...

Am I missing data?

It's kind of weird the previous topic was on this subject as well.

Anyway, I wrote a SOCKS4 proxy which seems to be working well for the most part. It seems though I am having trouble with websites with quite a bit of content. If I open up one of these web pages, it is like it never quite finishes loading. By the way, I configured Firefox 3.5 to use my server.

An example of a web page that does this is msdn.microsoft.com

My code has virtually no comments, but I know the problem has to be in the main() block in the loop. I think that firefox may be firing off the connection requests so fast my program can't handle it.

It's about 200 lines, but I'll include the whole thing, but where I think the problem lies is where I referred to earlier, the loop in my main block.

Also any vulnerabilities you see I would love hear. I know of one already. It has to do with recv when the client first connects, packet fragmentation and stuff. But other than that I'm all ears. Thanks!

I really don't know much about the Sock4 specification, and I've just started to look at the code, but my first thought was maybe that the buffer is too small (1024 bytes)? Just an initial thought anyway.

Notable things:
2) You dynamically allocate proxy_s, but with your usage of it, you might as well put it on the stack.

Not-so-notable things:
3) Check the return value of both selects
4) You make the assumption that send() will send everything you pass it.
5) You make the assumption that recv() will do the same.
6) You make the above assumptions with nonblocking sockets, which is even more fatal.
7) You make the assumption that an error from send() / recv() is a bad thing -- you're using nonblocking sockets, you need to check for WSAEWOULDBLOCK.

OK. I have a lot more problems than I thought. Since both my in/out sockets are non-blocking, i need to wait until both of them can finish their operation. Here is where my confusion starts.

I think the constants WSAEINPROGRESS and WSAEWOULDBLOCK are needed at this point. So far I've figured this. I will check send() and recv(), and if they return WSAEWOULDBLOCK, don't fret, it just means there was no operation to perform.

Here is what I am ultimately getting to. Say I received a large amount of data. Since these are non-blocking sockets, do I need to make time for them to finish the send/recv operation, or is a function call enough? And how would I go about doing this? Because if recv throws a WSAEINPROGRESS, how can I get the total bytes received? Will it actually eventually change the value of the variable?

It seems my proxy works fine, but then I opened up the dreaded youtube, which in turn caused some mass confusion, lol.

You shouldn't be getting WSAEINPROGRESS. In fact, I'm not entirely sure how you get an EINPROGRESS, since the docs indicate this comes from calling two blocking socket functions in the same thread. Not exactly sure how they expect us to do that. That said, you're single threaded, you should be fine.

WSAEWOULDBLOCK, however, you should & will get. There's two places it can crop up:
If it crops up on a call to recv(), oh well. No bytes were recv()'d. (If they had, recv() would have returned a positive number.)

send() is a bit more of a stickler though. If send() returns EWOULDBLOCK, then no bytes were sent. (Careful though, send() might return less than what you ask it -- so it might send 50%, 25%, 100% or 0% of what you ask it to send!) This means you'll have to buffer the data somewhere until send() can actually send them. You can create another fd_set and pass it to select() to find out when the socket is writeable. Only include the socket in the fd_set if you actually have data you need to send though, otherwise, you'll end up waking up too often in a sort of "socket is writable! I don't have anything to send. socket is STILL writable! etc..." loop.
The most simplistic buffer could be a std::queue of

Holy cow there's more to this than I thought lol. Oh well, a good learning experience. I guess at this point it would be much easier to combine some C++ because writing my own buffer handler in C might be tricky and dirty. But I do want to write a solid program that can handle anything so I will give it a shot.

Ok, I've narrowed it down pretty good. I still have the major bug I'm trying to pin down, when send returns less than what I want it to send.

My question:
Will send eventually finish this operation, or do I need to resend what it didn't send?
If I don't need to resend it and it is trying to finish the operation, what would I look for in its file descriptor so that I know it is complete, if that makes sense, lol.

Ok, I've narrowed it down pretty good. I still have the major bug I'm trying to pin down, when send returns less than what I want it to send.

My question:
Will send eventually finish this operation, or do I need to resend what it didn't send?
If I don't need to resend it and it is trying to finish the operation, what would I look for in its file descriptor so that I know it is complete, if that makes sense, lol.

If you pass send() M bytes and it returns N, then it only sent N bytes, and you are responsible for calling it again to send the remaining M-N bytes. It will not retry. (The TCP/IP layer actually DOES retry, but this is hidden under the covers -- by the time send() returns, all retry attempts have already been done)

If you pass send() M bytes and it returns N, then it only sent N bytes, and you are responsible for calling it again to send the remaining M-N bytes. It will not retry. (The TCP/IP layer actually DOES retry, but this is hidden under the covers -- by the time send() returns, all retry attempts have already been done)

My understanding was that send(), at least for non-blocking sockets, can merely buffer the data somewhere in the kernel (and perhaps, if the link is ready, send it out for the first try.) It's this buffer, however, that is of limited size, and once you exceed that, send() either blocks or returns EWOULDBLOCK (as it would have to wait for the buffer to empty, which takes time, and hence would block.)