Convert sysadm-server to run either in TCP or WebSocket mode.

New CLI flags:
"-ws": Use the websocket protocols instead of tcp
"-p <port number>": Use the designated port number for the server.
This commit is contained in:
Ken Moore
2015-12-29 12:43:29 -05:00
parent 0c943636bd
commit 9fe2914da3
5 changed files with 150 additions and 63 deletions

View File

@@ -13,30 +13,22 @@
#define DEBUG 0
#define PORTNUMBER 12142
#define APPCAFEWORKING QString("/var/tmp/appcafe/dispatch-queue.working")
//=======================
// PUBLIC
//=======================
WebServer::WebServer() : QWebSocketServer("sysadm-server", QWebSocketServer::NonSecureMode){
WebServer::WebServer(){
//Setup all the various settings
//Any SSL changes
/*QSslConfiguration ssl = this->sslConfiguration();
ssl.setProtocol(QSsl::SecureProtocols);
this->setSslConfiguration(ssl);*/
WSServer = 0;
TCPServer = 0;
AUTH = new AuthorizationManager();
watcher = new QFileSystemWatcher(this);
//Setup Connections
connect(this, SIGNAL(closed()), this, SLOT(ServerClosed()) );
connect(this, SIGNAL(serverError(QWebSocketProtocol::CloseCode)), this, SLOT(ServerError(QWebSocketProtocol::CloseCode)) );
connect(this, SIGNAL(newConnection()), this, SLOT(NewSocketConnection()) );
connect(this, SIGNAL(acceptError(QAbstractSocket::SocketError)), this, SLOT(NewConnectError(QAbstractSocket::SocketError)) );
connect(this, SIGNAL(originAuthenticationRequired(QWebSocketCorsAuthenticator*)), this, SLOT(OriginAuthRequired(QWebSocketCorsAuthenticator*)) );
connect(this, SIGNAL(peerVerifyError(const QSslError&)), this, SLOT(PeerVerifyError(const QSslError&)) );
connect(this, SIGNAL(sslErrors(const QList<QSslError>&)), this, SLOT(SslErrors(const QList<QSslError>&)) );
connect(watcher, SIGNAL(fileChanged(const QString&)), this, SLOT(WatcherUpdate(QString)) );
connect(watcher, SIGNAL(directoryChanged(const QString&)), this, SLOT(WatcherUpdate(QString)) );
}
@@ -45,28 +37,60 @@ WebServer::~WebServer(){
delete AUTH;
}
bool WebServer::startServer(){
bool ok = this->listen(QHostAddress::Any, PORTNUMBER);
bool WebServer::startServer(quint16 port, bool websocket){
bool ok = false;
if(websocket){ ok = setupWebSocket(port); }
else{ ok = setupTcp(port); }
if(ok){
QCoreApplication::processEvents();
qDebug() << "Server Started:" << QDateTime::currentDateTime().toString(Qt::ISODate);
qDebug() << " Name:" << this->serverName() << "Port:" << this->serverPort();
qDebug() << " URL:" << this->serverUrl().toString() << "Remote Address:" << this->serverAddress().toString();
qDebug() << " Port:" << port;
if(WSServer!=0){ qDebug() << " URL:" << WSServer->serverUrl().toString(); }
if(!QFile::exists(APPCAFEWORKING)){ QProcess::execute("touch "+APPCAFEWORKING); }
qDebug() << " Dispatcher Events:" << APPCAFEWORKING;
watcher->addPath(APPCAFEWORKING);
WatcherUpdate(APPCAFEWORKING); //load it initially
}else{ qCritical() << "Could not start server - exiting..."; }
}else{
qCritical() << "Could not start server - exiting...";
}
return ok;
}
void WebServer::stopServer(){
this->close();
if(WSServer!=0){ WSServer->close(); } //note - this will throw the "closed()" signal when done
else if(TCPServer!=0){ TCPServer->close(); QCoreApplication::exit(0);} //no corresponding signal
}
//===================
// PRIVATE
//===================
bool WebServer::setupWebSocket(quint16 port){
WSServer = new QWebSocketServer("sysadm-server", QWebSocketServer::NonSecureMode, this);
//Setup Connections
connect(WSServer, SIGNAL(newConnection()), this, SLOT(NewSocketConnection()) );
connect(WSServer, SIGNAL(acceptError(QAbstractSocket::SocketError)), this, SLOT(NewConnectError(QAbstractSocket::SocketError)) );
// -- websocket specific signals
connect(WSServer, SIGNAL(closed()), this, SLOT(ServerClosed()) );
connect(WSServer, SIGNAL(serverError(QWebSocketProtocol::CloseCode)), this, SLOT(ServerError(QWebSocketProtocol::CloseCode)) );
connect(WSServer, SIGNAL(originAuthenticationRequired(QWebSocketCorsAuthenticator*)), this, SLOT(OriginAuthRequired(QWebSocketCorsAuthenticator*)) );
connect(WSServer, SIGNAL(peerVerifyError(const QSslError&)), this, SLOT(PeerVerifyError(const QSslError&)) );
connect(WSServer, SIGNAL(sslErrors(const QList<QSslError>&)), this, SLOT(SslErrors(const QList<QSslError>&)) );
//Now start the server
return WSServer->listen(QHostAddress::Any, port);
}
bool WebServer::setupTcp(quint16 port){
TCPServer = new QTcpServer(this);
//Setup Connections
connect(TCPServer, SIGNAL(newConnection()), this, SLOT(NewSocketConnection()) );
connect(TCPServer, SIGNAL(acceptError(QAbstractSocket::SocketError)), this, SLOT(NewConnectError(QAbstractSocket::SocketError)) );
//Now start the server
return TCPServer->listen(QHostAddress::Any, port);
}
QString WebServer::generateID(){
int id = 0;
for(int i=0; i<OpenSockets.length(); i++){
@@ -88,44 +112,39 @@ QString WebServer::readFile(QString path){
//=======================
// PRIVATE SLOTS
//=======================
// Overall Server signals
void WebServer::ServerClosed(){
qDebug() << "Server Closed:" << QDateTime::currentDateTime().toString(Qt::ISODate);
QCoreApplication::exit(0);
}
void WebServer::ServerError(QWebSocketProtocol::CloseCode code){
qWarning() << "Server Error["+QString::number(code)+"]:" << this->errorString();
}
//GENERIC SERVER SIGNALS
// New Connection Signals
void WebServer::NewSocketConnection(){
if(!this->hasPendingConnections()){ return; }
WebSocket *sock = 0;
if(WSServer!=0){
if(WSServer->hasPendingConnections()){ sock = new WebSocket( WSServer->nextPendingConnection(), generateID(), AUTH); }
}else if(TCPServer!=0){
if(TCPServer->hasPendingConnections()){ sock = new WebSocket( TCPServer->nextPendingConnection(), generateID(), AUTH); }
}
if(sock==0){ return; } //no new connection
qDebug() << "New Socket Connection";
//if(idletimer->isActive()){ idletimer->stop(); }
QWebSocket *csock = this->nextPendingConnection();
if(csock == 0){ qWarning() << " - new connection invalid, skipping..."; QTimer::singleShot(10, this, SLOT(NewSocketConnection())); return; }
qDebug() << " - Accepting connection:" << csock->origin();
WebSocket *sock = new WebSocket(csock, generateID(), AUTH);
connect(sock, SIGNAL(SocketClosed(QString)), this, SLOT(SocketClosed(QString)) );
connect(this, SIGNAL(DispatchStatusUpdate(QString)), sock, SLOT(AppCafeStatusUpdate(QString)) );
sock->setLastDispatch(lastDispatch); //make sure this socket is aware of the latest notification
OpenSockets << sock;
}
void WebServer::NewConnectError(QAbstractSocket::SocketError err){
//if(csock!=0){
//qWarning() << "New Connection Error["+QString::number(err)+"]:" << csock->errorString();
//csock->close();
//}else{
qWarning() << "New Connection Error["+QString::number(err)+"]:" << this->errorString();
//}
//csock = 0; //remove the current socket
void WebServer::NewConnectError(QAbstractSocket::SocketError err){
qWarning() << "New Connection Error["+QString::number(err)+"]:" << ( (WSServer!=0) ? WSServer->errorString() : TCPServer->errorString());
QTimer::singleShot(0,this, SLOT(NewSocketConnection()) ); //check for a new connection
}
// SSL/Authentication Signals
//WEBSOCKET SERVER SIGNALS
// Overall Server signals
void WebServer::ServerClosed(){
QCoreApplication::exit(0);
}
void WebServer::ServerError(QWebSocketProtocol::CloseCode code){
qWarning() << "Server Error["+QString::number(code)+"]:" << ( (WSServer!=0) ? WSServer->errorString() : TCPServer->errorString());
}
// - SSL/Authentication Signals (still websocket only)
void WebServer::OriginAuthRequired(QWebSocketCorsAuthenticator *auth){
qDebug() << "Origin Auth Required:" << auth->origin();
//if(auth->origin() == this->serverAddress().toString()){
@@ -151,6 +170,7 @@ void WebServer::SslErrors(const QList<QSslError> &list){
}
}
// - More Functions for all socket interactions
void WebServer::SocketClosed(QString ID){
for(int i=0; i<OpenSockets.length(); i++){
if(OpenSockets[i]->ID()==ID){ delete OpenSockets.takeAt(i); break; }