Any ideas what I'm missing?
You want a delayed handshake. Ideologically it goes like this:
You create the QSslSocket object, but operate it as a QTcpSocket. The server and client exchange TCP messages (as per your liking) to try and negotiate whether they should stay in plain TCP or in SSL mode. When the connection is decided to be used over SSL the client calls startClientEncryption, while the server socket calls startServerEncryption to begin the actual SSL handshake. Connecting the TCP error and sslErrors() signals is a must.