summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clients/tde/src/app/remotemdi.cpp83
-rw-r--r--clients/tde/src/app/remotemdi.h2
-rw-r--r--protocol.txt4
-rw-r--r--servers/admin_sys_ctl_server_lin/src/admin_sys_ctl.cpp61
-rw-r--r--servers/auth_server_lin/src/auth_conn.cpp65
-rw-r--r--servers/auth_server_lin/src/auth_conn.h4
6 files changed, 204 insertions, 15 deletions
diff --git a/clients/tde/src/app/remotemdi.cpp b/clients/tde/src/app/remotemdi.cpp
index 669350f..223996e 100644
--- a/clients/tde/src/app/remotemdi.cpp
+++ b/clients/tde/src/app/remotemdi.cpp
@@ -29,12 +29,17 @@ using namespace std;
#include "views/instrumentview.h"
#include "dialogs/selectserverdlg.h"
+#define STATUSBAR_TIMEOUT_ID 5
+
RemoteMDI::RemoteMDI()
: KMdiMainFrm(0, "RemoteMDI", KMdi::ChildframeMode), m_children(0), m_rsvSvrSocket(NULL), connToServerConnecting(false), connToServerState(-1), connToServerTimeoutTimer(NULL)
{
setXMLFile("remotelabui.rc");
setIcon(SmallIcon("remote_laboratory_client"));
+ masterPollTimer = new TQTimer();
+ connect(masterPollTimer, SIGNAL(timeout()), this, SLOT(masterPoll()));
+
// Create some actions
KStdAction::close(this, SLOT(closeCurrent()), actionCollection());
KStdAction::quit(this, SLOT(close()), actionCollection());
@@ -67,6 +72,10 @@ RemoteMDI::RemoteMDI()
// Create the status bar
updateStatusBarMainMessage(i18n("No active instruments"));
+ KStatusBar* sb = statusBar();
+ if (sb) {
+ sb->insertItem(i18n("Unknown Time Remaining"), STATUSBAR_TIMEOUT_ID, 0, true);
+ }
processActions();
@@ -77,6 +86,11 @@ RemoteMDI::RemoteMDI()
RemoteMDI::~RemoteMDI()
{
+ if (masterPollTimer) {
+ masterPollTimer->stop();
+ delete masterPollTimer;
+ }
+
while (m_pCurrentWindow) {
closeCurrent();
}
@@ -255,6 +269,7 @@ void RemoteMDI::finishConnectingToServer() {
}
connToServerState = 3;
connToServerConnecting = false;
+ masterPollTimer->start(0, TRUE);
processLockouts();
break;
}
@@ -263,6 +278,67 @@ void RemoteMDI::finishConnectingToServer() {
}
}
+void RemoteMDI::masterPoll() {
+ // Query current termination timestamp
+ if (m_rsvSvrSocket) {
+ if (m_rsvSvrSocket->state() == TQSocket::Connected) {
+ TQDataStream ds(m_rsvSvrSocket);
+ ds.setPrintableData(true);
+ TQ_ULLONG terminationStamp;
+ long long currentStamp;
+ ds << TQString("TSTP");
+ m_rsvSvrSocket->writeEndOfFrame();
+ while (!m_rsvSvrSocket->canReadFrame()) {
+ tqApp->processEvents();
+ if (!m_rsvSvrSocket) {
+ masterPollTimer->start(1000, TRUE);
+ return;
+ }
+ }
+ ds >> terminationStamp;
+ m_rsvSvrSocket->clearFrameTail();
+ currentStamp = TQDateTime::currentDateTime().toTime_t();
+
+ KStatusBar* sb = statusBar();
+ if (sb) {
+ if (terminationStamp == 0) {
+ sb->changeItem(i18n("Unlimited Time Remaining"), STATUSBAR_TIMEOUT_ID);
+ }
+ else {
+ long long difference = terminationStamp - currentStamp;
+ int seconds = 0;
+ int minutes = 0;
+ int hours = 0;
+ int days = 0;
+ if (difference >= 0) {
+ days = (difference / 86400);
+ difference = difference - (days * 86400);
+ hours = (difference / 3600);
+ difference = difference - (hours * 3600);
+ minutes = (difference / 60);
+ difference = difference - (minutes * 60);
+ seconds = difference;
+ }
+ TQString differenceString;
+ if (days > 0) {
+ differenceString.append(i18n("%1 day(s), ").arg(days));
+ }
+ if ((days > 0) || (hours > 0)) {
+ differenceString.append(i18n("%1 hours(s), ").arg(hours));
+ }
+ if ((days > 0) || (hours > 0) || (minutes > 0)) {
+ differenceString.append(i18n("%1 minutes(s), ").arg(minutes));
+ }
+ differenceString.append(i18n("%1 seconds(s)").arg(seconds));
+ sb->changeItem(i18n("%1 Remaining").arg(differenceString), STATUSBAR_TIMEOUT_ID);
+ }
+ }
+ }
+ }
+
+ masterPollTimer->start(1000, TRUE);
+}
+
void RemoteMDI::connectToServer() {
if (m_rsvSvrSocket) {
if (m_rsvSvrSocket->state() != TQSocket::Idle) {
@@ -394,6 +470,13 @@ void RemoteMDI::processLockouts() {
for (TQPtrList<KAction>::Iterator it(m_instrumentActionList.begin()); it != m_instrumentActionList.end(); ++it) {
(*it)->setEnabled(connected);
}
+
+ if (!connected) {
+ KStatusBar* sb = statusBar();
+ if (sb) {
+ sb->changeItem(i18n("Unknown Time Remaining"), STATUSBAR_TIMEOUT_ID);
+ }
+ }
}
void RemoteMDI::configToolbars() {
diff --git a/clients/tde/src/app/remotemdi.h b/clients/tde/src/app/remotemdi.h
index c2c8884..ff93ea2 100644
--- a/clients/tde/src/app/remotemdi.h
+++ b/clients/tde/src/app/remotemdi.h
@@ -69,6 +69,7 @@ class RemoteMDI : public KMdiMainFrm
void processLockouts();
void processActions();
void startModule();
+ void masterPoll();
protected:
virtual bool queryClose();
@@ -86,6 +87,7 @@ class RemoteMDI : public KMdiMainFrm
bool connToServerConnecting;
int connToServerState;
TQTimer *connToServerTimeoutTimer;
+ TQTimer *masterPollTimer;
KAction *connect_action;
KAction *disconnect_action;
diff --git a/protocol.txt b/protocol.txt
index dda7c2d..c520be2 100644
--- a/protocol.txt
+++ b/protocol.txt
@@ -61,6 +61,10 @@ If BIND was previously commanded on this connection, the server must respond wit
Example: SERV EOF
libremotelab_fpgaviewer EOF
+TSTP:
+Returns a long long value containing the termination timestamp, if set
+If an administrator has enabled automatic termination of the client's session, a UNIX timestamp with the exact termination time must be returned. If automatic termination has not been enabled, the server must return zero.
+
QUIT:
Gracefully terminates the connection.
The server should return the case-sensitive text "OK" and must immediately close all active connections for the current user.
diff --git a/servers/admin_sys_ctl_server_lin/src/admin_sys_ctl.cpp b/servers/admin_sys_ctl_server_lin/src/admin_sys_ctl.cpp
index 3cce4b5..f0cf958 100644
--- a/servers/admin_sys_ctl_server_lin/src/admin_sys_ctl.cpp
+++ b/servers/admin_sys_ctl_server_lin/src/admin_sys_ctl.cpp
@@ -181,6 +181,8 @@ void SysCtlSocket::commandLoop() {
ds >> subCommand;
if (subCommand == "TERMINALS") {
clearFrameTail();
+ ds << TQString("OK");
+ writeEndOfFrame();
TQSqlCursor databaseActivityCursor("sessions", TRUE, m_terminals_database);
databaseActivityCursor.select();
while (databaseActivityCursor.next()) {
@@ -205,6 +207,8 @@ void SysCtlSocket::commandLoop() {
}
else if (subCommand == "WORKSPACES") {
clearFrameTail();
+ ds << TQString("OK");
+ writeEndOfFrame();
TQSqlCursor databaseActivityCursor("activity", TRUE, m_workspaces_database);
databaseActivityCursor.select();
while (databaseActivityCursor.next()) {
@@ -224,6 +228,8 @@ void SysCtlSocket::commandLoop() {
}
else {
clearFrameTail();
+ ds << TQString("ERRINVCMD");
+ writeEndOfFrame();
}
}
else if (command == "SESSION") {
@@ -235,22 +241,69 @@ void SysCtlSocket::commandLoop() {
TQ_UINT32 delay;
ds >> delay;
clearFrameTail();
- // FIXME
+ // FIXME UNIMPLEMENTED
+ ds << TQString("ERRINVCMD");
+ writeEndOfFrame();
}
else if (subCommand == "CANCEL_LOGOFF_TERMINAL") {
clearFrameTail();
- // FIXME
+ // FIXME UNIMPLEMENTED
+ ds << TQString("ERRINVCMD");
+ writeEndOfFrame();
}
else if (subCommand == "KILL_TERMINAL") {
clearFrameTail();
- // FIXME
+ TQSqlCursor databaseActivityCursor("sessions", TRUE, m_terminals_database);
+ databaseActivityCursor.select(TQString("pk=%1").arg(sessionID));
+ if (databaseActivityCursor.next()) {
+ // Gather server information
+ TQString server_name = databaseActivityCursor.value("servername").toString();
+ int server_pid = databaseActivityCursor.value("server_pid").toInt();
+ // Kill server process
+ TQString command = TQString("ssh root@%1 'kill -9 %2'").arg(server_name).arg(server_pid);
+ if (system(command.ascii()) == 0) {
+ // Remove database entry
+ databaseActivityCursor.select(TQString("pk=%1").arg(sessionID));
+ if (databaseActivityCursor.next()) {
+ databaseActivityCursor.primeDelete();
+ databaseActivityCursor.del(true);
+ }
+ ds << TQString("OK");
+ }
+ else {
+ ds << TQString("ERRFAILED");
+ }
+ writeEndOfFrame();
+ }
+ else {
+ ds << TQString("ERRINVCMD");
+ }
+ writeEndOfFrame();
}
else if (subCommand == "KILL_WORKSPACE") {
clearFrameTail();
- // FIXME
+ TQSqlCursor databaseActivityCursor("activity", TRUE, m_workspaces_database);
+ databaseActivityCursor.select(TQString("pk=%1").arg(sessionID));
+ if (databaseActivityCursor.next()) {
+ databaseActivityCursor.select(TQString("pk=%1").arg(sessionID));
+ if (databaseActivityCursor.next()) {
+ TQSqlRecord *buffer = databaseActivityCursor.primeUpdate();
+ buffer->setValue("terminate", true);
+ databaseActivityCursor.update();
+ }
+
+ ds << TQString("OK");
+ writeEndOfFrame();
+ }
+ else {
+ ds << TQString("ERRINVCMD");
+ }
+ writeEndOfFrame();
}
else {
clearFrameTail();
+ ds << TQString("ERRINVCMD");
+ writeEndOfFrame();
}
}
else {
diff --git a/servers/auth_server_lin/src/auth_conn.cpp b/servers/auth_server_lin/src/auth_conn.cpp
index f3f3474..2ed9860 100644
--- a/servers/auth_server_lin/src/auth_conn.cpp
+++ b/servers/auth_server_lin/src/auth_conn.cpp
@@ -41,7 +41,7 @@ struct exit_exception {
instance of this class.
*/
AuthSocket::AuthSocket(int sock, int serverID, TQObject *parent, const char *name) :
- TDEKerberosServerSocket(parent, name), m_criticalSection(0), m_stationID(-1), m_bound(false), m_serverID(serverID), m_servActive(false), m_servState(0), m_servClientSocket(NULL), m_servClientTimeout(NULL), m_loopTimer(NULL), m_config(static_cast<AuthServer*>(parent)->m_config), m_database(NULL), m_databaseStationsCursor(NULL),
+ TDEKerberosServerSocket(parent, name), m_criticalSection(0), m_stationID(-1), m_bound(false), m_serviceID(0), m_serverID(serverID), m_terminationStamp(0), m_servActive(false), m_servState(0), m_servClientSocket(NULL), m_servClientTimeout(NULL), m_loopTimer(NULL), m_pollTimer(NULL), m_config(static_cast<AuthServer*>(parent)->m_config), m_database(NULL), m_databaseStationsCursor(NULL),
m_databaseServicesCursor(NULL), m_databaseServiceTypesCursor(NULL), m_databasePermissionsCursor(NULL), m_databaseActivityCursor(NULL)
{
@@ -59,6 +59,10 @@ AuthSocket::AuthSocket(int sock, int serverID, TQObject *parent, const char *nam
if (connectToDatabase() != 0) {
exit(1);
}
+
+ m_pollTimer = new TQTimer();
+ connect(m_pollTimer, SIGNAL(timeout()), this, SLOT(pollFlags()));
+ m_pollTimer->start(0, TRUE);
}
AuthSocket::~AuthSocket() {
@@ -67,6 +71,11 @@ AuthSocket::~AuthSocket() {
delete m_kerberosInitTimer;
m_kerberosInitTimer = NULL;
}
+ if (m_pollTimer) {
+ m_pollTimer->stop();
+ delete m_pollTimer;
+ m_pollTimer = NULL;
+ }
if (m_loopTimer) {
m_loopTimer->stop();
delete m_loopTimer;
@@ -102,13 +111,11 @@ void AuthSocket::close() {
void AuthSocket::connectionClosedHandler() {
printf("[DEBUG] Connection from %s closed\n\r", m_remoteHost.ascii());
- if (m_bound) {
- // Update database
- m_databaseActivityCursor->select(TQString("station='%1' AND username='%2' AND realmname='%3'").arg(m_stationID).arg(m_authenticatedUserName).arg(m_authenticatedRealmName));
- if (m_databaseActivityCursor->next()) {
- m_databaseActivityCursor->primeDelete();
- m_databaseActivityCursor->del(true);
- }
+ // Update database
+ m_databaseActivityCursor->select(TQString("station='%1' AND username='%2' AND realmname='%3' AND serviceid=%4").arg(m_stationID).arg(m_authenticatedUserName).arg(m_authenticatedRealmName).arg(m_serviceID));
+ if (m_databaseActivityCursor->next()) {
+ m_databaseActivityCursor->primeDelete();
+ m_databaseActivityCursor->del(true);
}
if (m_criticalSection > 0) {
@@ -321,6 +328,24 @@ int AuthSocket::servLoop() {
}
}
+void AuthSocket::pollFlags() {
+ if ((m_bound) || (m_servActive)) {
+ long long timestamp = TQDateTime::currentDateTime().toTime_t();
+ m_databaseActivityCursor->select(TQString("station='%1' AND username='%2' AND realmname='%3' AND serviceid=%4").arg(m_stationID).arg(m_authenticatedUserName).arg(m_authenticatedRealmName).arg(m_serviceID));
+ if (m_databaseActivityCursor->next()) {
+ m_terminationStamp = m_databaseActivityCursor->value("terminate").toLongLong();
+ if (m_terminationStamp > 0) {
+ if (m_terminationStamp <= timestamp) {
+ printf("[DEBUG] Got termination request from database (%lld <= %lld)\n\r", m_terminationStamp, timestamp); fflush(stdout);
+ close();
+ }
+ }
+ }
+ }
+
+ m_pollTimer->start(1000, TRUE);
+}
+
void AuthSocket::commandLoop() {
bool transferred_data;
@@ -447,6 +472,8 @@ void AuthSocket::commandLoop() {
buffer->setValue("realmname", m_authenticatedRealmName);
buffer->setValue("logontime", TQDateTime::currentDateTime().toTime_t());
buffer->setValue("serverid", m_serverID);
+ buffer->setValue("serviceid", 0);
+ buffer->setValue("terminate", 0);
m_databaseActivityCursor->insert();
ds << TQString("OK");
@@ -465,7 +492,7 @@ void AuthSocket::commandLoop() {
clearFrameTail();
printf("[DEBUG] SERV command parameter was %s from user %s@%s\n\r", libname.ascii(), m_authenticatedUserName.ascii(), m_authenticatedRealmName.ascii()); fflush(stdout);
- m_databaseActivityCursor->select(TQString("username='%1' AND realmname='%2'").arg(m_authenticatedUserName).arg(m_authenticatedRealmName));
+ m_databaseActivityCursor->select(TQString("username='%1' AND realmname='%2' AND serviceid=0").arg(m_authenticatedUserName).arg(m_authenticatedRealmName));
if (m_databaseActivityCursor->next()) {
m_stationID = m_databaseActivityCursor->value("station").toInt();
}
@@ -497,6 +524,18 @@ void AuthSocket::commandLoop() {
m_srvServiceHostName = m_databaseServicesCursor->value("hostname").toString();
m_srvServicePort = m_databaseServicesCursor->value("port").toInt();
+ // Update database
+ m_serviceID = sid;
+ TQSqlRecord *buffer = m_databaseActivityCursor->primeInsert();
+ buffer->setValue("station", m_stationID);
+ buffer->setValue("username", m_authenticatedUserName);
+ buffer->setValue("realmname", m_authenticatedRealmName);
+ buffer->setValue("logontime", TQDateTime::currentDateTime().toTime_t());
+ buffer->setValue("serverid", m_serverID);
+ buffer->setValue("serviceid", m_serviceID);
+ buffer->setValue("terminate", 0);
+ m_databaseActivityCursor->insert();
+
if (!m_servClientSocket) m_servClientSocket = new TDEKerberosClientSocket;
m_servClientSocket->setServiceName("remotefpga");
@@ -514,6 +553,10 @@ void AuthSocket::commandLoop() {
}
}
}
+ else if (command == "TSTP") {
+ ds << m_terminationStamp;
+ writeEndOfFrame();
+ }
else {
ds << TQString("ERRINVCMD");
writeEndOfFrame();
@@ -589,9 +632,9 @@ AuthServer::AuthServer(TQObject* parent) :
// Delete existing activity entries for this server ID
TQSqlCursor databaseActivityCursor("activity", TRUE, m_database);
databaseActivityCursor.select(TQString("serverid='%1'").arg(m_serverID));
- if (databaseActivityCursor.next()) {
+ while (databaseActivityCursor.next()) {
databaseActivityCursor.primeDelete();
- databaseActivityCursor.del(true);
+ databaseActivityCursor.del(false);
}
if ( !ok() ) {
diff --git a/servers/auth_server_lin/src/auth_conn.h b/servers/auth_server_lin/src/auth_conn.h
index d1245be..af816b9 100644
--- a/servers/auth_server_lin/src/auth_conn.h
+++ b/servers/auth_server_lin/src/auth_conn.h
@@ -60,6 +60,7 @@ class AuthSocket : public TDEKerberosServerSocket
void connectionClosedHandler();
void commandLoop();
int servLoop();
+ void pollFlags();
private:
int line;
@@ -67,7 +68,9 @@ class AuthSocket : public TDEKerberosServerSocket
TQString m_remoteHost;
int m_stationID;
bool m_bound;
+ int m_serviceID;
int m_serverID;
+ TQ_ULLONG m_terminationStamp;
bool m_servActive;
int m_servState;
@@ -78,6 +81,7 @@ class AuthSocket : public TDEKerberosServerSocket
TQTimer* m_kerberosInitTimer;
TQTimer* m_loopTimer;
+ TQTimer* m_pollTimer;
TQByteArray m_loopBuffer;
KSimpleConfig* m_config;