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. Problem with a QTcpSocket
QtWS25 Last Chance

Problem with a QTcpSocket

Scheduled Pinned Locked Moved Unsolved General and Desktop
socketssl
14 Posts 3 Posters 6.2k Views
  • 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.
  • moffa13M Offline
    moffa13M Offline
    moffa13
    wrote on last edited by moffa13
    #1

    Hi all !

    I am trying to handle non SSL requests with a QSSLSocket and send error message to the client. What I'm doing is this.

    void Connection::sslErrors(QAbstractSocket::SocketError e){
        if(e == QAbstractSocket::SslHandshakeFailedError){
            QTcpSocket *s = new QTcpSocket;
            qintptr sd = m_socket->socketDescriptor();
            m_socket->deleteLater();
            s->setSocketDescriptor(sd);
            m_socket = s;
            m_socket->write("Please use SSL");
            m_socket->flush();
        }
    }
    

    It works fine but every non-ssl request I do i get this warning :

    "QSocketNotifier: Multiple socket notifiers for same socket 760 and type Read"

    I think it's because I have two sockets with the same socketDescriptor at the same time.

    I read this in the QAbstractSocket doc :

    When this signal is emitted, the socket may not be ready for a reconnect attempt. In that case, attempts to reconnect should be done from the event loop. For example, use a QTimer::singleShot() with 0 as the timeout.

    So I did the following :

    void Connection::sslErrors(QAbstractSocket::SocketError e){
        if(e == QAbstractSocket::SslHandshakeFailedError){
            QTimer::singleShot(0, this, SLOT(sendSSLError()));
        }
    }
    
    void Connection::sendSSLError(){
         m_socket->write("Please use SSL");
         m_socket->flush();
    }
    

    But in there the socket is already closed.

    What can I do ? Thanks !

    kshegunovK 1 Reply Last reply
    0
    • moffa13M moffa13

      Hi all !

      I am trying to handle non SSL requests with a QSSLSocket and send error message to the client. What I'm doing is this.

      void Connection::sslErrors(QAbstractSocket::SocketError e){
          if(e == QAbstractSocket::SslHandshakeFailedError){
              QTcpSocket *s = new QTcpSocket;
              qintptr sd = m_socket->socketDescriptor();
              m_socket->deleteLater();
              s->setSocketDescriptor(sd);
              m_socket = s;
              m_socket->write("Please use SSL");
              m_socket->flush();
          }
      }
      

      It works fine but every non-ssl request I do i get this warning :

      "QSocketNotifier: Multiple socket notifiers for same socket 760 and type Read"

      I think it's because I have two sockets with the same socketDescriptor at the same time.

      I read this in the QAbstractSocket doc :

      When this signal is emitted, the socket may not be ready for a reconnect attempt. In that case, attempts to reconnect should be done from the event loop. For example, use a QTimer::singleShot() with 0 as the timeout.

      So I did the following :

      void Connection::sslErrors(QAbstractSocket::SocketError e){
          if(e == QAbstractSocket::SslHandshakeFailedError){
              QTimer::singleShot(0, this, SLOT(sendSSLError()));
          }
      }
      
      void Connection::sendSSLError(){
           m_socket->write("Please use SSL");
           m_socket->flush();
      }
      

      But in there the socket is already closed.

      What can I do ? Thanks !

      kshegunovK Offline
      kshegunovK Offline
      kshegunov
      Moderators
      wrote on last edited by
      #2

      @moffa13
      Hello,
      What you're doing is very iffy. If I understand correctly what you want to accomplish, then call QSSLSocket:: ignoreSslErrors and then write to the unencrypted socket.
      See the relevant documentation page.

      Kind regards.

      Read and abide by the Qt Code of Conduct

      1 Reply Last reply
      0
      • moffa13M Offline
        moffa13M Offline
        moffa13
        wrote on last edited by moffa13
        #3

        Thanks for your reply.

        The error thrown is QAbstractSocket::SslHandshakeFailedError (13) handled with the signal (error) and not with the signal (sslErrors) so I can't handle it with ignoreSslErrors and event if I could what should I do ?

        When you say "write to the unencrypted socket", I don't know how to remove the encryption to write as plaintext because there is the startServerEncryption method but I thing there is no reverse function.

        kshegunovK 1 Reply Last reply
        0
        • moffa13M moffa13

          Thanks for your reply.

          The error thrown is QAbstractSocket::SslHandshakeFailedError (13) handled with the signal (error) and not with the signal (sslErrors) so I can't handle it with ignoreSslErrors and event if I could what should I do ?

          When you say "write to the unencrypted socket", I don't know how to remove the encryption to write as plaintext because there is the startServerEncryption method but I thing there is no reverse function.

          kshegunovK Offline
          kshegunovK Offline
          kshegunov
          Moderators
          wrote on last edited by
          #4

          @moffa13
          That's why linked the documentation page. See what it says there:

          If an error occurs, QSslSocket emits the sslErrors() signal. In this case, if no action is taken to ignore the error(s), the connection is dropped. To continue, despite the occurrence of an error, you can call ignoreSslErrors(), either from within this slot after the error occurs, or any time after construction of the QSslSocket and before the connection is attempted. This will allow QSslSocket to ignore the errors it encounters when establishing the identity of the peer. Ignoring errors during an SSL handshake should be used with caution, since a fundamental characteristic of secure connections is that they should be established with a successful handshake.

          So as I see it, you connect the sslErrors signal to your slot, call ignoreSslErrors and after that use the socket as if it weren't an SSL socket, but rather plain ol' QTcpSocket.

          Kind regards.

          Read and abide by the Qt Code of Conduct

          1 Reply Last reply
          0
          • moffa13M Offline
            moffa13M Offline
            moffa13
            wrote on last edited by moffa13
            #5

            I already did that; the problem is with my with slot because it's not called.

            So with this code

            void Connection::sslErrors(const QList<QSslError> &errors){
                std::cout << "SSL error !";
            }
            

            The error message is not written. Here's my connect :

              connect(m_socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(sslErrors(const QList<QSslError> &)));
            

            As I said only de error signal is called

            What did I do wrong ?

            kshegunovK 1 Reply Last reply
            0
            • moffa13M moffa13

              I already did that; the problem is with my with slot because it's not called.

              So with this code

              void Connection::sslErrors(const QList<QSslError> &errors){
                  std::cout << "SSL error !";
              }
              

              The error message is not written. Here's my connect :

                connect(m_socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(sslErrors(const QList<QSslError> &)));
              

              As I said only de error signal is called

              What did I do wrong ?

              kshegunovK Offline
              kshegunovK Offline
              kshegunov
              Moderators
              wrote on last edited by
              #6

              @moffa13
              Yeah, I'm talking nonsense. sslErrors() will not be emitted before the handshake has completed, which in your case it doesn't. See instead QSslSocket::startClientEncryption and QSslSocket::startServerEncryption, which are specifically tailored for delayed handshakes.

              Kind regards.

              Read and abide by the Qt Code of Conduct

              1 Reply Last reply
              0
              • moffa13M Offline
                moffa13M Offline
                moffa13
                wrote on last edited by
                #7

                I don't really see how to do this

                kshegunovK 1 Reply Last reply
                0
                • moffa13M moffa13

                  I don't really see how to do this

                  kshegunovK Offline
                  kshegunovK Offline
                  kshegunov
                  Moderators
                  wrote on last edited by
                  #8

                  @moffa13
                  As far as understand it (I haven't done this) you create your socket as usual. But instead of calling QSslSocket::connectToHostEncrypted , you call the regular connectToHost. And at one point, when you want to upgrade to an encrypted connection you call the QSslSocket::startClientEncryption. There are a few notes in the docs of how to do it for the server side too. However, I'm not that convinced that is what you want to do ... am I misunderstand you?

                  Kind regards.

                  Read and abide by the Qt Code of Conduct

                  1 Reply Last reply
                  0
                  • moffa13M Offline
                    moffa13M Offline
                    moffa13
                    wrote on last edited by moffa13
                    #9

                    Actually I am the server so I'm calling QSslSocket::startServerEncryption then the error is thrown. See the code:

                    void SSLServer::incomingConnection(qintptr socketDescriptor)
                    {
                        QScopedPointer<QSslSocket> socket(new QSslSocket(this));
                        if (socket->setSocketDescriptor(socketDescriptor)) {
                    
                            socket->addCaCertificate(certificate);
                            socket->setLocalCertificate(certificate);
                            socket->setPrivateKey(key);
                            
                            socket->startServerEncryption();
                            queue.enqueue(socket.take());
                        }
                    }
                    

                    Maybe I can do something with the slot(error) because at this point I can see the ssl error (handshake failed) and if I sleep the program the connection is closed yet. So, with this:

                    void Connection::error(QAbstractSocket::SocketError e){
                        std::cout << "SSL error ! code : " << e;
                    }
                    

                    This is written "SSL error ! code : 13" and if I add _sleep(1000) the connection is not dropped yet so maybe I can do something with it.

                    kshegunovK 1 Reply Last reply
                    0
                    • moffa13M moffa13

                      Actually I am the server so I'm calling QSslSocket::startServerEncryption then the error is thrown. See the code:

                      void SSLServer::incomingConnection(qintptr socketDescriptor)
                      {
                          QScopedPointer<QSslSocket> socket(new QSslSocket(this));
                          if (socket->setSocketDescriptor(socketDescriptor)) {
                      
                              socket->addCaCertificate(certificate);
                              socket->setLocalCertificate(certificate);
                              socket->setPrivateKey(key);
                              
                              socket->startServerEncryption();
                              queue.enqueue(socket.take());
                          }
                      }
                      

                      Maybe I can do something with the slot(error) because at this point I can see the ssl error (handshake failed) and if I sleep the program the connection is closed yet. So, with this:

                      void Connection::error(QAbstractSocket::SocketError e){
                          std::cout << "SSL error ! code : " << e;
                      }
                      

                      This is written "SSL error ! code : 13" and if I add _sleep(1000) the connection is not dropped yet so maybe I can do something with it.

                      kshegunovK Offline
                      kshegunovK Offline
                      kshegunov
                      Moderators
                      wrote on last edited by
                      #10

                      @moffa13
                      If you get "SSL error ! code : 13" then you should also get the sslErrors() signal. You could try calling ignoreSslErrors() inside the error handler and this will hopefully prevent the socket from closing the connection.

                      Kind regards.

                      Read and abide by the Qt Code of Conduct

                      1 Reply Last reply
                      0
                      • moffa13M Offline
                        moffa13M Offline
                        moffa13
                        wrote on last edited by
                        #11

                        I wrote this :

                        
                        connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError)));
                        connect(m_socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(sslErrors(const QList<QSslError> &)));
                        
                        ...
                        
                        void Connection::error(QAbstractSocket::SocketError e){
                            std::cout << "SSL error ! code : " << e;
                            m_socket->ignoreSslErrors();
                            write("Please use SSL");
                        }
                        
                        void Connection::sslErrors(const QList<QSslError> &errors){
                            std::cout << "Fuck it ";
                            std::cout << "SSL error " << errors.length();
                            m_socket->ignoreSslErrors();
                            write("Please use SSL");
                        }
                        

                        Only the first works and the ignoreSslErrors() doesn't change anything.

                        kshegunovK 1 Reply Last reply
                        0
                        • moffa13M moffa13

                          I wrote this :

                          
                          connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError)));
                          connect(m_socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(sslErrors(const QList<QSslError> &)));
                          
                          ...
                          
                          void Connection::error(QAbstractSocket::SocketError e){
                              std::cout << "SSL error ! code : " << e;
                              m_socket->ignoreSslErrors();
                              write("Please use SSL");
                          }
                          
                          void Connection::sslErrors(const QList<QSslError> &errors){
                              std::cout << "Fuck it ";
                              std::cout << "SSL error " << errors.length();
                              m_socket->ignoreSslErrors();
                              write("Please use SSL");
                          }
                          

                          Only the first works and the ignoreSslErrors() doesn't change anything.

                          kshegunovK Offline
                          kshegunovK Offline
                          kshegunov
                          Moderators
                          wrote on last edited by
                          #12

                          @moffa13
                          That is strange. I'm sorry I don't know, I can't see anything wrong with the snippets you provided. As far as I understand it, the signal should be raised (and you should get your slot executed).

                          Kind regards.

                          Read and abide by the Qt Code of Conduct

                          1 Reply Last reply
                          0
                          • moffa13M Offline
                            moffa13M Offline
                            moffa13
                            wrote on last edited by moffa13
                            #13

                            Hello,

                            I'm sending to you a short version my code, maybe you can try something ? If you want me to write it here, I'll do it.

                            https://mega.nz/#!0AQxzYjZ!PDXxC-QgsWlBJYnwtQEk16jNdQiXy-d-S4AfkRWeoPc

                            1 Reply Last reply
                            0
                            • M Offline
                              M Offline
                              marcbf
                              wrote on last edited by
                              #14

                              I currently have a very similar problem. I'm implementing a send mail client which should gracefully fall back to an unencrypted connection if encryption fails (and the user has decided to go ahead anyway). For that purpose I've connected to the QAbstractSocket::error() signal.

                              While I do get the signal it's ultimately moot since the code in question (QSslSocketBackendPrivate::startHandshake() in qsslsocket_openssl.cpp) immediately closes the socket by calling QSslSocket::abort() after emitting the signal. Because of that calling QSslSocket::ignoreSslErrors() is never an option.

                              I currently have no workaround in place. Maybe the only solution is to connect to the disconnected() signal and then check whether the connection was closed because of a handshake error. If it was, then open a new unencrypted socket/connection. I'm open to suggestions, though... :-)

                              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