@ -56,12 +56,7 @@ struct exit_exception {
} ;
enum connectionStates {
StateIdle = 0 ,
StateGetFileSize = 1 ,
StateGetFileContents = 2 ,
StateStartProgramming = 3 ,
StateCheckProgrammingStatus = 4 ,
StateProgammingFinished = 5
StateIdle = 0
} ;
/*
@ -70,8 +65,7 @@ enum connectionStates {
instance of this class .
*/
SysCtlSocket : : SysCtlSocket ( int sock , TQObject * parent , const char * name ) :
TDEKerberosServerSocket ( parent , name ) , m_criticalSection ( 0 ) , m_loopTimer ( NULL ) , m_config ( static_cast < SysCtlServer * > ( parent ) - > m_config ) , m_commandLoopState ( StateIdle ) ,
m_progpipe ( NULL ) , m_progpipefd ( - 1 ) , m_progErrorFlag ( false ) , m_progDoneFlag ( false )
TDEKerberosServerSocket ( parent , name ) , m_criticalSection ( 0 ) , m_loopTimer ( NULL ) , m_config ( static_cast < SysCtlServer * > ( parent ) - > m_config ) , m_terminals_database ( NULL ) , m_workspaces_database ( NULL ) , m_commandLoopState ( StateIdle )
{
// Initialize timers
@ -85,6 +79,10 @@ SysCtlSocket::SysCtlSocket(int sock, TQObject *parent, const char *name) :
connect ( this , SIGNAL ( connectionClosed ( ) ) , SLOT ( connectionClosedHandler ( ) ) ) ;
connect ( this , SIGNAL ( connectionClosed ( ) ) , parent , SLOT ( remoteConnectionClosed ( ) ) ) ;
setSocket ( sock ) ;
if ( connectToDatabase ( ) ! = 0 ) {
exit ( 1 ) ;
}
}
SysCtlSocket : : ~ SysCtlSocket ( ) {
@ -168,7 +166,7 @@ void SysCtlSocket::commandLoop() {
try {
transferred_data = false ;
if ( state ( ) = = TQSocket : : Connected ) {
if ( ( m_commandLoopState = = StateIdle ) | | ( m_commandLoopState = = StateStartProgramming ) | | ( m_commandLoopState = = StateCheckProgrammingStatus ) | | ( m_commandLoopState = = StateProgammingFinished ) ) {
if ( m_commandLoopState = = StateIdle ) {
// Certain commands can come in at any time during some operations
if ( canReadLine ( ) ) {
processPendingData ( ) ;
@ -178,145 +176,88 @@ void SysCtlSocket::commandLoop() {
ds . setPrintableData ( true ) ;
TQString command ;
ds > > command ;
if ( command = = " USERS " ) {
TQString subCommand ;
ds > > subCommand ;
if ( subCommand = = " TERMINALS " ) {
clearFrameTail ( ) ;
if ( command = = " STATUS " ) {
if ( m_logMessages ! = " " ) {
ds < < TQString ( " LOGMESSAGES " ) ;
writeEndOfFrame ( ) ;
ds < < m_logMessages ;
writeEndOfFrame ( ) ;
m_logMessages = " " ;
TQSqlCursor databaseActivityCursor ( " sessions " , TRUE , m_terminals_database ) ;
databaseActivityCursor . select ( ) ;
while ( databaseActivityCursor . next ( ) ) {
TQ_UINT32 protocolVersion = 1 ;
TQDateTime loginStamp ;
TQDateTime activityStamp ;
loginStamp . setTime_t ( databaseActivityCursor . value ( " stamp_start " ) . toInt ( ) ) ;
activityStamp . setTime_t ( databaseActivityCursor . value ( " stamp_statechange " ) . toInt ( ) ) ;
ds < < protocolVersion ;
ds < < databaseActivityCursor . value ( " pk " ) . toInt ( ) ;
ds < < databaseActivityCursor . value ( " username " ) . toString ( ) ;
ds < < databaseActivityCursor . value ( " servername " ) . toString ( ) ;
ds < < databaseActivityCursor . value ( " server_pid " ) . toInt ( ) ;
ds < < databaseActivityCursor . value ( " wm_pid " ) . toInt ( ) ;
ds < < databaseActivityCursor . value ( " state " ) . toInt ( ) ;
ds < < databaseActivityCursor . value ( " display " ) . toInt ( ) ;
ds < < loginStamp ;
ds < < activityStamp ;
}
else if ( m_progErrorFlag ) {
ds < < TQString ( " ERROR " ) ;
m_progErrorFlag = false ;
writeEndOfFrame ( ) ;
}
else if ( m_progDoneFlag ) {
ds < < TQString ( " DONE " ) ;
ds < < m_progRetCode ;
m_progDoneFlag = false ;
writeEndOfFrame ( ) ;
}
else if ( m_commandLoopState = = StateIdle ) {
ds < < TQString ( " IDLE " ) ;
writeEndOfFrame ( ) ;
else if ( subCommand = = " WORKSPACES " ) {
clearFrameTail ( ) ;
TQSqlCursor databaseActivityCursor ( " activity " , TRUE , m_workspaces_database ) ;
databaseActivityCursor . select ( ) ;
while ( databaseActivityCursor . next ( ) ) {
TQ_UINT32 protocolVersion = 1 ;
TQDateTime loginStamp ;
loginStamp . setTime_t ( databaseActivityCursor . value ( " logontime " ) . toInt ( ) ) ;
ds < < protocolVersion ;
ds < < databaseActivityCursor . value ( " pk " ) . toInt ( ) ;
ds < < databaseActivityCursor . value ( " station " ) . toInt ( ) ;
ds < < databaseActivityCursor . value ( " username " ) . toString ( ) ;
ds < < databaseActivityCursor . value ( " realmname " ) . toString ( ) ;
ds < < databaseActivityCursor . value ( " serverid " ) . toInt ( ) ;
ds < < loginStamp ;
}
else if ( ( m_commandLoopState = = StateStartProgramming ) | | ( m_commandLoopState = = StateCheckProgrammingStatus ) | | ( m_commandLoopState = = StateProgammingFinished ) ) {
ds < < TQString ( " PROGRAMMING " ) ;
writeEndOfFrame ( ) ;
}
else {
ds < < TQString ( " UNKNOWN " ) ;
writeEndOfFrame ( ) ;
}
}
else if ( m_commandLoopState = = StateIdle ) {
if ( command = = " FILE " ) {
m_commandLoopState = StateGetFileSize ;
}
else if ( command = = " PROGRAM " ) {
m_commandLoopState = StateStartProgramming ;
}
else {
printf ( " [WARNING] Received unknown command '%s' \n \r " , command . ascii ( ) ) ;
}
}
transferred_data = true ;
}
}
if ( m_commandLoopState = = StateGetFileSize ) {
if ( canReadLine ( ) ) {
processPendingData ( ) ;
}
if ( canReadFrame ( ) ) {
TQDataStream ds ( this ) ;
ds . setPrintableData ( true ) ;
ds > > m_programmingFileSize ;
clearFrameTail ( ) ;
m_servClientTimeout - > start ( NETWORK_COMM_TIMEOUT_MS , TRUE ) ;
m_commandLoopState = StateGetFileContents ;
}
}
else if ( m_commandLoopState = = StateGetFileContents ) {
if ( canReadLine ( ) ) {
m_servClientTimeout - > start ( NETWORK_COMM_TIMEOUT_MS , TRUE ) ;
processPendingData ( ) ;
}
if ( bytesAvailable ( ) > = m_programmingFileSize ) {
TQByteArray fileContents ( m_programmingFileSize ) ;
readBlock ( fileContents . data ( ) , fileContents . size ( ) ) ;
m_programmingFileName = TQString ( " /tmp/%1#%2.dat " ) . arg ( m_remoteHost ) . arg ( port ( ) ) ;
TQFile outputFile ( m_programmingFileName ) ;
if ( outputFile . open ( IO_ReadWrite ) ) {
outputFile . writeBlock ( fileContents ) ;
outputFile . flush ( ) ;
outputFile . close ( ) ;
}
transferred_data = true ;
m_commandLoopState = StateIdle ;
}
else {
if ( ! m_servClientTimeout - > isActive ( ) ) {
m_progErrorFlag = true ;
transferred_data = true ;
m_commandLoopState = StateIdle ;
}
else if ( command = = " SESSION " ) {
TQString subCommand ;
TQString sessionID ;
ds > > subCommand ;
ds > > sessionID ;
if ( subCommand = = " LOGOFF_TERMINAL " ) {
TQ_UINT32 delay ;
ds > > delay ;
clearFrameTail ( ) ;
// FIXME
}
else if ( subCommand = = " CANCEL_LOGOFF_TERMINAL " ) {
clearFrameTail ( ) ;
// FIXME
}
else if ( m_commandLoopState = = StateStartProgramming ) {
// Start programming!
// Open programming process
m_config - > setGroup ( " Programming " ) ;
TQString programmingScript = m_config - > readEntry ( " script " ) ;
programmingScript . replace ( " %f " , m_programmingFileName ) ;
if ( ! programmingScript . contains ( " 2>&1 " ) ) {
programmingScript . append ( " 2>&1 " ) ;
else if ( subCommand = = " KILL_TERMINAL " ) {
clearFrameTail ( ) ;
// FIXME
}
if ( ( m_progpipe = popen ( programmingScript . ascii ( ) , " r " ) ) = = NULL ) {
m_logMessages . append ( TQString ( " The system was unable to execute '%1' \n Please contact your system administrator with this information " ) . arg ( programmingScript ) ) ;
m_progErrorFlag = true ;
transferred_data = true ;
m_commandLoopState = StateIdle ;
else if ( subCommand = = " KILL_WORKSPACE " ) {
clearFrameTail ( ) ;
// FIXME
}
else {
m_progpipefd = fileno ( m_progpipe ) ;
fcntl ( m_progpipefd , F_SETFL , O_NONBLOCK ) ;
}
m_commandLoopState = StateCheckProgrammingStatus ;
}
else if ( m_commandLoopState = = StateCheckProgrammingStatus ) {
// Check programming status
TQCString buf ;
buf . resize ( 8192 ) ;
ssize_t r = read ( m_progpipefd , buf . data ( ) , buf . size ( ) ) ;
if ( ( r = = - 1 ) & & ( errno = = EAGAIN ) ) {
// No data available yet
clearFrameTail ( ) ;
}
else if ( r > 0 ) {
// Data was received
buf . data ( ) [ r ] = 0 ;
m_logMessages . append ( buf ) ;
}
else {
// Process terminated
m_commandLoopState = StateProgammingFinished ;
clearFrameTail ( ) ;
}
transferred_data = true ;
}
else if ( m_commandLoopState = = StateProgammingFinished ) {
// Programming process terminated; get exit code and clean up
if ( m_progpipe ) {
m_progRetCode = pclose ( m_progpipe ) ;
}
else {
m_progRetCode = - 1 ;
}
m_progpipe = NULL ;
m_progpipefd = - 1 ;
m_progDoneFlag = true ;
m_commandLoopState = StateIdle ;
}
}
m_criticalSection - - ;
@ -344,13 +285,32 @@ int SysCtlSocket::enterCommandLoop() {
return 0 ;
}
int SysCtlSocket : : connectToDatabase ( ) {
if ( ( m_terminals_database ) & & ( m_workspaces_database ) ) {
return - 2 ;
}
m_terminals_database = TQSqlDatabase : : database ( " terminals " ) ;
m_workspaces_database = TQSqlDatabase : : database ( " workspaces " ) ;
if ( ( ! m_terminals_database ) | | ( ! m_workspaces_database ) ) {
printf ( " [ERROR] Databases were not constructed by the application \n \r " ) ; fflush ( stdout ) ;
return - 1 ;
}
return 0 ;
}
/*
The SysCtlServer class handles new connections to the server . For every
client that connects , it creates a new SysCtlSocket - - that instance is now
responsible for the communication with that client .
*/
SysCtlServer : : SysCtlServer ( TQObject * parent , int port , KSimpleConfig * config ) :
TQServerSocket ( port , 1 , parent ) , m_config ( config ) , m_numberOfConnections ( 0 ) {
TQServerSocket ( port , 1 , parent ) , m_config ( config ) , m_numberOfConnections ( 0 ) , m_terminals_database ( NULL ) , m_workspaces_database ( NULL ) , m_sqlPingTimer ( NULL ) {
if ( connectToDatabase ( ) ! = 0 ) {
exit ( 1 ) ;
}
if ( ! ok ( ) ) {
printf ( " [ERROR] Failed to bind to port %d \n \r " , port ) ;
@ -361,7 +321,68 @@ SysCtlServer::SysCtlServer(TQObject* parent, int port, KSimpleConfig* config) :
}
SysCtlServer : : ~ SysCtlServer ( ) {
//
if ( m_sqlPingTimer ) {
m_sqlPingTimer - > stop ( ) ;
delete m_sqlPingTimer ;
m_sqlPingTimer = NULL ;
}
if ( m_terminals_database ) {
TQSqlDatabase : : removeDatabase ( m_terminals_database ) ;
m_terminals_database = NULL ;
}
if ( m_workspaces_database ) {
TQSqlDatabase : : removeDatabase ( m_workspaces_database ) ;
m_workspaces_database = NULL ;
}
}
int SysCtlServer : : connectToDatabase ( ) {
m_config - > setGroup ( " Terminals Database " ) ;
m_terminals_database = TQSqlDatabase : : addDatabase ( m_config - > readEntry ( " driver " ) , " terminals " ) ;
m_terminals_database - > setDatabaseName ( m_config - > readEntry ( " database " ) ) ;
m_terminals_database - > setUserName ( m_config - > readEntry ( " username " ) ) ;
m_terminals_database - > setPassword ( m_config - > readEntry ( " password " ) ) ;
m_terminals_database - > setHostName ( m_config - > readEntry ( " server " ) ) ;
if ( ! m_terminals_database - > open ( ) ) {
printf ( " [ERROR] Failed to connect to control database on server '%s' [%s] \n \r " , m_terminals_database - > hostName ( ) . ascii ( ) , m_terminals_database - > lastError ( ) . text ( ) . ascii ( ) ) ; fflush ( stdout ) ;
TQSqlDatabase : : removeDatabase ( m_terminals_database ) ;
m_terminals_database = NULL ;
return - 1 ;
}
m_config - > setGroup ( " Workspaces Database " ) ;
m_workspaces_database = TQSqlDatabase : : addDatabase ( m_config - > readEntry ( " driver " ) , " workspaces " ) ;
m_workspaces_database - > setDatabaseName ( m_config - > readEntry ( " database " ) ) ;
m_workspaces_database - > setUserName ( m_config - > readEntry ( " username " ) ) ;
m_workspaces_database - > setPassword ( m_config - > readEntry ( " password " ) ) ;
m_workspaces_database - > setHostName ( m_config - > readEntry ( " server " ) ) ;
if ( ! m_workspaces_database - > open ( ) ) {
printf ( " [ERROR] Failed to connect to control database on server '%s' [%s] \n \r " , m_workspaces_database - > hostName ( ) . ascii ( ) , m_workspaces_database - > lastError ( ) . text ( ) . ascii ( ) ) ; fflush ( stdout ) ;
TQSqlDatabase : : removeDatabase ( m_workspaces_database ) ;
m_workspaces_database = NULL ;
return - 1 ;
}
// FIXME
// We currently have no way to handle something as simple as the database server going offline!
// Start database ping process
m_sqlPingTimer = new TQTimer ( ) ;
connect ( m_sqlPingTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( pingSQLServer ( ) ) ) ;
m_sqlPingTimer - > start ( 60 * 1000 ) ;
return 0 ;
}
void SysCtlServer : : pingSQLServer ( ) {
TQSqlQuery terminals_query ( TQString : : null , m_terminals_database ) ;
terminals_query . exec ( " SELECT * FROM sessions " ) ;
TQSqlQuery workspaces_query ( TQString : : null , m_workspaces_database ) ;
workspaces_query . exec ( " SELECT * FROM activity " ) ;
}
void SysCtlServer : : newConnection ( int socket ) {