/***************************************************************************
* Copyright ( C ) 2012 - 2014 by Timothy Pearson *
* kb9vqf @ pearsoncomputing . net *
* *
* This program is free software ; you can redistribute it and / or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation ; either version 2 of the License , or *
* ( at your option ) any later version . *
* *
* This program is distributed in the hope that it will be useful , *
* but WITHOUT ANY WARRANTY ; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the *
* GNU General Public License for more details . *
* *
* You should have received a copy of the GNU General Public License *
* along with this program ; if not , write to the *
* Free Software Foundation , Inc . , *
* 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA . *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "tqtrla.h"
# include <pwd.h>
# include <tqwidget.h>
# include <tqbuffer.h>
# include <kdialog.h>
# include <tdelocale.h>
# include <tdemessagebox.h>
# include <libtdeldap.h>
# define SERVER_TIMEOUT_MS 10000
# define FPGA_DATA_PROCESSING_TIMEOUT_MS 2500
namespace KParts
{
class RemoteInstrumentPartPrivate
{
public :
RemoteInstrumentPartPrivate ( ) {
//
}
~ RemoteInstrumentPartPrivate ( ) {
//
}
} ;
RemoteInstrumentPart : : RemoteInstrumentPart ( TQObject * parent , const char * name )
: Part ( parent , name ) ,
m_socket ( NULL ) , connToServerConnecting ( false ) , connToServerState ( - 1 ) , connToServerTimeoutTimer ( NULL ) , m_fixedSize ( false ) , m_mdiMainForm ( NULL )
{
d = new RemoteInstrumentPartPrivate ;
// Create timers
m_connectionTimer = new TQTimer ( this ) ;
connect ( m_connectionTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( finishConnectingToServer ( ) ) ) ;
}
RemoteInstrumentPart : : ~ RemoteInstrumentPart ( ) {
RemoteInstrumentPart : : closeURL ( ) ;
delete d ;
}
bool RemoteInstrumentPart : : openURL ( const KURL & url ) {
m_url = url ;
return false ;
}
bool RemoteInstrumentPart : : closeURL ( ) {
return false ;
}
void RemoteInstrumentPart : : setUsingFixedSize ( bool fixed ) {
m_fixedSize = fixed ;
if ( ! fixed ) {
TQWidget * parentWidget = dynamic_cast < TQWidget * > ( parent ( ) ) ;
if ( parentWidget ) {
parentWidget - > setMinimumSize ( 0 , 0 ) ;
parentWidget - > setMaximumSize ( TQWIDGETSIZE_MAX , TQWIDGETSIZE_MAX ) ;
}
}
emit ( usingFixedSizeChanged ( fixed ) ) ;
}
TQPtrList < TDEAction > RemoteInstrumentPart : : menuActionList ( ) {
return TQPtrList < TDEAction > ( ) ;
}
void RemoteInstrumentPart : : resize ( TQSize size ) {
TQWidget * parentWidget = dynamic_cast < TQWidget * > ( parent ( ) ) ;
if ( parentWidget ) {
if ( m_fixedSize ) {
parentWidget - > setFixedSize ( size ) ;
}
else {
parentWidget - > resize ( size ) ;
}
}
}
void RemoteInstrumentPart : : close ( ) {
TQWidget * parentWidget = dynamic_cast < TQWidget * > ( parent ( ) ) ;
if ( parentWidget ) {
parentWidget - > close ( ) ;
}
}
int RemoteInstrumentPart : : getNewTicket ( ) {
int ret = - 1 ;
TQWidget * parentWidget = dynamic_cast < TQWidget * > ( parent ( ) ) ;
if ( ! parentWidget ) {
return ret ;
}
LDAPCredentials credentials ;
KerberosTicketInfoList ticketList = LDAPManager : : getKerberosTicketList ( ) ;
if ( ticketList . count ( ) > 0 ) {
TQStringList princParts = TQStringList : : split ( " @ " , ticketList [ 0 ] . cachePrincipal ) ;
credentials . username = princParts [ 0 ] ;
credentials . realm = princParts [ 1 ] ;
}
else {
struct passwd * pwd = getpwuid ( geteuid ( ) ) ;
if ( pwd ) {
credentials . username = TQString ( pwd - > pw_name ) ;
}
}
int result = LDAPManager : : getKerberosPassword ( credentials , i18n ( " Please provide Kerberos credentials " ) , false , parentWidget ) ;
if ( result = = KDialog : : Accepted ) {
TQString errorstring ;
TQString service ;
if ( LDAPManager : : obtainKerberosTicket ( credentials , service , & errorstring ) ! = 0 ) {
KMessageBox : : error ( parentWidget , i18n ( " <qt>Failed to obtain ticket<p>%1</qt> " ) . arg ( errorstring ) , i18n ( " Failed to obtain Kerberos ticket " ) ) ;
}
else {
ret = 0 ;
}
}
return ret ;
}
void RemoteInstrumentPart : : setStatusMessage ( const TQString & message ) {
emit ( statusMessageSet ( message ) ) ;
}
TQ_ULONG RemoteInstrumentPart : : maximumSocketDataChunkSize ( ) {
// FIXME
// Dynamically set this!
return 512 ;
}
TQStringList RemoteInstrumentPart : : textForServerError ( TQString shortError ) {
TQStringList ret ;
if ( shortError = = " ERRNOCONN " ) {
ret . append ( i18n ( " <qt>Unable to establish connection with backend server<p>Please verify that you are currently connected to a workspace</qt> " ) ) ;
ret . append ( i18n ( " Connection Failed " ) ) ;
}
else if ( shortError = = " ERRNOTAVL " ) {
ret . append ( i18n ( " <qt>The backend server is not available at this time<p>Please try a different workspace, or try again later</qt> " ) ) ;
ret . append ( i18n ( " Connection Failed " ) ) ;
}
else if ( shortError = = " ERRNOSERV " ) {
ret . append ( i18n ( " <qt>The active laboratory workspace does not support the requested service</qt> " ) ) ;
ret . append ( i18n ( " Service Unavailable " ) ) ;
}
else {
ret . append ( i18n ( " <qt>Unable to establish connection with remote server</qt> " ) ) ;
ret . append ( i18n ( " Connection Failed " ) ) ;
}
return ret ;
}
int RemoteInstrumentPart : : connectToServer ( TQString server ) {
if ( m_socket ) {
return - 1 ;
}
if ( ! m_socket ) {
m_socket = new TDEKerberosClientSocket ( this ) ;
connect ( m_socket , TQT_SIGNAL ( statusMessageUpdated ( const TQString & ) ) , this , TQT_SLOT ( setStatusMessage ( const TQString & ) ) ) ;
}
m_hostName = server ;
m_socket - > setServiceName ( " ulab " ) ;
m_socket - > setServerFQDN ( m_hostName ) ;
m_socket - > connectToHost ( m_hostName , 4004 ) ;
// Finish connecting when appropriate
connToServerState = 0 ;
connToServerConnecting = true ;
m_connectionTimer - > start ( 100 , TRUE ) ;
return 0 ;
}
void RemoteInstrumentPart : : disconnectFromServer ( ) {
disconnectFromServerCallback ( ) ;
m_connectionTimer - > stop ( ) ;
if ( m_socket ) {
m_socket - > clearPendingData ( ) ;
m_socket - > close ( ) ;
delete m_socket ;
m_socket = NULL ;
}
connectionStatusChangedCallback ( ) ;
}
void RemoteInstrumentPart : : finishConnectingToServer ( ) {
if ( ! m_socket ) {
connToServerState = - 1 ;
connToServerConnecting = false ;
connectionStatusChangedCallback ( ) ;
return ;
}
if ( connToServerConnecting ) {
switch ( connToServerState ) {
case 0 :
if ( ! connToServerTimeoutTimer ) {
connToServerTimeoutTimer = new TQTimer ;
connToServerTimeoutTimer - > start ( SERVER_TIMEOUT_MS , TRUE ) ;
}
if ( ( m_socket - > state ( ) = = TQSocket : : Connecting ) | | ( m_socket - > state ( ) = = TQSocket : : HostLookup ) ) {
if ( ! connToServerTimeoutTimer - > isActive ( ) ) {
connToServerState = - 3 ;
connToServerConnecting = false ;
disconnectFromServer ( ) ;
KMessageBox : : error ( 0 , i18n ( " <qt>Unable to establish connection to remote server</qt> " ) , i18n ( " Connection Failed " ) ) ;
close ( ) ;
return ;
}
}
else {
if ( m_socket - > state ( ) = = TQSocket : : Connected ) {
printf ( " [DEBUG] Initial connection established... \n \r " ) ; fflush ( stdout ) ;
m_socket - > setDataTimeout ( SERVER_TIMEOUT_MS ) ;
m_socket - > setUsingKerberos ( true ) ;
connToServerState = 1 ;
connToServerTimeoutTimer - > stop ( ) ;
connToServerTimeoutTimer - > start ( SERVER_TIMEOUT_MS , TRUE ) ;
}
else {
connToServerState = - 1 ;
connToServerConnecting = false ;
disconnectFromServer ( ) ;
KMessageBox : : error ( 0 , i18n ( " <qt>Unable to establish connection to remote server</qt> " ) , i18n ( " Connection Failed " ) ) ;
close ( ) ;
return ;
}
}
break ;
case 1 :
if ( m_socket - > kerberosStatus ( ) = = TDEKerberosClientSocket : : KerberosInitializing ) {
// Do nothing
}
else {
if ( m_socket - > kerberosStatus ( ) ! = TDEKerberosClientSocket : : KerberosInUse ) {
// Try to get a valid ticket
if ( getNewTicket ( ) = = 0 ) {
// Retry connection if no obvious errors were detected
m_connectionTimer - > stop ( ) ;
if ( m_socket ) {
m_socket - > clearPendingData ( ) ;
m_socket - > close ( ) ;
delete m_socket ;
m_socket = NULL ;
}
connectToServer ( m_hostName ) ;
return ;
}
else {
connToServerState = - 1 ;
connToServerConnecting = false ;
disconnectFromServer ( ) ;
KMessageBox : : error ( 0 , i18n ( " <qt>Unable to establish Kerberos protocol with remote server<p>Please verify that you currently hold a valid Kerberos ticket</qt> " ) , i18n ( " Connection Failed " ) ) ;
close ( ) ;
return ;
}
}
else {
connToServerState = 2 ;
connToServerTimeoutTimer - > stop ( ) ;
connToServerTimeoutTimer - > start ( SERVER_TIMEOUT_MS , TRUE ) ;
}
}
break ;
case 2 :
// Connection established!
// Read magic number and proto version from server
if ( m_socket - > canReadFrame ( ) ) {
TQDataStream ds ( m_socket ) ;
ds . setPrintableData ( true ) ;
TQ_UINT32 magicnum ;
TQ_UINT32 protover ;
ds > > magicnum ;
ds > > protover ;
m_socket - > clearFrameTail ( ) ;
printf ( " [DEBUG] Got magic number %d and protocol version %d \n \r " , magicnum , protover ) ; fflush ( stdout ) ;
// Request connection to backend server
ds < < TQString ( " SERV " ) ;
m_socket - > writeEndOfFrame ( ) ;
ds < < m_clientLibraryName ;
m_socket - > writeEndOfFrame ( ) ;
connToServerState = 3 ;
connToServerTimeoutTimer - > stop ( ) ;
connToServerTimeoutTimer - > start ( SERVER_TIMEOUT_MS , TRUE ) ;
}
else {
if ( ( ! connToServerTimeoutTimer - > isActive ( ) ) | | ( m_socket - > state ( ) ! = TQSocket : : Connected ) ) {
connToServerState = - 1 ;
connToServerConnecting = false ;
disconnectFromServer ( ) ;
KMessageBox : : error ( 0 , i18n ( " <qt>Connection with remote server terminated<p>This may indicate that the requested service is not functional</qt> " ) , i18n ( " Connection Failed " ) ) ;
close ( ) ;
return ;
}
}
break ;
case 3 :
// Read response from server
if ( m_socket - > canReadFrame ( ) ) {
TQDataStream ds ( m_socket ) ;
ds . setPrintableData ( true ) ;
TQString response ;
ds > > response ;
m_socket - > clearFrameTail ( ) ;
if ( response = = " OK " ) {
connToServerState = 4 ;
connToServerConnecting = false ;
connectionFinishedCallback ( ) ;
return ;
}
else {
TQStringList errorStrings = textForServerError ( response ) ;
connToServerState = - 1 ;
connToServerConnecting = false ;
disconnectFromServer ( ) ;
KMessageBox : : error ( 0 , errorStrings [ 0 ] , errorStrings [ 1 ] ) ;
close ( ) ;
return ;
}
}
else {
if ( ( ! connToServerTimeoutTimer - > isActive ( ) ) | | ( m_socket - > state ( ) ! = TQSocket : : Connected ) ) {
connToServerState = - 1 ;
connToServerConnecting = false ;
disconnectFromServer ( ) ;
KMessageBox : : error ( 0 , i18n ( " <qt>Connection with remote server terminated<p>This may indicate that the requested service is not functional</qt> " ) , i18n ( " Connection Failed " ) ) ;
close ( ) ;
return ;
}
}
break ;
}
m_connectionTimer - > start ( 100 , TRUE ) ;
}
}
void RemoteInstrumentPart : : setMDIMainForm ( KMdiMainFrm * form ) {
m_mdiMainForm = form ;
}
KMdiMainFrm * RemoteInstrumentPart : : mdiMainForm ( ) {
return m_mdiMainForm ;
}
void RemoteInstrumentPart : : connectionFinishedCallback ( ) {
//
}
void RemoteInstrumentPart : : disconnectFromServerCallback ( ) {
//
}
void RemoteInstrumentPart : : connectionStatusChangedCallback ( ) {
//
}
}
TQDataStream & operator < < ( TQDataStream & s , const TQFloatArray & data ) {
TQ_UINT32 i ;
TQ_UINT32 count = data . count ( ) ;
s < < count ;
for ( i = 0 ; i < count ; i + + ) {
s < < data [ i ] ;
}
return s ;
}
TQDataStream & operator > > ( TQDataStream & s , TQFloatArray & data ) {
TQ_UINT32 i ;
TQ_UINT32 count ;
s > > count ;
data . resize ( count ) ;
for ( i = 0 ; i < count ; i + + ) {
s > > data [ i ] ;
}
return s ;
}
TQDataStream & operator < < ( TQDataStream & s , const TQDoubleArray & data ) {
TQ_UINT32 i ;
TQ_UINT32 count = data . count ( ) ;
s < < count ;
for ( i = 0 ; i < count ; i + + ) {
s < < data [ i ] ;
}
return s ;
}
TQDataStream & operator > > ( TQDataStream & s , TQDoubleArray & data ) {
TQ_UINT32 i ;
TQ_UINT32 count ;
s > > count ;
data . resize ( count ) ;
for ( i = 0 ; i < count ; i + + ) {
s > > data [ i ] ;
}
return s ;
}
bool operator = = ( const ServiceType & s1 , const ServiceType & s2 ) {
bool identical = true ;
if ( s1 . type ! = s2 . type ) {
identical = false ;
}
return identical ;
}
# ifndef QT_NO_DATASTREAM
/*!
\ relates ServiceType
Writes the ServiceType \ a str to the stream \ a s .
See also \ link datastreamformat . html Format of the TQDataStream operators \ endlink
*/
TQDataStream & operator < < ( TQDataStream & s , const ServiceType & st )
{
TQ_INT8 tempchar ;
s < < st . type ;
s < < st . name ;
s < < st . description ;
s < < st . clientLibrary ;
s < < st . version ;
tempchar = ( st . singleInstance ) ? 1 : 0 ;
s < < tempchar ;
return s ;
}
/*!
\ relates ServiceType
Reads a ServiceType from the stream \ a s into ServiceType \ a str .
See also \ link datastreamformat . html Format of the TQDataStream operators \ endlink
*/
TQDataStream & operator > > ( TQDataStream & s , ServiceType & st )
{
TQ_INT8 tempchar ;
s > > st . type ;
s > > st . name ;
s > > st . description ;
s > > st . clientLibrary ;
s > > st . version ;
s > > tempchar ;
st . singleInstance = ( tempchar ! = 0 ) ;
return s ;
}
/*!
\ relates StationType
Writes the StationType \ a str to the stream \ a s .
See also \ link datastreamformat . html Format of the TQDataStream operators \ endlink
*/
TQDataStream & operator < < ( TQDataStream & s , const StationType & st )
{
s < < st . id ;
s < < st . type ;
s < < st . services ;
s < < st . name ;
s < < st . description ;
return s ;
}
/*!
\ relates StationType
Reads a StationType from the stream \ a s into StationType \ a str .
See also \ link datastreamformat . html Format of the TQDataStream operators \ endlink
*/
TQDataStream & operator > > ( TQDataStream & s , StationType & st )
{
s > > st . id ;
s > > st . type ;
s > > st . services ;
s > > st . name ;
s > > st . description ;
return s ;
}
StationList : : StationList ( ) : TQValueList < StationType > ( ) {
//
}
StationList : : ~ StationList ( ) {
//
}
/*!
\ relates StationType
Finds a StationType with ID \ a id in this list .
*/
StationList : : iterator StationList : : findByID ( TQ_UINT32 id ) {
StationList : : iterator it ;
for ( it = begin ( ) ; it ! = end ( ) ; + + it ) {
if ( ( * it ) . id = = id ) {
break ;
}
}
return it ;
}
/*!
\ relates SensorType
Writes the SensorType \ a str to the stream \ a s .
See also \ link datastreamformat . html Format of the TQDataStream operators \ endlink
*/
TQDataStream & operator < < ( TQDataStream & s , const SensorType & st )
{
s < < st . index ;
s < < st . name ;
s < < st . description ;
s < < st . units ;
s < < st . min ;
s < < st . max ;
s < < st . mininterval ;
s < < st . nominalinterval ;
return s ;
}
/*!
\ relates SensorType
Reads a SensorType from the stream \ a s into SensorType \ a str .
See also \ link datastreamformat . html Format of the TQDataStream operators \ endlink
*/
TQDataStream & operator > > ( TQDataStream & s , SensorType & st )
{
s > > st . index ;
s > > st . name ;
s > > st . description ;
s > > st . units ;
s > > st . min ;
s > > st . max ;
s > > st . mininterval ;
s > > st . nominalinterval ;
return s ;
}
/*!
\ relates TerminalServiceStatusType
Writes the TerminalServiceStatusType \ a st to the stream \ a s .
See also \ link datastreamformat . html Format of the TQDataStream operators \ endlink
*/
TQDataStream & operator < < ( TQDataStream & s , const TerminalServiceStatusType & st )
{
s < < st . protocolVersion ;
s < < st . sessionID ;
s < < st . username ;
s < < st . serverName ;
s < < st . serverPID ;
s < < st . wmPID ;
s < < st . state ;
s < < st . display ;
s < < st . loginStamp ;
s < < st . activityStamp ;
return s ;
}
/*!
\ relates SensorType
Reads a TerminalServiceStatusType from the stream \ a s into TerminalServiceStatusType \ a st .
See also \ link datastreamformat . html Format of the TQDataStream operators \ endlink
*/
TQDataStream & operator > > ( TQDataStream & s , TerminalServiceStatusType & st )
{
s > > st . protocolVersion ;
s > > st . sessionID ;
s > > st . username ;
s > > st . serverName ;
s > > st . serverPID ;
s > > st . wmPID ;
s > > st . state ;
s > > st . display ;
s > > st . loginStamp ;
s > > st . activityStamp ;
return s ;
}
/*!
\ relates WorkspaceServiceStatusType
Writes the WorkspaceServiceStatusType \ a st to the stream \ a s .
See also \ link datastreamformat . html Format of the TQDataStream operators \ endlink
*/
TQDataStream & operator < < ( TQDataStream & s , const WorkspaceServiceStatusType & st )
{
s < < st . protocolVersion ;
s < < st . sessionID ;
s < < st . stationID ;
s < < st . username ;
s < < st . realmname ;
s < < st . serverID ;
s < < st . serviceID ;
s < < st . stationName ;
s < < st . loginStamp ;
s < < st . terminateStamp ;
return s ;
}
/*!
\ relates WorkspaceServiceStatusType
Reads a WorkspaceServiceStatusType from the stream \ a s into WorkspaceServiceStatusType \ a st .
See also \ link datastreamformat . html Format of the TQDataStream operators \ endlink
*/
TQDataStream & operator > > ( TQDataStream & s , WorkspaceServiceStatusType & st )
{
s > > st . protocolVersion ;
s > > st . sessionID ;
s > > st . stationID ;
s > > st . username ;
s > > st . realmname ;
s > > st . serverID ;
s > > st . serviceID ;
s > > st . stationName ;
s > > st . loginStamp ;
s > > st . terminateStamp ;
return s ;
}
/*!
\ relates TerminalServiceAuthGroupType
Writes the TerminalServiceAuthGroupType \ a agt to the stream \ a s .
See also \ link datastreamformat . html Format of the TQDataStream operators \ endlink
*/
TQDataStream & operator < < ( TQDataStream & s , const TerminalServiceAuthGroupType & agt )
{
s < < agt . protocolVersion ;
s < < agt . groupName ;
s < < agt . allowedServerNames ;
s < < agt . maximumActiveSessionCount ;
return s ;
}
/*!
\ relates TerminalServiceAuthGroupType
Reads a TerminalServiceAuthGroupType from the stream \ a s into TerminalServiceAuthGroupType \ a agt .
See also \ link datastreamformat . html Format of the TQDataStream operators \ endlink
*/
TQDataStream & operator > > ( TQDataStream & s , TerminalServiceAuthGroupType & agt )
{
s > > agt . protocolVersion ;
s > > agt . groupName ;
s > > agt . allowedServerNames ;
s > > agt . maximumActiveSessionCount ;
return s ;
}
/*!
\ relates WorkspaceServiceAuthGroupType
Writes the WorkspaceServiceAuthGroupType \ a agt to the stream \ a s .
See also \ link datastreamformat . html Format of the TQDataStream operators \ endlink
*/
TQDataStream & operator < < ( TQDataStream & s , const WorkspaceServiceAuthGroupType & agt )
{
s < < agt . protocolVersion ;
s < < agt . groupName ;
s < < agt . allowedStationIDs ;
return s ;
}
/*!
\ relates WorkspaceServiceAuthGroupType
Reads a WorkspaceServiceAuthGroupType from the stream \ a s into WorkspaceServiceAuthGroupType \ a agt .
See also \ link datastreamformat . html Format of the TQDataStream operators \ endlink
*/
TQDataStream & operator > > ( TQDataStream & s , WorkspaceServiceAuthGroupType & agt )
{
s > > agt . protocolVersion ;
s > > agt . groupName ;
s > > agt . allowedStationIDs ;
return s ;
}
# endif // QT_NO_DATASTREAM
TerminalServiceAuthGroupList : : TerminalServiceAuthGroupList ( ) : TQValueList < TerminalServiceAuthGroupType > ( ) {
//
}
TerminalServiceAuthGroupList : : ~ TerminalServiceAuthGroupList ( ) {
//
}
/*!
\ relates WorkspaceServiceAuthGroupType
Finds a WorkspaceServiceAuthGroupType with group name \ a name in this list .
*/
TerminalServiceAuthGroupList : : iterator TerminalServiceAuthGroupList : : findByName ( TQString name ) {
TerminalServiceAuthGroupList : : iterator it ;
for ( it = begin ( ) ; it ! = end ( ) ; + + it ) {
if ( ( * it ) . groupName = = name ) {
break ;
}
}
return it ;
}
WorkspaceServiceAuthGroupList : : WorkspaceServiceAuthGroupList ( ) : TQValueList < WorkspaceServiceAuthGroupType > ( ) {
//
}
WorkspaceServiceAuthGroupList : : ~ WorkspaceServiceAuthGroupList ( ) {
//
}
/*!
\ relates WorkspaceServiceAuthGroupType
Finds a WorkspaceServiceAuthGroupType with group name \ a name in this list .
*/
WorkspaceServiceAuthGroupList : : iterator WorkspaceServiceAuthGroupList : : findByName ( TQString name ) {
WorkspaceServiceAuthGroupList : : iterator it ;
for ( it = begin ( ) ; it ! = end ( ) ; + + it ) {
if ( ( * it ) . groupName = = name ) {
break ;
}
}
return it ;
}