[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