/*************************************************************************** * Copyright (C) 2012-2019 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 #include #include #include #include #include #include #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(parent()); if (parentWidget) { parentWidget->setMinimumSize(0, 0); parentWidget->setMaximumSize(TQWIDGETSIZE_MAX, TQWIDGETSIZE_MAX); } } emit(usingFixedSizeChanged(fixed)); } TQPtrList RemoteInstrumentPart::menuActionList() { return TQPtrList(); } void RemoteInstrumentPart::resize(TQSize size) { TQWidget* parentWidget = dynamic_cast(parent()); if (parentWidget) { if (m_fixedSize) { parentWidget->setFixedSize(size); } else { parentWidget->resize(size); } } } void RemoteInstrumentPart::close() { TQWidget* parentWidget = dynamic_cast(parent()); if (parentWidget) { parentWidget->close(); } } int RemoteInstrumentPart::getNewTicket() { int ret = -1; TQWidget* parentWidget = dynamic_cast(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("Failed to obtain ticket

%1").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("Unable to establish connection with backend server

Please verify that you are currently connected to a workspace")); ret.append(i18n("Connection Failed")); } else if (shortError == "ERRNOTAVL") { ret.append(i18n("The backend server is not available at this time

Please try a different workspace, or try again later")); ret.append(i18n("Connection Failed")); } else if (shortError == "ERRNOSERV") { ret.append(i18n("The active laboratory workspace does not support the requested service")); ret.append(i18n("Service Unavailable")); } else { ret.append(i18n("Unable to establish connection with remote server")); 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("Unable to establish connection to remote server"), 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("Unable to establish connection to remote server"), 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("Unable to establish Kerberos protocol with remote server

Please verify that you currently hold a valid Kerberos ticket"), 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("Connection with remote server terminated

This may indicate that the requested service is not functional"), 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("Connection with remote server terminated

This may indicate that the requested service is not functional"), 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>( TQDataStream &s, TQFloatArray &data ) { TQ_UINT32 i; TQ_UINT32 count; s >> count; data.resize(count); for (i=0; i> 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>( TQDataStream &s, TQDoubleArray &data ) { TQ_UINT32 i; TQ_UINT32 count; s >> count; data.resize(count); for (i=0; i> 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() { // } 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() { // } 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() { // } 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; }