[Help-gnutls] GnuTLS and Qt

Ian Cullinan cibyr at cibyr.com
Sun Nov 4 11:48:47 CET 2007


I'm trying to get to grips with GnuTLS and Qt, so what I'm doing is
building a very simple "chat" program. I've defined:

extern "C" int gcry_qthread_init() { return 0; }
extern "C" int gcry_qmutex_init(void** priv) {
       *priv = (void*)(new QMutex());
       return 0;
}
extern "C" int gcry_qmutex_destroy(void** priv) {
       delete (QMutex*)(*priv);
       return 0;
}
extern "C" int gcry_qmutex_lock(void** priv) {
       ((QMutex*)(*priv))->lock();
       return 0;
}
extern "C" int gcry_qmutex_unlock(void** priv) {
       ((QMutex*)(*priv))->unlock();
       return 0;
}

struct gcry_thread_cbs gcry_threads_qt = {
 GCRY_THREAD_OPTION_USER, gcry_qthread_init, gcry_qmutex_init,
 gcry_qmutex_destroy, gcry_qmutex_lock, gcry_qmutex_unlock,
 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};

and I'm calling
       gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_qt);
       gnutls_global_init();
from the constructor of my main window. Which leads me to my first
question(s): do I need to do that? Or does it not really matter, even
though Qt make pretty heavy use of threads? Have I done something
wrong there? Should I be providing something for the select, waitpid,
accept, etc parts of that struct?

Then, I've defined:
extern "C" ssize_t gnutls_qt_pull(gnutls_transport_ptr_t transPtr,
void* buf, size_t len) {
       QTcpSocket* sock = (QTcpSocket*)transPtr;
       int ret = sock->read((char*)buf, (qint64)len);
       if (ret == -1) {
               cerr << "ERROR: " << sock->errorString().toStdString() << endl;
       }
       return ret;
}
extern "C" ssize_t gnutls_qt_push(gnutls_transport_ptr_t transPtr,
               const void* data, size_t len) {
       QTcpSocket* sock = (QTcpSocket*)transPtr;
       int ret = sock->write((const char*)data, (qint64)len);
       if (ret == -1) {
               cerr << "ERROR: " << sock->errorString().toStdString() << endl;
       }
       return ret;
}

When my "listen" button is clicked I do:
               gnutls_anon_allocate_server_credentials(&servercred);
               gnutls_dh_params_init(&dh_params);
               gnutls_dh_params_generate2(dh_params, DH_BITS);
               gnutls_anon_set_server_dh_params(servercred, dh_params);

               tcpServer = new QTcpServer(this);
               if (!tcpServer->listen(QHostAddress::Any,
                               (quint16)ui.listenPortSpinBox->value())) {
                       QMessageBox::critical(this, "Error listening",
tcpServer->errorString());
                       delete tcpServer;
                       return;
               }

               connect(tcpServer, SIGNAL(newConnection()), this,
                               SLOT(handleNewConnection()));

So on an incoming connection, handleNewConnection() gets called.
void tls_chat::handleNewConnection() {
       QTcpSocket* tcpSocket = tcpServer->nextPendingConnection();
       gnutls_session_t session;
       const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };

       gnutls_init(&session, GNUTLS_SERVER);
       gnutls_set_default_priority(session);
       gnutls_kx_set_priority(session, kx_prio);

       gnutls_credentials_set(session, GNUTLS_CRD_ANON, servercred);
       gnutls_dh_set_prime_bits(session, DH_BITS);

       gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t)tcpSocket);
       gnutls_transport_set_pull_function(session, gnutls_qt_pull);
       gnutls_transport_set_push_function(session, gnutls_qt_push);

       int ret;
       do {
               ret = gnutls_handshake(session);
       } while (ret == GNUTLS_E_AGAIN);

       if(ret < 0) {
               QMessageBox::critical(this, "Error",
                               QString("TLS Handshake failed with error: ")
                               + QString(gnutls_strerror(ret)), QMessageBox::Ok,
                               QMessageBox::NoButton);
               gnutls_bye(session, GNUTLS_SHUT_RDWR);
               tcpSocket->close();
               gnutls_deinit(session);
               delete tcpSocket;
               return;
       }

       chatWindow* window = new chatWindow(tcpSocket, session);
       window->show();
}

On any incoming connection (from my own code, or form gnutls-cli, I
get "A TLS packet with unexpected length was received." Nothing
appears in my console, so I don't think QTcpSocket is giving errors.
What am I missing here? I've copied the "Echo Server with Anonymous
Authentication" example almost exactly. Am I taking the right approach
by wrapping QMutex and QTcpSocket?

I'd really appreciate any help or advice, so thanks in advance and
apologies for this long, code-heavy message. If it helps any, I'm on
windows XP with gnutls 2.0.2, Qt 4.3.2 and MinGW 5.1.3

Cheers,

Ian Cullinan





More information about the Gnutls-help mailing list