Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to check incomingConnection for valid IP before starting QTcpSocket in separate thread
Forum Updated to NodeBB v4.3 + New Features

How to check incomingConnection for valid IP before starting QTcpSocket in separate thread

Scheduled Pinned Locked Moved General and Desktop
18 Posts 4 Posters 8.6k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • martin_kyM Offline
    martin_kyM Offline
    martin_ky
    wrote on last edited by
    #9

    I see your confusion. The qintptr is not really a pointer, but a pointer-sized integer value. Pointer-sized integers (or INTPTRs) are commonly used to pass native handle values of various objects of the underlying operating system. For example, on Windows a file (or socket) handle is defined as the WINAPI type HANDLE which is in turn defined as void pointer. On Linux and unixes a file or socket handle (more commonly called a 'file descriptor' on unix platforms) is defined as a simple int. Qt hides this underlying platform details and uses a qintptr type to pass native handle values. Such type is guaranteed to be able to represent both int values as well as pointer values.

    The documentation on "QTcpServer::incomingConnection()":http://qt-project.org/doc/qt-5.0/qtnetwork/qtcpserver.html#incomingConnection tells us that the socketDescriptor argument is the native socket descriptor for the accepted connection.

    Bottom line: the socketDescriptor is not a pointer to some object, it is a value that you can use directly in any native calls, including getpeername(). You will probably get a warning about casting to a smaller/different type, but you can safely ignore that, or add an explicit (int) cast.

    1 Reply Last reply
    0
    • B Offline
      B Offline
      bbbill
      wrote on last edited by
      #10

      martin_ky, thanks for your hints. After ours of head ache I looked up the internet for the getpeername() method you mentioned and finally found a Windows site where these socket basics are explained. Hope I´ll find way through this now.

      BTW working on a Win-OS hopefully will not kick me out of the decent part of mankind in the eyes of the rest of the world.

      1 Reply Last reply
      0
      • martin_kyM Offline
        martin_kyM Offline
        martin_ky
        wrote on last edited by
        #11

        Unless it was clear from my last post and from the Qt documentation: the qintptr IS the native socket descriptor of the incoming connection.

        Your incomingConnection() implementation can use it like this:

        @void MyTcpServer::incomingConnection(qintptr socketDescriptor)
        {
        sockaddr nativeAddress;
        int sz = sizeof nativeAddress;
        getpeername(socketDescriptor, &nativeAddress, &sz);
        QHostAddress address(&nativeAddress);
        qDebug() << "Peer address is:" << address.toString();

        //TODO: decide what to do with the incoming connection
        

        }
        @

        On Windows, don't forget to include WinSock2.h and link the Ws2_32.lib

        1 Reply Last reply
        0
        • B Offline
          B Offline
          bbbill
          wrote on last edited by
          #12

          Following the hints of your last post I had found the Win-Socket stuff on the internet and after some hours of head scratching came to a similar code, which did not work. Now I copied your snippet (thanks!) into my code. For reasons I cannot conceive of, it does not work for me either:

          @void TcpServerThreaded::incomingConnection(qintptr socketDescriptor){
          sockaddr nativeAddress;
          int sz = sizeof nativeAddress;
          if(getpeername(socketDescriptor, &nativeAddress, &sz)== SOCKET_ERROR){
          emit annotation(new QString("there is only little hope\n"));
          }else{
          QHostAddress address(&nativeAddress);
          emit annotation(new QString(address.toString()));
          }
          ...
          }
          @
          Compiles without errors, but guess what annotation I get...

          1 Reply Last reply
          0
          • martin_kyM Offline
            martin_kyM Offline
            martin_ky
            wrote on last edited by
            #13

            For the fun of it, I tried to compile it both on Qt 5.0.2 and Qt 4.8.3 (Windows, MSVC).

            On 4.8.3 works OK. But on 5.0.2 I'm getting the following error:

            • getpeername() returns -1 (SOCKET_ERROR)
            • WSAGetLastError() returns 10014 (WSAEFAULT)

            I have absolutely no idea why it works on Qt 4 and not on Qt 5 :(

            1 Reply Last reply
            0
            • B Offline
              B Offline
              bbbill
              wrote on last edited by
              #14

              I will try to find out a little more about it. Try and error etc.. Nevertheless great hints you gave me. Thanks again.

              1 Reply Last reply
              0
              • martin_kyM Offline
                martin_kyM Offline
                martin_ky
                wrote on last edited by
                #15

                You're welcome. It seems to me, that something changed between Qt 4 -> Qt 5, which makes this approach unusable on Windows.

                Perhaps somebody from the Qt developers could look at this more closely?

                1 Reply Last reply
                0
                • B Offline
                  B Offline
                  bbbill
                  wrote on last edited by
                  #16

                  Found a solution, however did not yet understand fully why it works:
                  the ERRORCODE from WSAGetLastError() 10014 means something like address(-size) error.
                  (See http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx)
                  So I assumed there must be something going wrong in the header file with the selection of the proper structure to use. Then I just increased the value of @ int sz = sizeof nativeAddress;@, which is being passed as a parameter to getpeername().
                  After having added 12 to sz, all of a sudden it worked.
                  Thanks to all again and especially to martin_ky.

                  1 Reply Last reply
                  0
                  • martin_kyM Offline
                    martin_kyM Offline
                    martin_ky
                    wrote on last edited by
                    #17

                    Ok, I figured this out (I was curious :). Bbbill, you're on the right track with the size of the sockaddr sturcture. This struct simply is not big enough to hold IPv6 addresses.

                    Do not just blindly increase the passed size of the address structure, or you will most certainly corrupt your stack. Instead sockaddr, use the sockaddr_storage struct, which is large enough to contain also IPv6 addresses. More light on this in "this thread.":http://stackoverflow.com/questions/8835322/api-using-sockaddr-storage

                    The difference between Qt 4 and 5 which I was talking about was in my QTcpServer::listen(QHostAddress::Any) call:

                    • QHostAddress::Any in Qt 4 means "listen on all IPv4 interfaces".
                    • but in Qt 5 "listen on all IPv4 and all IPv6 interfaces".

                    Therefore I was getting IPv6 connections when compiled with Qt 5, but not in Qt 4. If you don't want to use IPv6 and save some trouble, just make your QTcpServer listen only on QHostAddress::AnyIPv4. In this case, my original code works perfectly.

                    1 Reply Last reply
                    0
                    • B Offline
                      B Offline
                      bbbill
                      wrote on last edited by
                      #18

                      Yes, your recommendation makes sense. I changed my code for "sockaddr_storage". Have to use a cast in getpeername() now. Nasty but sure much more reliable than my tweeking with magic numbers.
                      Also I had to initialise the winsocket-dll by WSAStartup()-call prior to using native methods, otherwise it would not work. As I would like to leverage my programm to ip6 capability, I'll stick with this more general approach and go on learning to get it running. Thanks a lot.

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved