Improve the odds of winning the oidentd race when using SSL for IRC
[quassel.git] / src / core / corenetwork.cpp
index 798f27c..552662a 100644 (file)
@@ -18,6 +18,8 @@
  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
  ***************************************************************************/
 
+#include <QHostInfo>
+
 #include "corenetwork.h"
 
 #include "core.h"
@@ -80,7 +82,7 @@ CoreNetwork::CoreNetwork(const NetworkId &networkid, CoreSession *session)
     connect(this, SIGNAL(newEvent(Event *)), coreSession()->eventManager(), SLOT(postEvent(Event *)));
 
     if (Quassel::isOptionSet("oidentd")) {
-        connect(this, SIGNAL(socketInitialized(const CoreIdentity*, QHostAddress, quint16, QHostAddress, quint16)), Core::instance()->oidentdConfigGenerator(), SLOT(addSocket(const CoreIdentity*, QHostAddress, quint16, QHostAddress, quint16)), Qt::BlockingQueuedConnection);
+        connect(this, SIGNAL(socketConnected(const CoreIdentity*, QHostAddress, quint16, QHostAddress, quint16)), Core::instance()->oidentdConfigGenerator(), SLOT(addSocket(const CoreIdentity*, QHostAddress, quint16, QHostAddress, quint16)), Qt::BlockingQueuedConnection);
         connect(this, SIGNAL(socketDisconnected(const CoreIdentity*, QHostAddress, quint16, QHostAddress, quint16)), Core::instance()->oidentdConfigGenerator(), SLOT(removeSocket(const CoreIdentity*, QHostAddress, quint16, QHostAddress, quint16)));
     }
 }
@@ -184,6 +186,10 @@ void CoreNetwork::connectToIrc(bool reconnecting)
 
     enablePingTimeout();
 
+    // Qt caches DNS entries for a minute, resulting in round-robin (e.g. for chat.freenode.net) not working if several users
+    // connect at a similar time. QHostInfo::fromName(), however, always performs a fresh lookup, overwriting the cache entry.
+    QHostInfo::fromName(server.host);
+
 #ifdef HAVE_SSL
     if (server.useSsl) {
         CoreIdentity *identity = identityPtr();
@@ -262,13 +268,16 @@ void CoreNetwork::putCmd(const QString &cmd, const QList<QByteArray> &params, co
 
     if (!prefix.isEmpty())
         msg += ":" + prefix + " ";
-    msg += cmd.toUpper().toAscii();
+    msg += cmd.toUpper().toLatin1();
+
+    for (int i = 0; i < params.size(); i++) {
+        msg += " ";
+
+        if (i == params.size() - 1 && (params[i].contains(' ') || (!params[i].isEmpty() && params[i][0] == ':')))
+            msg += ":";
 
-    for (int i = 0; i < params.size() - 1; i++) {
-        msg += " " + params[i];
+        msg += params[i];
     }
-    if (!params.isEmpty())
-        msg += " :" + params.last();
 
     putRawLine(msg);
 }
@@ -402,7 +411,10 @@ void CoreNetwork::socketHasData()
 {
     while (socket.canReadLine()) {
         QByteArray s = socket.readLine();
-        s.chop(2);
+        if (s.endsWith("\r\n"))
+            s.chop(2);
+        else if (s.endsWith("\n"))
+            s.chop(1);
         NetworkDataEvent *event = new NetworkDataEvent(EventManager::NetworkIncoming, this, s);
 #if QT_VERSION >= 0x040700
         event->setTimestamp(QDateTime::currentDateTimeUtc());
@@ -432,6 +444,15 @@ void CoreNetwork::socketError(QAbstractSocket::SocketError error)
 
 void CoreNetwork::socketInitialized()
 {
+    CoreIdentity *identity = identityPtr();
+    if (!identity) {
+        qCritical() << "Identity invalid!";
+        disconnectFromIrc();
+        return;
+    }
+    
+    emit socketConnected(identity, localAddress(), localPort(), peerAddress(), peerPort());
+    
     Server server = usedServer();
 #ifdef HAVE_SSL
     if (server.useSsl && !socket.isEncrypted())
@@ -440,12 +461,6 @@ void CoreNetwork::socketInitialized()
 #if QT_VERSION >= 0x040600
     socket.setSocketOption(QAbstractSocket::KeepAliveOption, true);
 #endif
-    CoreIdentity *identity = identityPtr();
-    if (!identity) {
-        qCritical() << "Identity invalid!";
-        disconnectFromIrc();
-        return;
-    }
 
     emit socketInitialized(identity, localAddress(), localPort(), peerAddress(), peerPort());