summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2012-06-24 18:23:18 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2012-06-24 18:23:18 -0500
commite23898e185c0f639c6c6b98478b8b21f1ae83720 (patch)
treee5e2fd731ac59299cd68ed017d11f1ad9a9462d6
parent8dcfe72c396a6f0c4bafd2ed23ba52a475154ef2 (diff)
downloadulab-e23898e185c0f639c6c6b98478b8b21f1ae83720.tar.gz
ulab-e23898e185c0f639c6c6b98478b8b21f1ae83720.zip
Update protocol and implement LIST/BIND logic
-rw-r--r--clients/tde/configure.in2
-rw-r--r--clients/tde/src/Makefile.am2
-rw-r--r--clients/tde/src/app/Makefile.am4
-rw-r--r--clients/tde/src/app/remotemdi.cpp24
-rw-r--r--clients/tde/src/dialogs/Makefile.am4
-rw-r--r--clients/tde/src/dialogs/selectserverdlg.cpp115
-rw-r--r--clients/tde/src/dialogs/selectserverdlg.h47
-rw-r--r--clients/tde/src/dialogs/selectserverdlgbase.ui67
-rw-r--r--lib/libtdekrb/src/tdekrbserversocket.cpp6
-rw-r--r--lib/libtdekrb/src/tdekrbserversocket.h4
-rw-r--r--lib/libtqtrla/src/tqtrla.cpp50
-rw-r--r--lib/libtqtrla/src/tqtrla.h23
-rw-r--r--protocol.txt22
-rw-r--r--servers/auth_server_lin/src/auth_conn.cpp209
-rw-r--r--servers/auth_server_lin/src/auth_conn.h22
15 files changed, 563 insertions, 38 deletions
diff --git a/clients/tde/configure.in b/clients/tde/configure.in
index 425d6a8..472817b 100644
--- a/clients/tde/configure.in
+++ b/clients/tde/configure.in
@@ -84,7 +84,7 @@ AC_CONFIG_FILES([ po/Makefile ])
AC_CONFIG_FILES([ src/Makefile ])
AC_CONFIG_FILES([ src/app/Makefile ])
AC_CONFIG_FILES([ src/app/views/Makefile ])
-AC_CONFIG_FILES([ src/lib/Makefile ])
+AC_CONFIG_FILES([ src/dialogs/Makefile ])
AC_CONFIG_FILES([ src/part/Makefile ])
AC_CONFIG_FILES([ src/part/commanalyzer/Makefile ])
AC_CONFIG_FILES([ src/widgets/Makefile ])
diff --git a/clients/tde/src/Makefile.am b/clients/tde/src/Makefile.am
index 23fbb4d..c44e4ca 100644
--- a/clients/tde/src/Makefile.am
+++ b/clients/tde/src/Makefile.am
@@ -1,3 +1,3 @@
-SUBDIRS = widgets app part
+SUBDIRS = widgets dialogs app part
INCLUDES = $(all_includes)
METASOURCES = AUTO
diff --git a/clients/tde/src/app/Makefile.am b/clients/tde/src/app/Makefile.am
index 530c4c3..39cfe4c 100644
--- a/clients/tde/src/app/Makefile.am
+++ b/clients/tde/src/app/Makefile.am
@@ -1,9 +1,9 @@
SUBDIRS = views
-INCLUDES = $(all_includes) -I$(top_srcdir)/src $(KDE_INCLUDES)/tde
+INCLUDES = $(all_includes) -I$(top_srcdir)/src -I$(top_builddir)/src $(KDE_INCLUDES)/tde
METASOURCES = AUTO
# Application
bin_PROGRAMS = remote_laboratory_client
remote_laboratory_client_SOURCES = main.cpp remotemdi.cpp
-remote_laboratory_client_LDADD = ./views/libinstrumentview.la $(LIB_KPARTS) $(LIB_TDEUI)
+remote_laboratory_client_LDADD = ./views/libinstrumentview.la ../dialogs/libselectserverdlg.la $(LIB_KPARTS) $(LIB_TDEUI)
remote_laboratory_client_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_KIO) -lktexteditor -lkmdi -ltdekrbsocket -ltqtrla
diff --git a/clients/tde/src/app/remotemdi.cpp b/clients/tde/src/app/remotemdi.cpp
index 1df78df..9d40365 100644
--- a/clients/tde/src/app/remotemdi.cpp
+++ b/clients/tde/src/app/remotemdi.cpp
@@ -27,6 +27,7 @@ using namespace std;
#include <kkeydialog.h>
#include "views/instrumentview.h"
+#include "dialogs/selectserverdlg.h"
RemoteMDI::RemoteMDI()
: KMdiMainFrm(0, "RemoteMDI", KMdi::ChildframeMode), m_children(0), m_rsvSvrSocket(NULL)
@@ -165,6 +166,29 @@ void RemoteMDI::promptForStationType() {
ds >> slist;
printf("[RAJA DEBUG 200.2] Got list of stations, count is %d\n\r", slist.count()); fflush(stdout);
+
+ SelectServerDialog select(this, 0, slist);
+ const int ret = select.exec();
+ if (ret == KDialog::Accepted) {
+ TQString result;
+ ds << TQString("BIND");
+ ds << select.m_selectedStation;
+ ds >> result;
+ if (result == "OK") {
+ // Success, do nothing
+ }
+ else if (result == "ERRUNAVAL") {
+ KMessageBox::error(this, i18n("<qt>No stations of the specified type are currently available<p>Please try again later</qt>"), i18n("Insufficient Laboratory Resources"));
+ disconnectFromServer();
+ }
+ else {
+ KMessageBox::error(this, i18n("<qt>Unknown server error<p>Please reconnect and try again</qt>"), i18n("Internal Error"));
+ disconnectFromServer();
+ }
+ }
+ else {
+ disconnectFromServer();
+ }
}
void RemoteMDI::disconnectFromServer() {
diff --git a/clients/tde/src/dialogs/Makefile.am b/clients/tde/src/dialogs/Makefile.am
new file mode 100644
index 0000000..d66c5c7
--- /dev/null
+++ b/clients/tde/src/dialogs/Makefile.am
@@ -0,0 +1,4 @@
+INCLUDES = $(all_includes) -I$(top_srcdir)/src -I$(top_builddir)/src $(KDE_INCLUDES)/tde
+METASOURCES = AUTO
+noinst_LTLIBRARIES = libselectserverdlg.la
+libselectserverdlg_la_SOURCES = selectserverdlg.cpp selectserverdlgbase.ui \ No newline at end of file
diff --git a/clients/tde/src/dialogs/selectserverdlg.cpp b/clients/tde/src/dialogs/selectserverdlg.cpp
new file mode 100644
index 0000000..773ea98
--- /dev/null
+++ b/clients/tde/src/dialogs/selectserverdlg.cpp
@@ -0,0 +1,115 @@
+/***************************************************************************
+ * Copyright (C) 2012 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 <tqstringlist.h>
+#include <tqlabel.h>
+#include <tqmap.h>
+
+#include <kapplication.h>
+#include <ksimpleconfig.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kstandarddirs.h>
+#include <kiconloader.h>
+#include <dcopclient.h>
+#include <kprocess.h>
+#include <kcombobox.h>
+#include <kmessagebox.h>
+
+#include "selectserverdlg.h"
+#include "selectserverdlgbase.h"
+
+class Q_EXPORT StationTypeListViewItem : public TQListViewItem
+{
+ public:
+ StationTypeListViewItem(TQListView * parent) : TQListViewItem(parent) {}
+ StationTypeListViewItem(TQListViewItem * parent) : TQListViewItem(parent) {}
+ StationTypeListViewItem(TQListView * parent, TQListViewItem * after) : TQListViewItem(parent, after) {}
+ StationTypeListViewItem(TQListViewItem * parent, TQListViewItem * after) : TQListViewItem(parent, after) {}
+
+ StationTypeListViewItem(TQListView * parent, TQString s1, TQString s2 = TQString::null, TQString s3 = TQString::null, TQString s4 = TQString::null, TQString s5 = TQString::null, TQString s6 = TQString::null, TQString s7 = TQString::null, TQString s8 = TQString::null) : TQListViewItem(parent, s1, s2, s3, s4, s5, s6, s7, s8) {}
+ StationTypeListViewItem(TQListViewItem * parent, TQString s1, TQString s2 = TQString::null, TQString s3 = TQString::null, TQString s4 = TQString::null, TQString s5 = TQString::null, TQString s6 = TQString::null, TQString s7 = TQString::null, TQString s8 = TQString::null) : TQListViewItem(parent, s1, s2, s3, s4, s5, s6, s7, s8) {}
+
+ StationTypeListViewItem(TQListView * parent, TQListViewItem * after, TQString s1, TQString s2 = TQString::null, TQString s3 = TQString::null, TQString s4 = TQString::null, TQString s5 = TQString::null, TQString s6 = TQString::null, TQString s7 = TQString::null, TQString s8 = TQString::null) : TQListViewItem(parent, after, s1, s2, s3, s4, s5, s6, s7, s8) {}
+ StationTypeListViewItem(TQListViewItem * parent, TQListViewItem * after, TQString s1, TQString s2 = TQString::null, TQString s3 = TQString::null, TQString s4 = TQString::null, TQString s5 = TQString::null, TQString s6 = TQString::null, TQString s7 = TQString::null, TQString s8 = TQString::null) : TQListViewItem(parent, after, s1, s2, s3, s4, s5, s6, s7, s8) {}
+
+ ~StationTypeListViewItem() {}
+
+ public:
+ StationType m_stationType;
+};
+
+SelectServerDialog::SelectServerDialog(TQWidget* parent, const char* name, StationList sl)
+ : KDialogBase(parent, name, true, i18n("Workspace Selection"), Ok|Cancel, Ok, true), m_stationList(sl)
+{
+ unsigned int i;
+ unsigned int j;
+
+ m_base = new SelectServerDlg(this);
+
+ setMainWidget(m_base);
+
+ m_base->serverList->setAllColumnsShowFocus(true);
+ m_base->serverList->setFullWidth(true);
+
+ connect(m_base->serverList, TQT_SIGNAL(executed(TQListViewItem*)), this, TQT_SLOT(slotOk()));
+
+ for (i=0; i<m_stationList.count(); i++) {
+ StationType st = m_stationList[i];
+ TQString services;
+ for (j=0; j<st.services.count(); j++) {
+ ServiceType servicetype = st.services[j];
+ if (j > 0) {
+ services.append(", ");
+ }
+ services.append(servicetype.description);
+ }
+ bool newService = true;
+ TQListViewItemIterator it(m_base->serverList);
+ while (it.current()) {
+ StationTypeListViewItem* curItem = dynamic_cast<StationTypeListViewItem*>(it.current());
+ if (curItem) {
+ if (curItem->m_stationType.services == st.services) {
+ newService = false;
+ }
+ ++it;
+ }
+ }
+ if (newService) {
+ StationTypeListViewItem* item = new StationTypeListViewItem(m_base->serverList, services);
+ item->m_stationType = st;
+ }
+ }
+}
+
+void SelectServerDialog::slotOk() {
+ StationTypeListViewItem* curItem = dynamic_cast<StationTypeListViewItem*>(m_base->serverList->selectedItem());
+
+ if (!curItem) {
+ KMessageBox::error(this, i18n("You must select a workstation type to continue!"), i18n("Input Required"));
+ return;
+ }
+
+ m_selectedStation = curItem->m_stationType;
+
+ accept();
+}
+
+#include "selectserverdlg.moc"
diff --git a/clients/tde/src/dialogs/selectserverdlg.h b/clients/tde/src/dialogs/selectserverdlg.h
new file mode 100644
index 0000000..740f76b
--- /dev/null
+++ b/clients/tde/src/dialogs/selectserverdlg.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * Copyright (C) 2012 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. *
+ ***************************************************************************/
+
+#ifndef _SELECTSERVERDIALOG_H_
+#define _SELECTSERVERDIALOG_H_
+
+#include <kdialogbase.h>
+#include <kcombobox.h>
+
+#include <tqtrla.h>
+
+class SelectServerDlg;
+
+class SelectServerDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ SelectServerDialog(TQWidget* parent = 0, const char* name = 0, StationList sl = StationList());
+
+public slots:
+ void slotOk();
+
+public:
+ SelectServerDlg *m_base;
+ StationList m_stationList;
+ StationType m_selectedStation;
+};
+
+#endif \ No newline at end of file
diff --git a/clients/tde/src/dialogs/selectserverdlgbase.ui b/clients/tde/src/dialogs/selectserverdlgbase.ui
new file mode 100644
index 0000000..6be0eff
--- /dev/null
+++ b/clients/tde/src/dialogs/selectserverdlgbase.ui
@@ -0,0 +1,67 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>SelectServerDlg</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>SelectServerDlg</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="1" column="0" rowspan="1" colspan="1">
+ <property name="name">
+ <cstring>px_icon</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ <property name="indent">
+ <number>0</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="1" colspan="2">
+ <property name="name">
+ <cstring>prompt</cstring>
+ </property>
+ <property name="text">
+ <string>Please select the type of laboratory workspace you wish to use</string>
+ </property>
+ </widget>
+ <widget class="KListView" row="2" column="0" colspan="3">
+ <column>
+ <property name="text">
+ <string>Workspace Services</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizeable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>serverList</cstring>
+ </property>
+ <property name="rootIsDecorated">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="3" margin="6"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+</UI>
diff --git a/lib/libtdekrb/src/tdekrbserversocket.cpp b/lib/libtdekrb/src/tdekrbserversocket.cpp
index 33187bc..cd7fa88 100644
--- a/lib/libtdekrb/src/tdekrbserversocket.cpp
+++ b/lib/libtdekrb/src/tdekrbserversocket.cpp
@@ -460,7 +460,8 @@ int TDEKerberosServerSocket::initializeKerberosInterface() {
printf("[WARNING] Unable to determine authenticated username!\n\r");
}
else {
- printf("[DEBUG] Authenticated username: %s\n\r", data ? data : "(NULL)");
+ m_authenticatedUserName = data ? data : "(NULL)";
+ printf("[DEBUG] Authenticated username: %s\n\r", m_authenticatedUserName.ascii());
}
result = sasl_getprop(saslData->m_krbConnection, SASL_DEFUSERREALM, (const void **)&data);
@@ -468,7 +469,8 @@ int TDEKerberosServerSocket::initializeKerberosInterface() {
printf("[WARNING] Unable to determine authenticated realm!\n\r");
}
else {
- printf("[DEBUG] Authenticated realm: %s\n\r", data ? data : "(NULL)");
+ m_authenticatedRealmName = data ? data : "(NULL)";
+ printf("[DEBUG] Authenticated realm: %s\n\r", m_authenticatedRealmName.ascii());
}
result = sasl_getprop(saslData->m_krbConnection, SASL_SSF, (const void **)&ssf);
diff --git a/lib/libtdekrb/src/tdekrbserversocket.h b/lib/libtdekrb/src/tdekrbserversocket.h
index a41d14f..0b977f5 100644
--- a/lib/libtdekrb/src/tdekrbserversocket.h
+++ b/lib/libtdekrb/src/tdekrbserversocket.h
@@ -55,6 +55,10 @@ class TDEKerberosServerSocket : public TQSocket
int transmitEncryptedData(int fd, const char* readbuf, int cc);
int receiveEncryptedData(char *buf, int trunclen);
+ protected:
+ TQString m_authenticatedUserName;
+ TQString m_authenticatedRealmName;
+
private:
bool m_kerberosRequested;
TQString m_serviceName;
diff --git a/lib/libtqtrla/src/tqtrla.cpp b/lib/libtqtrla/src/tqtrla.cpp
index 9eb514a..71508dd 100644
--- a/lib/libtqtrla/src/tqtrla.cpp
+++ b/lib/libtqtrla/src/tqtrla.cpp
@@ -20,8 +20,50 @@
#include "tqtrla.h"
+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 )
+{
+ s << st.type;
+ s << st.name;
+ s << st.description;
+ 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 )
+{
+ s >> st.type;
+ s >> st.name;
+ s >> st.description;
+ return s;
+}
+
+/*!
\relates StationType
Writes the StationType \a str to the stream \a s.
@@ -31,11 +73,11 @@
TQDataStream &operator<<( TQDataStream &s, const StationType &st )
{
+ s << st.id;
s << st.type;
s << st.services;
+ s << st.name;
s << st.description;
- s << st.total_stations;
- s << st.stations_in_use;
return s;
}
@@ -49,11 +91,11 @@ TQDataStream &operator<<( TQDataStream &s, const StationType &st )
TQDataStream &operator>>( TQDataStream &s, StationType &st )
{
+ s >> st.id;
s >> st.type;
s >> st.services;
+ s >> st.name;
s >> st.description;
- s >> st.total_stations;
- s >> st.stations_in_use;
return s;
}
#endif // QT_NO_DATASTREAM
diff --git a/lib/libtqtrla/src/tqtrla.h b/lib/libtqtrla/src/tqtrla.h
index 9da1d93..2a6228b 100644
--- a/lib/libtqtrla/src/tqtrla.h
+++ b/lib/libtqtrla/src/tqtrla.h
@@ -23,14 +23,31 @@
#include <tqobject.h>
+class ServiceType
+{
+ public:
+ TQ_UINT32 type;
+ TQString name;
+ TQString description;
+};
+
+#ifndef QT_NO_DATASTREAM
+Q_EXPORT TQDataStream &operator<<(TQDataStream &, const ServiceType &);
+Q_EXPORT TQDataStream &operator>>(TQDataStream &, ServiceType &);
+#endif
+
+typedef TQValueList<ServiceType> ServiceList;
+
+Q_EXPORT bool operator==(const ServiceType &s1, const ServiceType &s2);
+
class StationType
{
public:
+ TQ_UINT32 id;
TQ_UINT32 type;
- TQValueList<TQ_UINT32> services;
+ ServiceList services;
+ TQString name;
TQString description;
- TQ_UINT32 total_stations;
- TQ_UINT32 stations_in_use;
};
#ifndef QT_NO_DATASTREAM
diff --git a/protocol.txt b/protocol.txt
index 8fe08f1..184906e 100644
--- a/protocol.txt
+++ b/protocol.txt
@@ -27,8 +27,8 @@ The client may terminate the connection at any time, or provide invalid data to
After initial negotiation, the server must enter command mode. In this mode the server expects to receive a command string. The following commands are currently supported:
LIST
-BIND <TQ_UINT32 'Type ID'>
-SERV <TQ_UINT32 'Service ID'>
+BIND <StationType 'Type ID'>
+SERV <ServiceType 'Service ID'>
QUIT
If an invalid command is specified, the server should respond with a string containing the case-sensitive text "ERRINVCMD".
@@ -38,25 +38,23 @@ The expected actions and/or data transmission/reception on receipt of a valid co
LIST:
Returns a list of available laboratory stations
The server should return a TQValueList<StationType>, where StationType consists of the following types for each laboratory station:
-TQ_UINT32 Type ID
-TQValueList<TQ_UINT32> Service IDs
-TQString Description
-TQ_UINT32 Total station count of this type
-TQ_UINT32 Number of stations of this type in use
+<this is still in flux, see tqtrla.h for current data structure(s)>
-Descriptions should be constructed from station service type flags as known to the master server, and multiple stations with identical resources should be consolidated to one type ID and description. Type IDs do not need to be universally unique, but must remain constant for a given connection after a LIST command. Subsequent commands may alter the Type ID mappings.
+Descriptions should be constructed from station service type flags as known to the master server, and multiple stations with identical resources should be consolidated to one station type ID and description. Station type IDs do not need to be universally unique, but must not conflict with other station type IDs. Subsequent commands may alter the station type ID mappings.
-BIND <TQ_UINT32 'Type ID'>:
+BIND <StationType 'Type ID'>:
Connects to a specified laboratory station
-If a station with the specified Type ID is available, the server must mark that station as in use by the authenticated user, must return the case-sensitive text "OK", and should block all commands other than QUIT. If a station with the specified Type ID is not available, the server must respond with a string containing the case-sensitive text "ERRUNAVAL" and must re-enter command mode.
+If a station with the specified Service ID list is available, the server must mark that station as in use by the authenticated user, must return the case-sensitive text "OK", and should block all commands other than QUIT. If a station with the specified Service ID list is not available, the server must respond with a string containing the case-sensitive text "ERRUNAVAL" and must re-enter command mode.
-Example: BIND 5
+Example: BIND
+ StationType
SERV <TQ_UINT32 'Service ID'>
Requests a connection to the specified backend server on the laboratory station
If BIND was previously commanded on this connection, the server must respond with a string containing the case-sensitive text "ERRINVCMD". If no station has been reserved for this user via a call to BIND on an active connection, the server must respond with a string containing the case-sensitive text "ERRNOCONN". If the backend server is not available, i.e. a connection attempt or attempts have failed to establish a connection, the server should respond with the string "ERRNOTAVL" and must close the client connection. Otherwise, the server must return a string containing the case-sensitive text "OK" and then immediately enter binary pass-through mode between the backend server and the client.
-Example: SERV 4000
+Example: SERV
+ ServiceType
QUIT:
Gracefully terminates the connection.
diff --git a/servers/auth_server_lin/src/auth_conn.cpp b/servers/auth_server_lin/src/auth_conn.cpp
index 396218a..28b79fb 100644
--- a/servers/auth_server_lin/src/auth_conn.cpp
+++ b/servers/auth_server_lin/src/auth_conn.cpp
@@ -22,6 +22,8 @@
#include <stdlib.h>
+#include <klocale.h>
+
#include "auth_conn.h"
/* exception handling */
@@ -36,17 +38,40 @@ struct exit_exception {
instance of this class.
*/
AuthSocket::AuthSocket(int sock, TQObject *parent, const char *name) :
- TDEKerberosServerSocket( parent, name ), m_criticalSection(0) {
+ TDEKerberosServerSocket(parent, name), m_criticalSection(0), m_stationID(-1), m_config(static_cast<AuthServer*>(parent)->m_config), m_database(NULL), m_databaseStationsCursor(NULL) {
setServiceName("remotefpga");
line = 0;
connect(this, SIGNAL(connectionClosed()), SLOT(connectionClosedHandler()));
- setSocket( sock );
+ setSocket(sock);
+
+ if (connectToDatabase() != 0) {
+ exit(1);
+ }
}
AuthSocket::~AuthSocket() {
- //
+ if (m_databaseStationsCursor) {
+ delete m_databaseStationsCursor;
+ }
+ if (m_databaseServicesCursor) {
+ delete m_databaseServicesCursor;
+ }
+ if (m_databaseServiceTypesCursor) {
+ delete m_databaseServiceTypesCursor;
+ }
+ if (m_databasePermissionsCursor) {
+ delete m_databasePermissionsCursor;
+ }
+ if (m_databaseActivityCursor) {
+ delete m_databaseActivityCursor;
+ }
+
+ if (m_database) {
+ m_database->close();
+ delete m_database;
+ }
}
void AuthSocket::close() {
@@ -56,6 +81,14 @@ void AuthSocket::close() {
void AuthSocket::connectionClosedHandler() {
printf("[DEBUG] Connection from %s closed\n\r", m_remoteHost.ascii());
+
+ // 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);
+ }
+
if (m_criticalSection > 0) {
throw exit_exception(-1);
}
@@ -85,15 +118,92 @@ int AuthSocket::enterCommandLoop() {
while (state() == TQSocket::Connected) {
ds >> command;
-printf("[RAJA DEBUG 500.0] Got command %s\n\r", command.ascii()); fflush(stdout);
- if (command == "LIST") {
- // Send list of available servers...
- // RAJA FIXME
- StationList slist;
- ds << slist;
- }
- else {
- ds << "ERRINVCMD";
+ if (command != "") {
+ printf("[DEBUG] Got command %s from user %s@%s\n\r", command.ascii(), m_authenticatedUserName.ascii(), m_authenticatedRealmName.ascii()); fflush(stdout);
+ if (command == "LIST") {
+ // Send list of available servers...
+ m_slist.clear();
+
+ // Get all stations from the database
+ m_databaseStationsCursor->select();
+ while (m_databaseStationsCursor->next()) {
+ bool authorized = false;
+ bool in_use = false;
+
+ m_databasePermissionsCursor->select(TQString("station=%1").arg(m_databaseStationsCursor->value("pk").toInt()));
+ while (m_databasePermissionsCursor->next()) {
+ if (m_databasePermissionsCursor->value("username").toString() == m_authenticatedUserName) {
+ authorized = true;
+ }
+ }
+ m_databaseActivityCursor->select(TQString("station=%1").arg(m_databaseStationsCursor->value("pk").toInt()));
+ while (m_databaseActivityCursor->next()) {
+ if (m_databaseActivityCursor->value("username").toString() != "") {
+ in_use = true;
+ }
+ }
+
+ if ((authorized) && (!in_use)) {
+ StationType st;
+ st.id = m_databaseStationsCursor->value("pk").toInt();
+ st.name = m_databaseStationsCursor->value("name").toString();
+ st.description = m_databaseStationsCursor->value("description").toString();
+ m_databaseServicesCursor->select(TQString("station=%1").arg(m_databaseStationsCursor->value("pk").toInt()));
+ while (m_databaseServicesCursor->next()) {
+ m_databaseServiceTypesCursor->select(TQString("serviceid=%1").arg(m_databaseServicesCursor->value("servicetype").toInt()));
+ ServiceType svt;
+ if (m_databaseServiceTypesCursor->next()) {
+ svt.name = m_databaseServiceTypesCursor->value("name").toString();
+ svt.description = m_databaseServiceTypesCursor->value("description").toString();
+ }
+ if (svt.name == "") {
+ svt.name = i18n("<unknown>");
+ }
+ if (svt.description == "") {
+ svt.description = i18n("<unknown>");
+ }
+ st.services.append(svt);
+ }
+
+ m_slist.append(st);
+ }
+ }
+
+ ds << m_slist;
+ }
+ else if (command == "BIND") {
+ // Get desired Station Type from client
+ StationType st;
+ ds >> st;
+
+ // Attempt to bind to station matching desired Service Type list...
+ m_stationID = -1;
+
+ for (StationList::Iterator it(m_slist.begin()); it != m_slist.end(); ++it) {
+ if ((*it).services == st.services) {
+ m_stationID = (*it).id;
+ break;
+ }
+ }
+
+ if (m_stationID < 0) {
+ ds << TQString("ERRUNAVAL");
+ }
+ else {
+ // Update database
+ 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());
+ m_databaseActivityCursor->insert();
+
+ ds << TQString("OK");
+ }
+ }
+ else {
+ ds << "ERRINVCMD";
+ }
}
tqApp->processEvents();
}
@@ -108,6 +218,75 @@ printf("[RAJA DEBUG 500.0] Got command %s\n\r", command.ascii()); fflush(stdout)
}
+int AuthSocket::connectToDatabase() {
+ if (m_database) {
+ return -2;
+ }
+
+ m_config->setGroup("Database");
+
+ m_database = TQSqlDatabase::addDatabase(m_config->readEntry("driver"));
+ m_database->setDatabaseName(m_config->readEntry("database"));
+ m_database->setUserName(m_config->readEntry("username"));
+ m_database->setPassword(m_config->readEntry("password"));
+ m_database->setHostName(m_config->readEntry("server"));
+
+ if(!m_database->open()) {
+ printf("[ERROR] Failed to connect to control database on server '%s' [%s]\n\r", m_database->hostName().ascii(), m_database->lastError().text().ascii()); fflush(stdout);
+ delete m_database;
+ m_database = NULL;
+ return -1;
+ }
+
+ if (!m_database->tables().contains("stations")) {
+ m_database->close();
+ printf("[ERROR] Control database '%s' on '%s' does not contain the required 'stations' table\n\r", m_database->databaseName().ascii(), m_database->hostName().ascii()); fflush(stdout);
+ delete m_database;
+ m_database = NULL;
+ return -1;
+ }
+
+ if (!m_database->tables().contains("services")) {
+ m_database->close();
+ printf("[ERROR] Control database '%s' on '%s' does not contain the required 'services' table\n\r", m_database->databaseName().ascii(), m_database->hostName().ascii()); fflush(stdout);
+ delete m_database;
+ m_database = NULL;
+ return -1;
+ }
+
+ if (!m_database->tables().contains("servicetypes")) {
+ m_database->close();
+ printf("[ERROR] Control database '%s' on '%s' does not contain the required 'servicetypes' table\n\r", m_database->databaseName().ascii(), m_database->hostName().ascii()); fflush(stdout);
+ delete m_database;
+ m_database = NULL;
+ return -1;
+ }
+
+ if (!m_database->tables().contains("permissions")) {
+ m_database->close();
+ printf("[ERROR] Control database '%s' on '%s' does not contain the required 'permissions' table\n\r", m_database->databaseName().ascii(), m_database->hostName().ascii()); fflush(stdout);
+ delete m_database;
+ m_database = NULL;
+ return -1;
+ }
+
+ if (!m_database->tables().contains("activity")) {
+ m_database->close();
+ printf("[ERROR] Control database '%s' on '%s' does not contain the required 'activity' table\n\r", m_database->databaseName().ascii(), m_database->hostName().ascii()); fflush(stdout);
+ delete m_database;
+ m_database = NULL;
+ return -1;
+ }
+
+ m_databaseStationsCursor = new TQSqlCursor("stations");
+ m_databaseServicesCursor = new TQSqlCursor("services");
+ m_databaseServiceTypesCursor = new TQSqlCursor("servicetypes");
+ m_databasePermissionsCursor = new TQSqlCursor("permissions");
+ m_databaseActivityCursor = new TQSqlCursor("activity");
+
+ return 0;
+}
+
/*
The AuthServer class handles new connections to the server. For every
client that connects, it creates a new AuthSocket -- that instance is now
@@ -116,14 +295,18 @@ printf("[RAJA DEBUG 500.0] Got command %s\n\r", command.ascii()); fflush(stdout)
AuthServer::AuthServer(TQObject* parent) :
TQServerSocket( 4004, 1, parent ) {
+ m_config = new KSimpleConfig("remotefpga_authserver.conf", false);
+
if ( !ok() ) {
printf("[ERROR] Failed to bind to port 4004\n\r");
exit(1);
}
+
+ printf("[INFO] Server started on port 4004\n\r"); fflush(stdout);
}
AuthServer::~AuthServer() {
- //
+ delete m_config;
}
void AuthServer::newConnection(int socket) {
diff --git a/servers/auth_server_lin/src/auth_conn.h b/servers/auth_server_lin/src/auth_conn.h
index 3ce82e2..710b4c0 100644
--- a/servers/auth_server_lin/src/auth_conn.h
+++ b/servers/auth_server_lin/src/auth_conn.h
@@ -28,6 +28,10 @@
#include <tqlabel.h>
#include <tqpushbutton.h>
#include <tqtextstream.h>
+#include <tqsqldatabase.h>
+#include <tqsqlcursor.h>
+
+#include <ksimpleconfig.h>
#include <tdekrbserversocket.h>
@@ -50,12 +54,24 @@ class AuthSocket : public TDEKerberosServerSocket
int enterCommandLoop();
private slots:
+ int connectToDatabase();
void connectionClosedHandler();
private:
int line;
int m_criticalSection;
TQString m_remoteHost;
+ int m_stationID;
+
+ KSimpleConfig* m_config;
+ TQSqlDatabase* m_database;
+ TQSqlCursor* m_databaseStationsCursor;
+ TQSqlCursor* m_databaseServicesCursor;
+ TQSqlCursor* m_databaseServiceTypesCursor;
+ TQSqlCursor* m_databasePermissionsCursor;
+ TQSqlCursor* m_databaseActivityCursor;
+
+ StationList m_slist;
friend class AuthServer;
};
@@ -63,6 +79,7 @@ class AuthSocket : public TDEKerberosServerSocket
class AuthServer : public TQServerSocket
{
Q_OBJECT
+
public:
AuthServer(TQObject* parent=0);
~AuthServer();
@@ -72,4 +89,9 @@ class AuthServer : public TQServerSocket
signals:
void newConnect(AuthSocket*);
+ private:
+ KSimpleConfig* m_config;
+
+ friend class AuthSocket;
+
}; \ No newline at end of file