Пример #1
0
MythSocket *MythCoreContext::ConnectEventSocket(const QString &hostname,
                                                int port)
{
    MythSocket *eventSock = new MythSocket();

    while (eventSock->state() != MythSocket::Idle)
    {
        usleep(5000);
    }

    // Assume that since we _just_ connected the command socket,
    // this one won't need multiple retries to work...
    if (!eventSock->connect(hostname, port))
    {
        LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to connect event "
                                       "socket to master backend");
        eventSock->DecrRef();
        return NULL;
    }

    eventSock->Lock();

    QString str = QString("ANN Monitor %1 %2")
        .arg(d->m_localHostname).arg(true);
    QStringList strlist(str);
    eventSock->writeStringList(strlist);
    bool ok = true;
    if (!eventSock->readStringList(strlist) || strlist.empty() ||
        (strlist[0] == "ERROR"))
    {
        if (!strlist.empty())
        {
            LOG(VB_GENERAL, LOG_ERR, LOC +
                "Problem connecting event socket to master backend");
        }
        else
        {
            LOG(VB_GENERAL, LOG_ERR, LOC +
                "Timeout connecting event socket to master backend");
        }
        ok = false;
    }

    eventSock->Unlock();

    if (ok)
    {
        eventSock->setCallbacks(this);
    }
    else
    {
        eventSock->DecrRef();
        eventSock = NULL;
    }

    return eventSock;
}
Пример #2
0
static bool RemoteSendReceiveStringList(const QString &host, QStringList &strlist)
{
    bool ok = false;

    if (gCoreContext->IsMasterBackend())
    {
        // since the master backend cannot connect back around to
        // itself, and the libraries do not have access to the list
        // of connected slave backends to query an existing connection
        // start up a new temporary connection directly to the slave
        // backend to query the file list
        QString ann = QString("ANN Playback %1 0")
                        .arg(gCoreContext->GetHostName());
        QString addr = gCoreContext->GetBackendServerIP(host);
        int port = gCoreContext->GetBackendServerPort(host);
        bool mismatch = false;

        MythSocket *sock = gCoreContext->ConnectCommandSocket(
                                            addr, port, ann, &mismatch);
        if (sock)
        {
            ok = sock->SendReceiveStringList(strlist);
            sock->DecrRef();
        }
        else
            strlist.clear();
    }
    else
        ok = gCoreContext->SendReceiveStringList(strlist);

    return ok;
}
Пример #3
0
bool RemoteGetFileList(QString host, QString path, QStringList* list,
                       QString sgroup, bool fileNamesOnly)
{

    // Make sure the list is empty when we get started
    list->clear();

    if (sgroup.isEmpty())
        sgroup = "Videos";

    *list << "QUERY_SG_GETFILELIST";
    *list << host;
    *list << StorageGroup::GetGroupToUse(host, sgroup);
    *list << path;
    *list << QString::number(fileNamesOnly);

    bool ok = false;

    if (gCoreContext->IsMasterBackend())
    {
        // since the master backend cannot connect back around to
        // itself, and the libraries do not have access to the list
        // of connected slave backends to query an existing connection
        // start up a new temporary connection directly to the slave
        // backend to query the file list
        QString ann = QString("ANN Playback %1 0")
                        .arg(gCoreContext->GetHostName());
        QString addr = gCoreContext->GetBackendServerIP(host);
        int port = gCoreContext->GetBackendServerPort(host);
        bool mismatch = false;

        MythSocket *sock = gCoreContext->ConnectCommandSocket(
                                            addr, port, ann, &mismatch);
        if (sock)
        {
            ok = sock->SendReceiveStringList(*list);
            sock->DecrRef();
        }
        else
            list->clear();
    }
    else
        ok = gCoreContext->SendReceiveStringList(*list);

// Should the SLAVE UNREACH test be here ?
    return ok;
}
Пример #4
0
MythSocket *RemoteFile::openSocket(bool control)
{
    QUrl qurl(path);
    QString dir;

    QString host = qurl.host();
    int port = qurl.port();

    dir = qurl.path();

    if (qurl.hasQuery())
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
        dir += "?" + QUrl::fromPercentEncoding(
                   qurl.query(QUrl::FullyEncoded).toLocal8Bit());
#else
        dir += "?" + QUrl::fromPercentEncoding(qurl.encodedQuery());
#endif

    if (qurl.hasFragment())
        dir += "#" + qurl.fragment();

    QString sgroup = qurl.userName();

    MythSocket *lsock = new MythSocket();
    QString stype = (control) ? "control socket" : "file data socket";

    QString loc = QString("RemoteFile::openSocket(%1): ").arg(stype);

    if (port <= 0)
    {
        port = GetMythDB()->GetSettingOnHost("BackendServerPort", host).toInt();

        // if we still have no port use the default
        if (port <= 0)
            port = 6543;
    }

    if (!lsock->ConnectToHost(host, port))
    {
        LOG(VB_GENERAL, LOG_ERR, loc +
            QString("Could not connect to server %1:%2") .arg(host).arg(port));
        lsock->DecrRef();
        return NULL;
    }

    QString hostname = GetMythDB()->GetHostName();

    QStringList strlist;

#ifndef IGNORE_PROTO_VER_MISMATCH
    if (!gCoreContext->CheckProtoVersion(lsock))
    {
        LOG(VB_GENERAL, LOG_ERR, loc +
            QString("Failed validation to server %1:%2").arg(host).arg(port));
        lsock->DecrRef();
        return NULL;
    }
#endif

    if (control)
    {
        strlist.append(QString("ANN Playback %1 %2").arg(hostname).arg(false));
        if (!lsock->SendReceiveStringList(strlist))
        {
            LOG(VB_GENERAL, LOG_ERR, loc +
                QString("Could not read string list from server %1:%2")
                .arg(host).arg(port));
            lsock->DecrRef();
            return NULL;
        }
    }
    else
    {
        strlist.push_back(QString("ANN FileTransfer %1 %2 %3 %4")
                          .arg(hostname).arg(writemode)
                          .arg(usereadahead).arg(timeout_ms));
        strlist << QString("%1").arg(dir);
        strlist << sgroup;

        QStringList::const_iterator it = possibleauxfiles.begin();
        for (; it != possibleauxfiles.end(); ++it)
            strlist << *it;

        if (!lsock->SendReceiveStringList(strlist))
        {
            LOG(VB_GENERAL, LOG_ERR, loc +
                QString("Did not get proper response from %1:%2")
                .arg(host).arg(port));
            strlist.clear();
            strlist.push_back("ERROR");
            strlist.push_back("invalid response");
        }

        if (strlist.size() >= 3)
        {
            it = strlist.begin();
            ++it;
            recordernum = (*it).toInt();
            ++it;
            filesize = (*(it)).toLongLong();
            ++it;
            for (; it != strlist.end(); ++it)
                auxfiles << *it;
        }
        else if (0 < strlist.size() && strlist.size() < 3 &&
                 strlist[0] != "ERROR")
        {
            LOG(VB_GENERAL, LOG_ERR, loc +
                QString("Did not get proper response from %1:%2")
                .arg(host).arg(port));
            strlist.clear();
            strlist.push_back("ERROR");
            strlist.push_back("invalid response");
        }
    }

    if (strlist.empty() || strlist[0] == "ERROR")
    {
        lsock->DecrRef();
        lsock = NULL;
        if (strlist.empty())
        {
            LOG(VB_GENERAL, LOG_ERR, loc + "Failed to open socket, timeout");
        }
        else
        {
            LOG(VB_GENERAL, LOG_ERR, loc + "Failed to open socket" +
                ((strlist.size() >= 2) ?
                 QString(", error was %1").arg(strlist[1]) :
                 QString(", remote error")));
        }
    }

    return lsock;
}
Пример #5
0
int connect_to_master(void)
{
    MythSocket *tempMonitorConnection = new MythSocket();
    if (tempMonitorConnection->ConnectToHost(
            gCoreContext->GetMasterServerIP(),
            gCoreContext->GetMasterServerPort()))
    {
        if (!gCoreContext->CheckProtoVersion(tempMonitorConnection))
        {
            LOG(VB_GENERAL, LOG_ERR, "Master backend is incompatible with "
                    "this backend.\nCannot become a slave.");
            tempMonitorConnection->DecrRef();
            return GENERIC_EXIT_CONNECT_ERROR;
        }

        QStringList tempMonitorDone("DONE");

        QStringList tempMonitorAnnounce(QString("ANN Monitor %1 0")
                                            .arg(gCoreContext->GetHostName()));
        tempMonitorConnection->SendReceiveStringList(tempMonitorAnnounce);
        if (tempMonitorAnnounce.empty() ||
            tempMonitorAnnounce[0] == "ERROR")
        {
            tempMonitorConnection->DecrRef();
            tempMonitorConnection = NULL;
            if (tempMonitorAnnounce.empty())
            {
                LOG(VB_GENERAL, LOG_ERR, LOC +
                    "Failed to open event socket, timeout");
            }
            else
            {
                LOG(VB_GENERAL, LOG_ERR, LOC +
                    "Failed to open event socket" +
                    ((tempMonitorAnnounce.size() >= 2) ?
                    QString(", error was %1").arg(tempMonitorAnnounce[1]) :
                    QString(", remote error")));
            }
        }

        QStringList timeCheck;
        if (tempMonitorConnection)
        {
            timeCheck.push_back("QUERY_TIME_ZONE");
            tempMonitorConnection->SendReceiveStringList(timeCheck);
            tempMonitorConnection->WriteStringList(tempMonitorDone);
        }
        if (timeCheck.size() < 3)
        {
            if (tempMonitorConnection)
                tempMonitorConnection->DecrRef();
            return GENERIC_EXIT_SOCKET_ERROR;
        }

        QDateTime our_time = MythDate::current();
        QDateTime master_time = MythDate::fromString(timeCheck[2]);
        int timediff = abs(our_time.secsTo(master_time));

        if (timediff > 300)
        {
            LOG(VB_GENERAL, LOG_ERR,
                QString("Current time on the master backend differs by "
                        "%1 seconds from time on this system. Exiting.")
                .arg(timediff));
            if (tempMonitorConnection)
                tempMonitorConnection->DecrRef();
            return GENERIC_EXIT_INVALID_TIME;
        }

        if (timediff > 20)
        {
            LOG(VB_GENERAL, LOG_WARNING,
                    QString("Time difference between the master "
                            "backend and this system is %1 seconds.")
                .arg(timediff));
        }
    }
    if (tempMonitorConnection)
        tempMonitorConnection->DecrRef();

    return GENERIC_EXIT_OK;
}
Пример #6
0
MythSocket *MythCoreContext::ConnectCommandSocket(
    const QString &hostname, int port, const QString &announce,
    bool *p_proto_mismatch, bool gui, int maxConnTry, int setup_timeout)
{
    MythSocket *serverSock = NULL;

    {
        QMutexLocker locker(&d->m_WOLInProgressLock);
        d->WaitForWOL();
    }

    QString WOLcmd = GetSetting("WOLbackendCommand", "");

    if (maxConnTry < 1)
        maxConnTry = max(GetNumSetting("BackendConnectRetry", 1), 1);

    int WOLsleepTime = 0, WOLmaxConnTry = 0;
    if (!WOLcmd.isEmpty())
    {
        WOLsleepTime  = GetNumSetting("WOLbackendReconnectWaitTime", 0);
        WOLmaxConnTry = max(GetNumSetting("WOLbackendConnectRetry", 1), 1);
        maxConnTry    = max(maxConnTry, WOLmaxConnTry);
    }

    bool we_attempted_wol = false;

    if (setup_timeout <= 0)
        setup_timeout = MythSocket::kShortTimeout;

    bool proto_mismatch = false;
    for (int cnt = 1; cnt <= maxConnTry; cnt++)
    {
        LOG(VB_GENERAL, LOG_INFO, LOC +
            QString("Connecting to backend server: %1:%2 (try %3 of %4)")
                .arg(hostname).arg(port).arg(cnt).arg(maxConnTry));

        serverSock = new MythSocket();

        int sleepms = 0;
        if (serverSock->connect(hostname, port))
        {
            if (SetupCommandSocket(
                    serverSock, announce, setup_timeout, proto_mismatch))
            {
                break;
            }

            if (proto_mismatch)
            {
                if (p_proto_mismatch)
                    *p_proto_mismatch = true;

                serverSock->DecrRef();
                serverSock = NULL;
                break;
            }

            setup_timeout = (int)(setup_timeout * 1.5f);
        }
        else if (!WOLcmd.isEmpty() && (cnt < maxConnTry))
        {
            if (!we_attempted_wol)
            {
                QMutexLocker locker(&d->m_WOLInProgressLock);
                if (d->m_WOLInProgress)
                {
                    d->WaitForWOL();
                    continue;
                }

                d->m_WOLInProgress = we_attempted_wol = true;
            }

            myth_system(WOLcmd, kMSDontDisableDrawing | kMSDontBlockInputDevs |
                                kMSProcessEvents);
            sleepms = WOLsleepTime * 1000;
        }

        serverSock->DecrRef();
        serverSock = NULL;

        if (!serverSock && (cnt == 1))
        {
            QCoreApplication::postEvent(
                d->m_GUIcontext, new MythEvent("CONNECTION_FAILURE"));
        }

        if (sleepms)
            usleep(sleepms * 1000);
    }

    if (we_attempted_wol)
    {
        QMutexLocker locker(&d->m_WOLInProgressLock);
        d->m_WOLInProgress = false;
        d->m_WOLInProgressWaitCondition.wakeAll();
    }

    if (!serverSock && !proto_mismatch)
    {
        LOG(VB_GENERAL, LOG_ERR,
                "Connection to master server timed out.\n\t\t\t"
                "Either the server is down or the master server settings"
                "\n\t\t\t"
                "in mythtv-settings does not contain the proper IP address\n");
    }
    else
    {
        QCoreApplication::postEvent(
            d->m_GUIcontext, new MythEvent("CONNECTION_RESTABLISHED"));
    }

    return serverSock;
}