C Board  

Go Back   C Board > General Programming Boards > Networking/Device Communication

Reply
 
LinkBack Thread Tools Display Modes
Old 07-23-2009, 01:20 AM   #1
Registered User
 
carrotcake1029's Avatar
 
Join Date: Apr 2008
Posts: 299
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!

Edit: I used MinGW (gcc 4.4) to compile this. I am on Windows.
Attached Files
File Type: c main.c (4.2 KB, 31 views)
carrotcake1029 is offline   Reply With Quote
Old 07-23-2009, 02:00 AM   #2
Guest
 
Sebastiani's Avatar
 
Join Date: Aug 2001
Posts: 4,923
>> Am I missing data?

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.

>> By the way, I configured Firefox 3.5 to use my server.

Good idea.
Sebastiani is offline   Reply With Quote
Old 07-23-2009, 02:04 AM   #3
Guest
 
Sebastiani's Avatar
 
Join Date: Aug 2001
Posts: 4,923
I just thought of one more thing. CreateThread can have problems with memory leaks, which after awhile adds up to quite a bit of memory. I'd recommend _beginthreadex/_endthreadex, if possible.
Sebastiani is offline   Reply With Quote
Old 07-23-2009, 05:51 AM   #4
int x = *((int *) NULL);
 
Cactus_Hugger's Avatar
 
Join Date: Jul 2003
Location: Banks of the River Styx
Posts: 891
Good things:
1) Much error checking, keep this up.

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.
__________________
long time; /* know C? */
Unprecedented performance: Nothing ever ran this slow before.
Any sufficiently advanced bug is indistinguishable from a feature.
Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
The best way to accelerate an IBM is at 9.8 m/s/s.
recursion (re - cur' - zhun) n. 1. (see recursion)
Cactus_Hugger is offline   Reply With Quote
Old 07-23-2009, 10:51 AM   #5
Registered User
 
carrotcake1029's Avatar
 
Join Date: Apr 2008
Posts: 299
Thanks a ton for looking at it. I know its a lot. I will be sure to fix everything you mentioned and let you know if it does better. I forgot about WSAEWOULDBLOCK... :P

Edit: Haha, the main problem was me not checking for WSAEWOULDBLOCK on recv. Thanks for spotting my oversight. I'll also be sure everything is being checked for errors.

Last edited by carrotcake1029; 07-23-2009 at 12:03 PM.
carrotcake1029 is offline   Reply With Quote
Old 07-23-2009, 01:12 PM   #6
Registered User
 
carrotcake1029's Avatar
 
Join Date: Apr 2008
Posts: 299
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.
carrotcake1029 is offline   Reply With Quote
Old 07-23-2009, 04:43 PM   #7
int x = *((int *) NULL);
 
Cactus_Hugger's Avatar
 
Join Date: Jul 2003
Location: Banks of the River Styx
Posts: 891
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
Code:
struct
{
    unsigned char data[SOME_MAGICAL_CONSTANT];
    size_t used, size_t send;
}
Keep a tag to the last one around, so you don't end up with 400 of them only 1% filled.
__________________
long time; /* know C? */
Unprecedented performance: Nothing ever ran this slow before.
Any sufficiently advanced bug is indistinguishable from a feature.
Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
The best way to accelerate an IBM is at 9.8 m/s/s.
recursion (re - cur' - zhun) n. 1. (see recursion)
Cactus_Hugger is offline   Reply With Quote
Old 07-23-2009, 06:23 PM   #8
Registered User
 
carrotcake1029's Avatar
 
Join Date: Apr 2008
Posts: 299
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.

Thanks again for your help.

Would this be an accurate way of handling the whole recv stuff:
Code:
            if(FD_ISSET(out, &fd))
            {
                r = recv(out, buff, 1048576, 0);

                if (r == SOCKET_ERROR)
                {
                    if (WSAGetLastError() != WSAEWOULDBLOCK)
                    {
                        closesocket(in);
                        closesocket(out);
                        puts("error@recv@thread@server");
                        break;
                    }
                }

                if (r != SOCKET_ERROR)
                {
                    if (r > 0)
                    {
                        send(in, buff, r, 0);
                        /* will add handler later */
                    }
                    else
                    {
                        closesocket(in);
                        closesocket(out);
                        puts("server disconnected");
                        break;
                    }
                }
            }

Last edited by carrotcake1029; 07-23-2009 at 06:52 PM.
carrotcake1029 is offline   Reply With Quote
Old 07-23-2009, 11:10 PM   #9
Registered User
 
carrotcake1029's Avatar
 
Join Date: Apr 2008
Posts: 299
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.
carrotcake1029 is offline   Reply With Quote
Old 07-24-2009, 10:12 AM   #10
Senior software engineer
 
brewbuck's Avatar
 
Join Date: Mar 2007
Location: Portland, OR
Posts: 5,381
Quote:
Originally Posted by carrotcake1029 View Post
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)
__________________
"Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously." -- raftpeople@slashdot
brewbuck is offline   Reply With Quote
Old 07-24-2009, 01:26 PM   #11
Registered User
 
carrotcake1029's Avatar
 
Join Date: Apr 2008
Posts: 299
Ok, what I thought. When I get some time I'll see if I can write a good routine to get this working properly. Thank you.
carrotcake1029 is offline   Reply With Quote
Old 07-24-2009, 03:31 PM   #12
int x = *((int *) NULL);
 
Cactus_Hugger's Avatar
 
Join Date: Jul 2003
Location: Banks of the River Styx
Posts: 891
Quote:
Originally Posted by brewbuck View Post
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.)
__________________
long time; /* know C? */
Unprecedented performance: Nothing ever ran this slow before.
Any sufficiently advanced bug is indistinguishable from a feature.
Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
The best way to accelerate an IBM is at 9.8 m/s/s.
recursion (re - cur' - zhun) n. 1. (see recursion)
Cactus_Hugger is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Lame null append cause buffer to crash cmoo C Programming 8 12-29-2008 03:27 AM
Program Crashing Pressure C Programming 3 04-18-2005 10:28 PM
Binary Tree, couple questions scoobasean C Programming 3 03-12-2005 09:09 PM
Data missing in variable nizbit C Programming 8 03-07-2005 08:22 AM
odd errors from msvc std library files blight2c C++ Programming 6 04-30-2002 12:06 AM


All times are GMT -6. The time now is 03:23 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22