Thread: Am I missing data?

  1. #1
    Registered User carrotcake1029's Avatar
    Join Date
    Apr 2008
    Posts
    404

    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.

  2. #2
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> 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.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  3. #3
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    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.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  4. #4
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    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)

  5. #5
    Registered User carrotcake1029's Avatar
    Join Date
    Apr 2008
    Posts
    404
    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.

  6. #6
    Registered User carrotcake1029's Avatar
    Join Date
    Apr 2008
    Posts
    404
    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.

  7. #7
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    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)

  8. #8
    Registered User carrotcake1029's Avatar
    Join Date
    Apr 2008
    Posts
    404
    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.

  9. #9
    Registered User carrotcake1029's Avatar
    Join Date
    Apr 2008
    Posts
    404
    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.

  10. #10
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    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)
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  11. #11
    Registered User carrotcake1029's Avatar
    Join Date
    Apr 2008
    Posts
    404
    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.

  12. #12
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    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)

Popular pages Recent additions subscribe to a feed

Similar Threads

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