00001 using namespace std;
00002
00003
00004 #include <QMutex>
00005 #include <QReadWriteLock>
00006 #include <QReadLocker>
00007 #include <QWriteLocker>
00008 #include <QMutexLocker>
00009 #include <QWaitCondition>
00010 #include <QEvent>
00011 #include <QCoreApplication>
00012 #include <QNetworkProxy>
00013 #include <QRunnable>
00014
00015
00016 #include "mythsocketmanager.h"
00017 #include "socketrequesthandler.h"
00018 #include "sockethandler.h"
00019 #include "referencecounter.h"
00020 #include "mythcorecontext.h"
00021 #include "mythconfig.h"
00022 #include "mythversion.h"
00023 #include "mythlogging.h"
00024 #include "mthread.h"
00025 #include "serverpool.h"
00026
00027 #define LOC QString("MythSocketManager: ")
00028
00029 #define PRT_TIMEOUT 10
00030
00031 class ProcessRequestRunnable : public QRunnable
00032 {
00033 public:
00034 ProcessRequestRunnable(MythSocketManager &parent, MythSocket *sock) :
00035 m_parent(parent), m_sock(sock)
00036 {
00037 m_sock->UpRef();
00038 }
00039
00040 virtual void run(void)
00041 {
00042 m_parent.ProcessRequest(m_sock);
00043 m_sock->DownRef();
00044 }
00045
00046 MythSocketManager &m_parent;
00047 MythSocket *m_sock;
00048 };
00049
00050 MythServer::MythServer(QObject *parent) : ServerPool(parent)
00051 {
00052 }
00053
00054 void MythServer::newTcpConnection(int socket)
00055 {
00056 MythSocket *s = new MythSocket(socket);
00057 emit newConnection(s);
00058 }
00059
00060 MythSocketManager::MythSocketManager() :
00061 m_server(NULL), m_threadPool("MythSocketManager")
00062 {
00063 }
00064
00065 MythSocketManager::~MythSocketManager()
00066 {
00067 m_threadPool.Stop();
00068
00069 QWriteLocker wlock(&m_handlerLock);
00070
00071 QMap<QString, SocketRequestHandler*>::iterator i;
00072 for (i = m_handlerMap.begin(); i != m_handlerMap.end(); ++i)
00073 delete *i;
00074
00075 m_handlerMap.clear();
00076 }
00077
00078 bool MythSocketManager::Listen(int port)
00079 {
00080 if (m_server != NULL)
00081 {
00082 m_server->close();
00083 delete m_server;
00084 m_server = NULL;
00085 }
00086
00087 m_server = new MythServer(this);
00088 m_server->setProxy(QNetworkProxy::NoProxy);
00089 if (!m_server->listen(port))
00090 {
00091 LOG(VB_GENERAL, LOG_ERR, QString("Failed to bind port %1.").arg(port));
00092 return false;
00093 }
00094
00095 connect(m_server, SIGNAL(newConnection(MythSocket *)),
00096 this, SLOT(newConnection(MythSocket *)));
00097 return true;
00098 }
00099
00100 void MythSocketManager::RegisterHandler(SocketRequestHandler *handler)
00101 {
00102 QWriteLocker wlock(&m_handlerLock);
00103
00104 QString name = handler->GetHandlerName();
00105 if (m_handlerMap.contains(name))
00106 {
00107 LOG(VB_GENERAL, LOG_WARNING, LOC + name +
00108 " has already been registered.");
00109 delete handler;
00110 }
00111 else
00112 {
00113 LOG(VB_GENERAL, LOG_INFO, LOC +
00114 "Registering socket command handler " + name);
00115 handler->SetParent(this);
00116 m_handlerMap.insert(name, handler);
00117 }
00118 }
00119
00120 void MythSocketManager::AddSocketHandler(SocketHandler *sock)
00121 {
00122 QWriteLocker wlock(&m_socketLock);
00123 if (m_socketMap.contains(sock->GetSocket()))
00124 return;
00125
00126 sock->UpRef();
00127 m_socketMap.insert(sock->GetSocket(), sock);
00128 }
00129
00130 SocketHandler *MythSocketManager::GetConnectionBySocket(MythSocket *sock)
00131 {
00132 QReadLocker rlock(&m_socketLock);
00133 if (!m_socketMap.contains(sock))
00134 return NULL;
00135
00136 SocketHandler *handler = m_socketMap[sock];
00137 handler->UpRef();
00138 return handler;
00139 }
00140
00141 void MythSocketManager::readyRead(MythSocket *sock)
00142 {
00143 if (sock->isExpectingReply())
00144 {
00145 LOG(VB_SOCKET, LOG_DEBUG, "Socket marked as expecting reply.");
00146 return;
00147 }
00148
00149 m_threadPool.startReserved(
00150 new ProcessRequestRunnable(*this, sock),
00151 "ServiceRequest", PRT_TIMEOUT);
00152 }
00153
00154 void MythSocketManager::connectionClosed(MythSocket *sock)
00155 {
00156 {
00157 QReadLocker rlock(&m_handlerLock);
00158
00159 QMap<QString, SocketRequestHandler*>::const_iterator i;
00160 for (i = m_handlerMap.constBegin(); i != m_handlerMap.constEnd(); ++i)
00161 (*i)->connectionClosed(sock);
00162 }
00163
00164 {
00165 QWriteLocker wlock(&m_socketLock);
00166 if (m_socketMap.contains(sock))
00167 {
00168 SocketHandler *handler = m_socketMap.take(sock);
00169 handler->DownRef();
00170 }
00171 }
00172 }
00173
00174 void MythSocketManager::ProcessRequest(MythSocket *sock)
00175 {
00176
00177
00178
00179 if (sock->isExpectingReply())
00180 return;
00181
00182 sock->Lock();
00183
00184 if (sock->bytesAvailable() > 0)
00185 {
00186 ProcessRequestWork(sock);
00187 }
00188
00189 sock->Unlock();
00190 }
00191
00192 void MythSocketManager::ProcessRequestWork(MythSocket *sock)
00193 {
00194 QStringList listline;
00195 if (!sock->readStringList(listline))
00196 return;
00197
00198 QString line = listline[0].simplified();
00199 QStringList tokens = line.split(' ', QString::SkipEmptyParts);
00200 QString command = tokens[0];
00201
00202 bool handled = false;
00203
00204
00205 if (command == "DONE")
00206 {
00207 HandleDone(sock);
00208 return;
00209 }
00210
00211 if (!sock->isValidated())
00212 {
00213
00214
00215 if (command == "MYTH_PROTO_VERSION")
00216 {
00217 HandleVersion(sock, tokens);
00218 }
00219 else
00220 {
00221 LOG(VB_SOCKET, LOG_ERR, LOC +
00222 "Use of socket attempted before protocol validation.");
00223 listline.clear();
00224 listline << "ERROR" << "socket has not been validated";
00225 sock->writeStringList(listline);
00226 }
00227 return;
00228 }
00229
00230 if (!sock->isAnnounced())
00231 {
00232
00233
00234 if (command == "ANN")
00235 {
00236 QReadLocker rlock(&m_handlerLock);
00237
00238 QMap<QString, SocketRequestHandler*>::const_iterator i
00239 = m_handlerMap.constBegin();
00240 while (!handled && (i != m_handlerMap.constEnd()))
00241 {
00242 LOG(VB_SOCKET, LOG_DEBUG, LOC +
00243 QString("Attempting to handle annouce with: %1")
00244 .arg((*i)->GetHandlerName()));
00245 handled = (*i)->HandleAnnounce(sock, tokens, listline);
00246 ++i;
00247 }
00248
00249 if (handled)
00250 {
00251 --i;
00252 LOG(VB_SOCKET, LOG_DEBUG, LOC +
00253 QString("Socket announce handled by: %1")
00254 .arg((*i)->GetHandlerName()));
00255 for (i = m_handlerMap.constBegin();
00256 i != m_handlerMap.constEnd(); ++i)
00257 (*i)->connectionAnnounced(sock, tokens, listline);
00258 }
00259 else
00260 {
00261 LOG(VB_SOCKET, LOG_ERR, LOC + "Socket announce unhandled.");
00262 listline.clear();
00263 listline << "ERROR" << "unhandled announce";
00264 sock->writeStringList(listline);
00265 }
00266
00267 return;
00268 }
00269 else
00270 {
00271 LOG(VB_SOCKET, LOG_ERR, LOC +
00272 "Use of socket attempted before announcement.");
00273 listline.clear();
00274 listline << "ERROR" << "socket has not been announced";
00275 sock->writeStringList(listline);
00276 }
00277 return;
00278 }
00279
00280 if (command == "ANN")
00281 {
00282 LOG(VB_SOCKET, LOG_ERR, LOC + "ANN sent out of sequence.");
00283 listline.clear();
00284 listline << "ERROR" << "socket has already been announced";
00285 sock->writeStringList(listline);
00286 return;
00287 }
00288
00289 {
00290
00291 QReadLocker rlock(&m_handlerLock);
00292 QReadLocker slock(&m_socketLock);
00293
00294 if (!m_socketMap.contains(sock))
00295 {
00296 LOG(VB_SOCKET, LOG_ERR, LOC + "No handler found for socket.");
00297 listline.clear();
00298 listline << "ERROR" << "socket handler cannot be found";
00299 sock->writeStringList(listline);
00300 return;
00301 }
00302
00303 SocketHandler *handler = GetConnectionBySocket(sock);
00304 ReferenceLocker hlock(handler, false);
00305
00306 QMap<QString, SocketRequestHandler*>::const_iterator i
00307 = m_handlerMap.constBegin();
00308 while (!handled && (i != m_handlerMap.constEnd()))
00309 {
00310 handled = (*i)->HandleQuery(handler, tokens, listline);
00311 ++i;
00312 }
00313
00314 if (handled)
00315 LOG(VB_SOCKET, LOG_DEBUG, LOC + QString("Query handled by: %1")
00316 .arg((*--i)->GetHandlerName()));
00317 }
00318
00319 if (!handled)
00320 {
00321 if (command == "BACKEND_MESSAGE")
00322
00323
00324 return;
00325
00326 listline.clear();
00327 listline << "ERROR" << "unknown command";
00328 sock->writeStringList(listline);
00329 }
00330 }
00331
00332 void MythSocketManager::HandleVersion(MythSocket *socket,
00333 const QStringList slist)
00334 {
00335 QStringList retlist;
00336 QString version = slist[1];
00337 if (version != MYTH_PROTO_VERSION)
00338 {
00339 LOG(VB_GENERAL, LOG_ERR, LOC +
00340 "Client speaks protocol version " + version +
00341 " but we speak " + MYTH_PROTO_VERSION + '!');
00342 retlist << "REJECT" << MYTH_PROTO_VERSION;
00343 socket->writeStringList(retlist);
00344 HandleDone(socket);
00345 return;
00346 }
00347
00348 if (slist.size() < 3)
00349 {
00350 LOG(VB_GENERAL, LOG_ERR, LOC + "Client did not pass protocol "
00351 "token. Refusing connection!");
00352 retlist << "REJECT" << MYTH_PROTO_VERSION;
00353 socket->writeStringList(retlist);
00354 HandleDone(socket);
00355 return;
00356 }
00357
00358 QString token = slist[2];
00359 if (token != MYTH_PROTO_TOKEN)
00360 {
00361 LOG(VB_GENERAL, LOG_ERR, LOC + "Client sent incorrect protocol token "
00362 "for protocol version. Refusing connection!");
00363 retlist << "REJECT" << MYTH_PROTO_VERSION;
00364 socket->writeStringList(retlist);
00365 HandleDone(socket);
00366 return;
00367 }
00368
00369 LOG(VB_SOCKET, LOG_DEBUG, LOC + "Client validated");
00370 retlist << "ACCEPT" << MYTH_PROTO_VERSION;
00371 socket->writeStringList(retlist);
00372 socket->setValidated();
00373 }
00374
00375 void MythSocketManager::HandleDone(MythSocket *sock)
00376 {
00377 sock->close();
00378 }
00379