Ticket #5831: multinetworkcontrol.diff

File multinetworkcontrol.diff, 12.3 KB (added by Xavier Hervy <xavier.hervy@…>, 11 years ago)

update for trunk r19172

  • networkcontrol.h

     
    1010#include <QTcpServer>
    1111#include <QTcpSocket>
    1212#include <QMutex>
     13#include <QEvent>
    1314
    1415class MainServer;
    1516class QTextStream;
    1617
     18const int kNetworkControlCloseEvent     = 35672;
     19
     20class NetworkControlClient : public QObject
     21{
     22    Q_OBJECT
     23  public:
     24    NetworkControlClient(QTcpSocket *);
     25    ~NetworkControlClient();
     26    QTcpSocket * getSocket()
     27    {
     28        return m_socket;
     29    };
     30    QTextStream * getTextStream()
     31    {
     32        return m_textStream;
     33    };
     34  signals:
     35        void commandReceived(QString&);
     36  public slots:
     37        void readClient();
     38  private:
     39        QTcpSocket * m_socket;
     40        QTextStream *m_textStream;
     41};
     42
     43class NetworkCommand : public QObject
     44{
     45    Q_OBJECT
     46  public:
     47    NetworkCommand(NetworkControlClient * cli, QString c)
     48    {
     49        m_command = c;
     50        m_client = cli;
     51    }
     52   
     53    NetworkCommand &operator=(NetworkCommand const &nc)
     54    {
     55        m_command = nc.m_command;
     56        m_client = nc.m_client;
     57        return *this;
     58    }
     59    QString getCommand()
     60    {
     61        return m_command;
     62    }
     63    NetworkControlClient * getClient()
     64    {
     65        return m_client;
     66    }
     67  private:
     68    QString m_command;
     69    NetworkControlClient * m_client;
     70};
     71
     72class NetworkControlCloseEvent : public QEvent
     73{
     74  public:
     75    NetworkControlCloseEvent(NetworkControlClient * ncc)
     76        :QEvent((QEvent::Type)kNetworkControlCloseEvent)
     77        ,m_networkControlClient(ncc){};
     78    NetworkControlClient * getClient()
     79    {
     80        return m_networkControlClient;
     81    };
     82    private:
     83        NetworkControlClient * m_networkControlClient;
     84   
     85};
     86
     87
    1788class NetworkControl : public QTcpServer
    1889{
    1990    Q_OBJECT
     
    2596
    2697  private slots:
    2798    void newConnection();
    28     void readClient();
     99    void receiveCommand(QString&);
    29100
    30101  protected:
    31102    static void *SocketThread(void *param);
     
    48119    QString listSchedule(const QString& chanID = "") const;
    49120    QString saveScreenshot(QStringList tokens);
    50121
    51     void processNetworkControlCommand(QString command);
     122    void processNetworkControlCommand(NetworkCommand *nc);
    52123
    53124
    54125    QString prompt;
     
    58129    QMap <QString, int> keyMap;
    59130
    60131    QMutex clientLock;
    61     QTcpSocket *client;
    62     QTextStream *cs;
     132    QList<NetworkControlClient*> clients;
    63133
    64     deque<QString> networkControlCommands;
     134    QList<NetworkCommand*> networkControlCommands;
    65135    QMutex ncLock;
    66136    QWaitCondition ncCond;
    67137
    68     deque<QString> networkControlReplies;
     138    QList<NetworkCommand*> networkControlReplies;
    69139    QMutex nrLock;
    70140
    71141    pthread_t command_thread;
  • networkcontrol.cpp

     
    2525#define LOC_ERR QString("NetworkControl Error: ")
    2626
    2727const int kNetworkControlDataReadyEvent = 35671;
    28 const int kNetworkControlCloseEvent     = 35672;
    2928
     29
     30
    3031/** Is @p test an abbreviation of @p command ?
    3132 * The @p test substring must be at least @p minchars long.
    3233 * @param command the full command name
     
    4647NetworkControl::NetworkControl()
    4748          : QTcpServer(),
    4849            prompt("# "),
    49             gotAnswer(false), answer(""),
    50             client(NULL), cs(NULL)
     50            gotAnswer(false), answer("")
    5151{
    5252    // Eventually this map should be in the jumppoints table
    5353    jumpMap["channelpriorities"]     = "Channel Recording Priorities";
     
    198198NetworkControl::~NetworkControl(void)
    199199{
    200200    nrLock.lock();
    201     networkControlReplies.push_back(
    202         "mythfrontend shutting down, connection closing...");
     201    networkControlReplies.push_back(new NetworkCommand(NULL,
     202        "mythfrontend shutting down, connection closing..."));
    203203    nrLock.unlock();
    204204
    205205    notifyDataAvailable();
     
    232232
    233233void NetworkControl::RunCommandThread(void)
    234234{
    235     QString command;
     235    NetworkCommand *nc;
    236236
    237237    while (!stopCommandThread)
    238238    {
     
    245245                return;
    246246            }
    247247        }
    248         command = networkControlCommands.front();
     248        nc = networkControlCommands.front();
    249249        networkControlCommands.pop_front();
    250250        ncLock.unlock();
    251251
    252         processNetworkControlCommand(command);
     252        processNetworkControlCommand(nc);
    253253    }
    254254}
    255255
    256 void NetworkControl::processNetworkControlCommand(QString command)
     256void NetworkControl::processNetworkControlCommand(NetworkCommand *nc)
    257257{
    258258    QMutexLocker locker(&clientLock);
    259259    QString result = "";
    260     QStringList tokens = command.simplified().split(" ");
     260    QStringList tokens = nc->getCommand().simplified().split(" ");
    261261
    262262    if (is_abbrev("jump", tokens[0]))
    263263        result = processJump(tokens);
     
    270270    else if (is_abbrev("help", tokens[0]))
    271271        result = processHelp(tokens);
    272272    else if ((tokens[0].toLower() == "exit") || (tokens[0].toLower() == "quit"))
    273         QApplication::postEvent(this,
    274                                 new QEvent((QEvent::Type)kNetworkControlCloseEvent));
     273        QApplication::postEvent(this, 
     274                                new NetworkControlCloseEvent (nc->getClient()));
    275275    else if (! tokens[0].isEmpty())
    276276        result = QString("INVALID command '%1', try 'help' for more info")
    277277                         .arg(tokens[0]);
     
    279279    if (result != "")
    280280    {
    281281        nrLock.lock();
    282         networkControlReplies.push_back(result);
     282        networkControlReplies.push_back(new NetworkCommand(nc->getClient(),result));
    283283        nrLock.unlock();
    284284
    285285        notifyDataAvailable();
     
    289289void NetworkControl::newConnection()
    290290{
    291291    QString welcomeStr = "";
    292     bool closedOldConn = false;
    293292    QTcpSocket *s = this->nextPendingConnection();
    294     connect(s, SIGNAL(readyRead()), this, SLOT(readClient()));
     293    NetworkControlClient * ncc = new NetworkControlClient(s);
     294    connect(ncc, SIGNAL(commandReceived(QString&)), this,
     295            SLOT(receiveCommand(QString&)));
    295296    connect(s, SIGNAL(disconnected()), s, SLOT(deleteLater()));
    296297
    297298    VERBOSE(VB_GENERAL, LOC +
    298299            QString("New connection established."));
    299300
    300301    QMutexLocker locker(&clientLock);
    301     if (cs)
    302     {
    303         cs->setDevice(s);
    304     }
    305     else
    306     {
    307         cs = new QTextStream(s);
    308         cs->setCodec("UTF-8");
    309     }
    310    
    311     if (client)
    312     {
    313         closedOldConn = true;
    314         client->close();
    315     }
    316     client = s;
    317 
    318     ncLock.lock();
    319     networkControlCommands.clear();
    320     ncLock.unlock();
    321 
    322     nrLock.lock();
    323     networkControlReplies.clear();
    324     nrLock.unlock();
    325 
    326302    welcomeStr = "MythFrontend Network Control\r\n";
    327     if (closedOldConn)
    328     {
    329         welcomeStr +=
    330             "WARNING: mythfrontend was already under network control.\r\n";
    331         welcomeStr +=
    332             "         Previous session is being disconnected.\r\n";
    333     }
    334 
    335303    welcomeStr += "Type 'help' for usage information\r\n"
    336304                  "---------------------------------";
    337305    nrLock.lock();
    338     networkControlReplies.push_back(welcomeStr);
     306    networkControlReplies.push_back(new NetworkCommand(ncc,welcomeStr));
    339307    nrLock.unlock();
    340308
    341309    notifyDataAvailable();
    342310}
    343311
    344 void NetworkControl::readClient(void)
     312NetworkControlClient::NetworkControlClient(QTcpSocket *s)
    345313{
     314    m_socket = s;
     315    m_textStream = new QTextStream(s);
     316    m_textStream->setCodec("UTF-8");
     317    connect(m_socket, SIGNAL(readyRead()), this, SLOT(readClient()));
     318}
     319
     320NetworkControlClient::~NetworkControlClient()
     321{
     322    m_socket->close();
     323    delete m_socket;
     324    delete m_textStream;
     325}
     326
     327void NetworkControlClient::readClient(void)
     328{
    346329    QTcpSocket *socket = (QTcpSocket *)sender();
    347330    if (!socket)
    348331        return;
     
    360343            continue;
    361344
    362345        tokens = lineIn.simplified().split(" ");
    363 
    364         ncLock.lock();
    365         networkControlCommands.push_back(lineIn);
    366         ncCond.wakeOne();
    367         ncLock.unlock();
     346       
     347        VERBOSE(VB_IMPORTANT, LOC +
     348            QString("emit commandReceived(%1)").arg(lineIn));
     349        emit commandReceived(lineIn);
    368350    }
    369351}
    370352
     353void NetworkControl::receiveCommand(QString &command)
     354{
     355    VERBOSE(VB_IMPORTANT, LOC +
     356            QString("NetworkControl::receiveCommand(%1)").arg(command));
     357    NetworkControlClient *ncc = (NetworkControlClient *)sender();
     358    if (!ncc)
     359         return;
     360 
     361    ncLock.lock();
     362    networkControlCommands.push_back(new NetworkCommand(ncc,command));
     363    ncCond.wakeOne();
     364    ncLock.unlock();
     365}
     366
    371367QString NetworkControl::processJump(QStringList tokens)
    372368{
    373369    QString result = "OK";
     
    872868            for (int i = 3; i < tokens.size(); i++)
    873869                response += QString(" ") + tokens[i];
    874870            nrLock.lock();
    875             networkControlReplies.push_back(response);
     871            //networkControlReplies.push_back(response);
     872            //FIXME What is response for ? send to which client ?
     873            networkControlReplies.push_back(new NetworkCommand(NULL,response));
    876874            nrLock.unlock();
    877875
    878876            notifyDataAvailable();
     
    880878    }
    881879    else if (e->type() == kNetworkControlDataReadyEvent)
    882880    {
     881        NetworkCommand *nc;
    883882        QString reply;
    884883        int replies;
    885884        QRegExp crlfRegEx("\r\n$");
     
    887886
    888887        nrLock.lock();
    889888        replies = networkControlReplies.size();
    890         while (client && cs && replies > 0 &&
    891                client->state() == QTcpSocket::ConnectedState)
     889        while (replies > 0 )
    892890        {
    893             reply = networkControlReplies.front();
     891            nc = networkControlReplies.front();
    894892            networkControlReplies.pop_front();
    895             *cs << reply;
    896             if (!reply.contains(crlfRegEx) || reply.contains(crlfcrlfRegEx))
    897                 *cs << "\r\n" << prompt;
    898             cs->flush();
    899             client->flush();
    900893
     894            NetworkControlClient * ncc = nc->getClient();
     895            if (ncc)
     896            {
     897                QTcpSocket *client = ncc->getSocket();
     898                QTextStream *cs = ncc->getTextStream();
     899                reply = nc->getCommand();
     900                if (client && cs && client->state() == QTcpSocket::ConnectedState)
     901                {
     902                    *cs << reply;
     903                    if (!reply.contains(crlfRegEx) || reply.contains(crlfcrlfRegEx))
     904                        *cs << "\r\n" << prompt;
     905                    cs->flush();
     906                    client->flush();
     907                }
     908            }
     909            else //send to all clients
     910            {
     911                reply = nc->getCommand();
     912                if (!reply.contains(crlfRegEx) || reply.contains(crlfcrlfRegEx))
     913                        reply = QString("%1\r\n%2").arg(reply).arg(prompt);
     914                QList<NetworkControlClient *>::const_iterator it;
     915                for (it = clients.begin(); it != clients.end(); ++it)
     916                {
     917                    NetworkControlClient *ncc = *it;
     918                    if (ncc)
     919                    {
     920                        QTcpSocket *client = ncc->getSocket();
     921                        QTextStream *cs = ncc->getTextStream();
     922                        if (client && cs && client->state() == QTcpSocket::ConnectedState)
     923                        {
     924                            *cs << reply;
     925                            if (!reply.contains(crlfRegEx) || reply.contains(crlfcrlfRegEx))
     926                                *cs << "\r\n" << prompt;
     927                            cs->flush();
     928                            client->flush();
     929                        }
     930                    }
     931                }
     932            }
     933            delete nc;
    901934            replies = networkControlReplies.size();
    902935        }
    903936        nrLock.unlock();
    904937    }
    905938    else if (e->type() == kNetworkControlCloseEvent)
    906939    {
    907         if (client && client->state() == QTcpSocket::ConnectedState)
     940        NetworkControlCloseEvent *ncce = (NetworkControlCloseEvent*)e;
     941        NetworkControlClient *client = ncce->getClient();
     942        if (client)
    908943        {
    909944            clientLock.lock();
    910             client->close();
     945            int index = clients.indexOf(client);
     946            clients.removeAt(index);
    911947            delete client;
    912             delete cs;
    913             client = NULL;
    914             cs = NULL;
    915948            clientLock.unlock();
    916949        }
    917950    }