Ticket #5831: multinetworkcontrol.diff
File multinetworkcontrol.diff, 12.3 KB (added by , 15 years ago) |
---|
-
networkcontrol.h
10 10 #include <QTcpServer> 11 11 #include <QTcpSocket> 12 12 #include <QMutex> 13 #include <QEvent> 13 14 14 15 class MainServer; 15 16 class QTextStream; 16 17 18 const int kNetworkControlCloseEvent = 35672; 19 20 class 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 43 class 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 72 class 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 17 88 class NetworkControl : public QTcpServer 18 89 { 19 90 Q_OBJECT … … 25 96 26 97 private slots: 27 98 void newConnection(); 28 void re adClient();99 void receiveCommand(QString&); 29 100 30 101 protected: 31 102 static void *SocketThread(void *param); … … 48 119 QString listSchedule(const QString& chanID = "") const; 49 120 QString saveScreenshot(QStringList tokens); 50 121 51 void processNetworkControlCommand( QString command);122 void processNetworkControlCommand(NetworkCommand *nc); 52 123 53 124 54 125 QString prompt; … … 58 129 QMap <QString, int> keyMap; 59 130 60 131 QMutex clientLock; 61 QTcpSocket *client; 62 QTextStream *cs; 132 QList<NetworkControlClient*> clients; 63 133 64 deque<QString> networkControlCommands;134 QList<NetworkCommand*> networkControlCommands; 65 135 QMutex ncLock; 66 136 QWaitCondition ncCond; 67 137 68 deque<QString> networkControlReplies;138 QList<NetworkCommand*> networkControlReplies; 69 139 QMutex nrLock; 70 140 71 141 pthread_t command_thread; -
networkcontrol.cpp
25 25 #define LOC_ERR QString("NetworkControl Error: ") 26 26 27 27 const int kNetworkControlDataReadyEvent = 35671; 28 const int kNetworkControlCloseEvent = 35672;29 28 29 30 30 31 /** Is @p test an abbreviation of @p command ? 31 32 * The @p test substring must be at least @p minchars long. 32 33 * @param command the full command name … … 46 47 NetworkControl::NetworkControl() 47 48 : QTcpServer(), 48 49 prompt("# "), 49 gotAnswer(false), answer(""), 50 client(NULL), cs(NULL) 50 gotAnswer(false), answer("") 51 51 { 52 52 // Eventually this map should be in the jumppoints table 53 53 jumpMap["channelpriorities"] = "Channel Recording Priorities"; … … 198 198 NetworkControl::~NetworkControl(void) 199 199 { 200 200 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...")); 203 203 nrLock.unlock(); 204 204 205 205 notifyDataAvailable(); … … 232 232 233 233 void NetworkControl::RunCommandThread(void) 234 234 { 235 QString command;235 NetworkCommand *nc; 236 236 237 237 while (!stopCommandThread) 238 238 { … … 245 245 return; 246 246 } 247 247 } 248 command= networkControlCommands.front();248 nc = networkControlCommands.front(); 249 249 networkControlCommands.pop_front(); 250 250 ncLock.unlock(); 251 251 252 processNetworkControlCommand( command);252 processNetworkControlCommand(nc); 253 253 } 254 254 } 255 255 256 void NetworkControl::processNetworkControlCommand( QString command)256 void NetworkControl::processNetworkControlCommand(NetworkCommand *nc) 257 257 { 258 258 QMutexLocker locker(&clientLock); 259 259 QString result = ""; 260 QStringList tokens = command.simplified().split(" ");260 QStringList tokens = nc->getCommand().simplified().split(" "); 261 261 262 262 if (is_abbrev("jump", tokens[0])) 263 263 result = processJump(tokens); … … 270 270 else if (is_abbrev("help", tokens[0])) 271 271 result = processHelp(tokens); 272 272 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())); 275 275 else if (! tokens[0].isEmpty()) 276 276 result = QString("INVALID command '%1', try 'help' for more info") 277 277 .arg(tokens[0]); … … 279 279 if (result != "") 280 280 { 281 281 nrLock.lock(); 282 networkControlReplies.push_back( result);282 networkControlReplies.push_back(new NetworkCommand(nc->getClient(),result)); 283 283 nrLock.unlock(); 284 284 285 285 notifyDataAvailable(); … … 289 289 void NetworkControl::newConnection() 290 290 { 291 291 QString welcomeStr = ""; 292 bool closedOldConn = false;293 292 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&))); 295 296 connect(s, SIGNAL(disconnected()), s, SLOT(deleteLater())); 296 297 297 298 VERBOSE(VB_GENERAL, LOC + 298 299 QString("New connection established.")); 299 300 300 301 QMutexLocker locker(&clientLock); 301 if (cs)302 {303 cs->setDevice(s);304 }305 else306 {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 326 302 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 335 303 welcomeStr += "Type 'help' for usage information\r\n" 336 304 "---------------------------------"; 337 305 nrLock.lock(); 338 networkControlReplies.push_back( welcomeStr);306 networkControlReplies.push_back(new NetworkCommand(ncc,welcomeStr)); 339 307 nrLock.unlock(); 340 308 341 309 notifyDataAvailable(); 342 310 } 343 311 344 void NetworkControl::readClient(void)312 NetworkControlClient::NetworkControlClient(QTcpSocket *s) 345 313 { 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 320 NetworkControlClient::~NetworkControlClient() 321 { 322 m_socket->close(); 323 delete m_socket; 324 delete m_textStream; 325 } 326 327 void NetworkControlClient::readClient(void) 328 { 346 329 QTcpSocket *socket = (QTcpSocket *)sender(); 347 330 if (!socket) 348 331 return; … … 360 343 continue; 361 344 362 345 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); 368 350 } 369 351 } 370 352 353 void 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 371 367 QString NetworkControl::processJump(QStringList tokens) 372 368 { 373 369 QString result = "OK"; … … 872 868 for (int i = 3; i < tokens.size(); i++) 873 869 response += QString(" ") + tokens[i]; 874 870 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)); 876 874 nrLock.unlock(); 877 875 878 876 notifyDataAvailable(); … … 880 878 } 881 879 else if (e->type() == kNetworkControlDataReadyEvent) 882 880 { 881 NetworkCommand *nc; 883 882 QString reply; 884 883 int replies; 885 884 QRegExp crlfRegEx("\r\n$"); … … 887 886 888 887 nrLock.lock(); 889 888 replies = networkControlReplies.size(); 890 while (client && cs && replies > 0 && 891 client->state() == QTcpSocket::ConnectedState) 889 while (replies > 0 ) 892 890 { 893 reply= networkControlReplies.front();891 nc = networkControlReplies.front(); 894 892 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();900 893 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; 901 934 replies = networkControlReplies.size(); 902 935 } 903 936 nrLock.unlock(); 904 937 } 905 938 else if (e->type() == kNetworkControlCloseEvent) 906 939 { 907 if (client && client->state() == QTcpSocket::ConnectedState) 940 NetworkControlCloseEvent *ncce = (NetworkControlCloseEvent*)e; 941 NetworkControlClient *client = ncce->getClient(); 942 if (client) 908 943 { 909 944 clientLock.lock(); 910 client->close(); 945 int index = clients.indexOf(client); 946 clients.removeAt(index); 911 947 delete client; 912 delete cs;913 client = NULL;914 cs = NULL;915 948 clientLock.unlock(); 916 949 } 917 950 }