X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcore%2Fidentserver.cpp;h=1335a6c0147a2e73238e01bf9a2925acd1966c6f;hp=c1cb5d036bc34805decceb72607f12c78b0415f5;hb=8bdfd0d16857c508f543298ad98f6262127f2886;hpb=dcc39bc640adc4dc1b326162dbe8d682cb035447 diff --git a/src/core/identserver.cpp b/src/core/identserver.cpp index c1cb5d03..1335a6c0 100644 --- a/src/core/identserver.cpp +++ b/src/core/identserver.cpp @@ -33,19 +33,65 @@ IdentServer::IdentServer(QObject* parent) bool IdentServer::startListening() { - uint16_t port = Quassel::optionValue("ident-port").toUShort(); - bool success = false; - if (_v6server.listen(QHostAddress("::"), port)) { - qInfo() << qPrintable(tr("Listening for identd clients on IPv6 %1 port %2").arg("::").arg(_v6server.serverPort())); - - success = true; - } - if (_server.listen(QHostAddress("0.0.0.1"), port)) { - qInfo() << qPrintable(tr("Listening for identd clients on IPv4 %1 port %2").arg("0.0.0.1").arg(_server.serverPort())); + uint16_t port = Quassel::optionValue("ident-port").toUShort(); - success = true; + const QString listen = Quassel::optionValue("ident-listen"); + const QStringList listen_list = listen.split(",", QString::SkipEmptyParts); + for (const QString &listen_term : listen_list) { // TODO: handle multiple interfaces for same TCP version gracefully + QHostAddress addr; + if (!addr.setAddress(listen_term)) { + qCritical() << qPrintable( + tr("Invalid listen address %1") + .arg(listen_term) + ); + } + else { + switch (addr.protocol()) { + case QAbstractSocket::IPv6Protocol: + if (_v6server.listen(addr, port)) { + qInfo() << qPrintable( + tr("Listening for identd requests on IPv6 %1 port %2") + .arg(addr.toString()) + .arg(_v6server.serverPort()) + ); + success = true; + } + else + qWarning() << qPrintable( + tr("Could not open IPv6 interface %1:%2: %3") + .arg(addr.toString()) + .arg(port) + .arg(_v6server.errorString())); + break; + case QAbstractSocket::IPv4Protocol: + if (_server.listen(addr, port)) { + qInfo() << qPrintable( + tr("Listening for identd requests on IPv4 %1 port %2") + .arg(addr.toString()) + .arg(_server.serverPort()) + ); + success = true; + } + else { + // if v6 succeeded on Any, the port will be already in use - don't display the error then + if (!success || _server.serverError() != QAbstractSocket::AddressInUseError) + qWarning() << qPrintable( + tr("Could not open IPv4 interface %1:%2: %3") + .arg(addr.toString()) + .arg(port) + .arg(_server.errorString())); + } + break; + default: + qCritical() << qPrintable( + tr("Invalid listen address %1, unknown network protocol") + .arg(listen_term) + ); + break; + } + } } if (!success) { @@ -104,17 +150,22 @@ void IdentServer::respond() else if (query.endsWith("\n")) query.chop(1); + qDebug() << "Received identd query" << query << "from" << socket->peerAddress(); + QList split = query.split(','); - bool success = false; + bool successLocalPort = false; + bool successRemotePort = false; quint16 localPort = 0; - if (!split.empty()) { - localPort = split[0].trimmed().toUShort(&success, 10); + quint16 remotePort = 0; + if (split.length() == 2) { + localPort = split[0].trimmed().toUShort(&successLocalPort, 10); + remotePort = split[1].trimmed().toUShort(&successRemotePort, 10); } - Request request{socket, localPort, query, transactionId, _requestId++}; - if (!success) { + Request request{socket, localPort, remotePort, query, transactionId, _requestId++}; + if (!successLocalPort || !successRemotePort) { request.respondError("INVALID-PORT"); } else if (responseAvailable(request)) { @@ -131,20 +182,28 @@ void IdentServer::respond() void Request::respondSuccess(const QString& user) { if (socket) { - QString data = query + " : USERID : Quassel : " + user + "\r\n"; + QString data = QString("%1, %2 : USERID : Quassel : %3\r\n") + .arg(QString::number(localPort)) + .arg(QString::number(remotePort)) + .arg(user); + qDebug() << "answering identd request from" << socket->peerAddress() << "with" << data; socket->write(data.toUtf8()); socket->flush(); - socket->close(); + QTimer::singleShot(DISCONNECTION_TIMEOUT, socket, &QTcpSocket::close); } } void Request::respondError(const QString& error) { if (socket) { - QString data = query + " : ERROR : " + error + "\r\n"; + QString data = QString("%1, %2 : ERROR : %3\r\n") + .arg(QString::number(localPort)) + .arg(QString::number(remotePort)) + .arg(error); + qDebug() << "answering identd request from" << socket->peerAddress() << "with" << data; socket->write(data.toUtf8()); socket->flush(); - socket->close(); + QTimer::singleShot(DISCONNECTION_TIMEOUT, socket, &QTcpSocket::close); } } @@ -171,7 +230,7 @@ void IdentServer::addSocket(const CoreIdentity* identity, const CoreNetwork* network = qobject_cast(sender()); _connections[localPort] = network->coreSession()->strictCompliantIdent(identity); - ; + processWaiting(socketId); }