Fix up the bridge/server connection management stuff. Now the server will automatically check/re-connect as needed.

This commit is contained in:
Ken Moore
2016-05-23 10:05:09 -04:00
parent 87f344e218
commit 376a903991
7 changed files with 54 additions and 22 deletions

View File

@@ -10,7 +10,7 @@
#define DEBUG 0
#define IDLETIMEOUTMINS 30
BridgeConnection::BridgeConnection(QWebSocket *sock, QString ID){
BridgeConnection::BridgeConnection(QObject *parent, QWebSocket *sock, QString ID) : QObject(parent){
SockID = ID;
SockAuthToken.clear(); //nothing set initially
SOCKET = sock;

View File

@@ -11,7 +11,7 @@
class BridgeConnection : public QObject{
Q_OBJECT
public:
BridgeConnection(QWebSocket*, QString ID);
BridgeConnection(QObject *parent, QWebSocket*, QString ID);
~BridgeConnection();
QString ID();

View File

@@ -120,7 +120,7 @@ void BridgeServer::NewSocketConnection(){
if(allowConnection(ws->peerAddress()) ){
QString name = ws->peerName();
if(name.isEmpty()){ name = ws->peerAddress().toString(); }
sock = new BridgeConnection( ws, generateID(name) );
sock = new BridgeConnection( this, ws, generateID(name) );
}else{
ws->abort();
}

View File

@@ -142,7 +142,7 @@ RestOutputStruct::ExitCode WebSocket::EvaluateBackendRequest(const RestInputStru
// === SYSADM SSL SETTINGS ===
RestOutputStruct::ExitCode WebSocket::EvaluateSysadmSettingsRequest(const QJsonValue in_args, QJsonObject *out){
qDebug() << "sysadm/settings Request:" << in_args;
//qDebug() << "sysadm/settings Request:" << in_args;
if(!in_args.isObject()){ return RestOutputStruct::BADREQUEST; }
QJsonObject argsO = in_args.toObject();
QStringList keys = argsO.keys();

View File

@@ -16,7 +16,7 @@ WebServer::WebServer(){
WSServer = 0;
TCPServer = 0;
bridgeTimer = new QTimer(this);
bridgeTimer->setInterval(5*60*1000); //5 minutes
bridgeTimer->setInterval(60000); //1 minute
connect(bridgeTimer, SIGNAL(timeout()), this, SLOT(checkBridges()) );
AUTH = new AuthorizationManager();
connect(AUTH, SIGNAL(BlockHost(QHostAddress)), this, SLOT(BlackListConnection(QHostAddress)) );
@@ -145,13 +145,13 @@ void WebServer::NewSocketConnection(){
if(WSServer->hasPendingConnections()){
QWebSocket *ws = WSServer->nextPendingConnection();
if( !allowConnection(ws->peerAddress()) ){ ws->close(); }
else{ sock = new WebSocket( ws, generateID(), AUTH); }
else{ sock = new WebSocket( this, ws, generateID(), AUTH); }
}
}else if(TCPServer!=0){
if(TCPServer->hasPendingConnections()){
QSslSocket *ss = TCPServer->nextPendingConnection();
if( !allowConnection(ss->peerAddress()) ){ ss->close(); }
else{ sock = new WebSocket( ss, generateID(), AUTH); }
else{ sock = new WebSocket( this, ss, generateID(), AUTH); }
}
}
if(sock==0){ return; } //no new connection
@@ -211,6 +211,7 @@ void WebServer::SslErrors(const QList<QSslError> &list){
// - More Functions for all socket interactions
void WebServer::SocketClosed(QString ID){
qDebug() << "Socket Closed:" << ID;
for(int i=0; i<OpenSockets.length(); i++){
if(OpenSockets[i]->ID()==ID){ delete OpenSockets.takeAt(i); break; }
}
@@ -219,7 +220,7 @@ void WebServer::SocketClosed(QString ID){
// BRIDGE Connection checks
void WebServer::checkBridges(){
qDebug() << "Check Bridges:" << WS_MODE;
//qDebug() << "Check Bridges:" << WS_MODE << QDateTime::currentDateTime().toString(Qt::ISODate);
if(!WS_MODE){ return; }
//Get all the unique bridge URL's we need connections to
@@ -229,17 +230,18 @@ void WebServer::checkBridges(){
}
//Now browse through all the current connections and see if any are already active
for(int i=0; i<OpenSockets.length(); i++){
if( bridgeKeys.contains( OpenSockets[i]->ID() ) ){
bool active = OpenSockets[i]->isActive();
if( bridgeKeys.contains( OpenSockets[i]->ID() ) && active){
bridgeKeys.removeAll( OpenSockets[i]->ID() ); //already running - remove from the temporary list
}else if( OpenSockets[i]->ID().toInt()==0 ){
}else if( OpenSockets[i]->ID().toInt()==0 || !active){
//non-integer ID - another bridge connection which must have been removed from the server settings
OpenSockets[i]->closeConnection();
}
}
//Now startup any connections which are missing
for(int i=0; i<bridgeKeys.length(); i++){
qDebug() << "Try to connect to bridge:" << bridgeKeys[i];
WebSocket *sock = new WebSocket(bridgeKeys[i], bridgeKeys[i], AUTH);
//qDebug() << "Try to connect to bridge:" << bridgeKeys[i];
WebSocket *sock = new WebSocket(this, bridgeKeys[i], bridgeKeys[i], AUTH);
connect(sock, SIGNAL(SocketClosed(QString)), this, SLOT(SocketClosed(QString)) );
OpenSockets << sock;
}

View File

@@ -11,7 +11,7 @@
#define DEBUG 0
#define IDLETIMEOUTMINS 30
WebSocket::WebSocket(QWebSocket *sock, QString ID, AuthorizationManager *auth){
WebSocket::WebSocket(QObject *parent, QWebSocket *sock, QString ID, AuthorizationManager *auth) : QObject(parent){
SockID = ID;
isBridge = false;
SockAuthToken.clear(); //nothing set initially
@@ -31,9 +31,13 @@ WebSocket::WebSocket(QWebSocket *sock, QString ID, AuthorizationManager *auth){
connect(this, SIGNAL(SendMessage(QString)), this, SLOT(sendReply(QString)) );
idletimer->start();
QTimer::singleShot(30000, this, SLOT(checkAuth()));
connCheckTimer = new QTimer(this);
connCheckTimer->setInterval(60000); //1 minute check for connection validity
connect(connCheckTimer, SIGNAL(timeout()), this, SLOT(checkConnection()) );
connCheckTimer->start();
}
WebSocket::WebSocket(QSslSocket *sock, QString ID, AuthorizationManager *auth){
WebSocket::WebSocket(QObject *parent, QSslSocket *sock, QString ID, AuthorizationManager *auth) : QObject(parent){
SockID = ID;
SockAuthToken.clear(); //nothing set initially
TSOCKET = sock;
@@ -57,9 +61,13 @@ WebSocket::WebSocket(QSslSocket *sock, QString ID, AuthorizationManager *auth){
//qDebug() << " - Socket Encrypted:" << TSOCKET->isEncrypted();
idletimer->start();
QTimer::singleShot(30000, this, SLOT(checkAuth()));
connCheckTimer = new QTimer(this);
connCheckTimer->setInterval(60000); //1 minute check for connection validity
connect(connCheckTimer, SIGNAL(timeout()), this, SLOT(checkConnection()) );
connCheckTimer->start();
}
WebSocket::WebSocket(QString url, QString ID, AuthorizationManager *auth){
WebSocket::WebSocket(QObject *parent, QString url, QString ID, AuthorizationManager *auth) : QObject(parent){
//sets up a bridge connection (websocket only)
SockID = ID;
isBridge = true;
@@ -82,7 +90,6 @@ WebSocket::WebSocket(QString url, QString ID, AuthorizationManager *auth){
//connect(SOCKET, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)) );
connect(SOCKET, SIGNAL(sslErrors(const QList<QSslError>&)), this, SLOT(SslError(const QList<QSslError>&)) );
//idletimer->start(); //do not idle out on a bridge connection
/*QTimer::singleShot(30000, this, SLOT(checkAuth()));*/
//Assemble the URL as needed
if(!url.startsWith("wss://")){ url.prepend("wss://"); }
bool hasport = false;
@@ -91,8 +98,11 @@ WebSocket::WebSocket(QString url, QString ID, AuthorizationManager *auth){
//Now setup/init the connection
qDebug() << "Connecting to bridge:" << url;
SOCKET->setSslConfiguration(QSslConfiguration::defaultConfiguration());
//QTimer::singleShot(0,SOCKET, SLOT(ignoreSslErrors()) );
SOCKET->open(QUrl(url));
connCheckTimer = new QTimer(this);
connCheckTimer->setInterval(60000); //1 minute check for connection validity
connect(connCheckTimer, SIGNAL(timeout()), this, SLOT(checkConnection()) );
connCheckTimer->start();
}
WebSocket::~WebSocket(){
@@ -121,6 +131,16 @@ void WebSocket::closeConnection(){
}
}
bool WebSocket::isActive(){
bool ok = false;
if(SOCKET!=0){
ok = SOCKET->isValid();
}else if(TSOCKET!=0){
ok = TSOCKET->isValid();
}
return ok;
}
//=======================
// PRIVATE
//=======================
@@ -448,6 +468,14 @@ QStringList WebSocket::JsonArrayToStringList(QJsonArray array){
// =====================
// PRIVATE SLOTS
// =====================
void WebSocket::checkConnection(){
if(SOCKET !=0 && !SOCKET->isValid()){
emit SocketClosed(SockID);
}
else if(TSOCKET !=0 && !TSOCKET->isValid() ){
emit SocketClosed(SockID);
}
}
void WebSocket::checkIdle(){
if(SOCKET !=0 && SOCKET->isValid()){
LogManager::log(LogManager::HOST,"Connection Idle: "+SockPeerIP);
@@ -578,7 +606,7 @@ void WebSocket::SslError(const QList<QSslError> &err){ //sslErrors() signal
}
void WebSocket::startBridgeAuth(){
qDebug() << "Init Bridge Auth...";
//qDebug() << "Init Bridge Auth...";
QJsonObject obj;
obj.insert("id", "server_to_bridge_auth");
obj.insert("namespace","rpc");

View File

@@ -19,16 +19,17 @@ struct bridge_data{
class WebSocket : public QObject{
Q_OBJECT
public:
WebSocket(QWebSocket*, QString ID, AuthorizationManager *auth);
WebSocket(QSslSocket*, QString ID, AuthorizationManager *auth);
WebSocket(QString url, QString ID, AuthorizationManager *auth); //sets up a bridge connection (websocket only)
WebSocket(QObject *parent, QWebSocket*, QString ID, AuthorizationManager *auth);
WebSocket(QObject *parent, QSslSocket*, QString ID, AuthorizationManager *auth);
WebSocket(QObject *parent, QString url, QString ID, AuthorizationManager *auth); //sets up a bridge connection (websocket only)
~WebSocket();
QString ID();
void closeConnection();
bool isActive(); //check if the connection is still active/valid
private:
QTimer *idletimer;
QTimer *idletimer, *connCheckTimer;
QWebSocket *SOCKET;
QSslSocket *TSOCKET;
QString SockID, SockAuthToken, SockPeerIP;
@@ -90,6 +91,7 @@ private:
private slots:
void sendReply(QString msg);
void checkConnection(); //see if the current connection is still open/valid
void checkIdle(); //see if the currently-connected client is idle
void checkAuth(); //see if the currently-connected client has authed yet
void SocketClosing();