Convert servers to cooperative multitasking

master
Timothy Pearson 12 years ago
parent 8392c61105
commit 65ea633f47

@ -343,7 +343,12 @@ void RemoteMDI::childWindowCloseRequest(KMdiChildView *pWnd) {
// Give the child a chance to finish what it was doing and exit cleanly (i.e. without crashing!)
iview->closeConnections();
iview->hide();
KMdiMainFrm::childWindowCloseRequest(pWnd);
// RAJA FIXME
// Executing KMdiMainFrm::childWindowCloseRequest(pWnd) here will probably cause a crash
// We need to call this AFTER control has been returned to the main event loop at least once
// This is related to my lack of proper returning to the event loop, which MUST BE FIXED
// KMdiMainFrm::childWindowCloseRequest(pWnd); // RAJA UNCOMMENT ME
}
}
@ -363,11 +368,11 @@ void RemoteMDI::closeSpecifiedWindow(KMdiChildView *window) {
if (window) {
// Notify the status bar of the removal of the window
statusBar()->message(i18n("%1 removed").arg(window->tabCaption()));
// We could also call removeWindowFromMdi, but it doesn't delete the
// pointer. This way, we're sure that the view will get deleted.
closeWindow(window);
// Synchronize combo box
if (m_pCurrentWindow) {
currentChanged(m_pCurrentWindow);

@ -15,6 +15,7 @@ InstrumentView::InstrumentView(const TQString &library, TQWidget *parentWidget,
: KMdiChildView(parentWidget, name, f)
, m_libraryName(library)
, m_instrumentPart( 0 )
, m_canary( NULL )
{
init();
}
@ -23,12 +24,15 @@ InstrumentView::InstrumentView(const TQString &library, const TQString &caption,
: KMdiChildView(caption, parentWidget, name, f)
, m_libraryName(library)
, m_instrumentPart( 0 )
, m_canary( NULL )
{
init();
}
InstrumentView::~InstrumentView() {
//
if (m_canary) {
*m_canary = true;
}
}
void InstrumentView::init() {
@ -44,10 +48,13 @@ void InstrumentView::init() {
}
bool InstrumentView::queryExit() {
if( !m_instrumentPart ) //apparently std::exit() still calls this function, and abort() causes a crash..
if (!m_instrumentPart) { // apparently std::exit() still calls this function, and abort() causes a crash..
return true;
}
printf("[RAJA DEBUG 700.0] In InstrumentView::queryExit\n\r"); fflush(stdout);
m_instrumentPart->closeURL();
printf("[RAJA DEBUG 700.1] In InstrumentView::queryExit\n\r"); fflush(stdout);
return true;
}
@ -57,11 +64,24 @@ void InstrumentView::closeConnections() {
}
void InstrumentView::connectServer(TQString server) {
if (!m_canary) {
m_canary = new bool;
*m_canary = false;
}
bool* canary = m_canary;
if (m_instrumentPart) {
if (m_instrumentPart->openURL(KURL(server))) {
close();
if (m_instrumentPart->openURL(KURL(server))) { // This can call processEvents, therefore this object may not exist when it returns!
if (*canary == true) {
delete canary;
return;
}
TQTimer::singleShot(0, this, SLOT(close()));
}
}
delete m_canary;
m_canary = NULL;
}
/**********************************************

@ -26,14 +26,15 @@ class InstrumentView : public KMdiChildView
void closeConnections();
protected:
virtual void saveProperties( KConfig * );
virtual void readProperties( KConfig * );
virtual void saveProperties(KConfig *);
virtual void readProperties(KConfig *);
virtual bool queryExit();
private:
void init();
TQString m_libraryName;
RemoteLab::InstrumentPart *m_instrumentPart;
bool* m_canary;
};
} // namespace RemoteLab

@ -46,12 +46,6 @@
#include "floatspinbox.h"
#include "layout.h"
/* exception handling */
struct exit_exception {
int c;
exit_exception(int c):c(c) { }
};
namespace RemoteLab {
typedef KParts::GenericFactory<RemoteLab::FPGAViewPart> Factory;
@ -82,7 +76,7 @@ FPGAViewPart::FPGAViewPart(TQWidget *parentWidget, const char *widgetName, TQObj
FPGAViewPart::~FPGAViewPart() {
if (m_connectionMutex->locked()) {
throw exit_exception(-1);
printf("[WARNING] Exiting when data transfer still in progress!\n\r"); fflush(stdout);
}
if (m_socket) {
@ -95,11 +89,14 @@ FPGAViewPart::~FPGAViewPart() {
}
void FPGAViewPart::processLockouts() {
if ((m_socket) && (m_socket->state() == TQSocket::Connected)) {
widget()->setEnabled(true);
}
else {
widget()->setEnabled(false);
TQWidget* mainWidget = widget();
if (mainWidget) {
if ((m_socket) && (m_socket->state() == TQSocket::Connected)) {
mainWidget->setEnabled(true);
}
else {
mainWidget->setEnabled(false);
}
}
}
@ -114,22 +111,27 @@ void FPGAViewPart::postInit() {
bool FPGAViewPart::openURL(const KURL &url) {
int ret;
ret = connectToServer(url.url());
// RAJA FIXME
// Need canary?
processLockouts();
return (ret != 0);
}
bool FPGAViewPart::closeURL() {
if (m_connectionMutex->locked()) {
throw exit_exception(-1);
}
printf("[RAJA DEBUG 710.0] In FPGAViewPart::closeURL\n\r"); fflush(stdout);
printf("[RAJA DEBUG 710.1] In FPGAViewPart::closeURL\n\r"); fflush(stdout);
if (m_socket) {
m_socket->clearPendingData();
printf("[RAJA DEBUG 710.2] In FPGAViewPart::closeURL\n\r"); fflush(stdout);
m_socket->close();
delete m_socket;
printf("[RAJA DEBUG 710.3] In FPGAViewPart::closeURL\n\r"); fflush(stdout);
m_socket->deleteLater();
printf("[RAJA DEBUG 710.4] In FPGAViewPart::closeURL\n\r"); fflush(stdout);
m_socket = NULL;
printf("[RAJA DEBUG 710.5] In FPGAViewPart::closeURL\n\r"); fflush(stdout);
}
printf("[RAJA DEBUG 710.6] In FPGAViewPart::closeURL\n\r"); fflush(stdout);
processLockouts();
m_url = KURL();
@ -138,6 +140,11 @@ bool FPGAViewPart::closeURL() {
}
int FPGAViewPart::connectToServer(TQString server) {
printf("[RAJA DEBUG 200.0] In FPGAViewPart::connectToServer\n\r"); fflush(stdout);
if (m_socket) {
printf("[RAJA DEBUG 200.1] In FPGAViewPart::connectToServer TRIED TO CONNECT TWICE!!!\n\r"); fflush(stdout);
return -1;
}
if (!m_socket) {
m_socket = new TDEKerberosClientSocket(this);
}
@ -146,63 +153,61 @@ int FPGAViewPart::connectToServer(TQString server) {
m_socket->connectToHost(server, 4004);
while ((m_socket->state() != TQSocket::Connected) && (m_socket->state() != TQSocket::Idle)) {
tqApp->eventLoop()->processEvents(TQEventLoop::AllEvents);
if (!m_socket) return -1; // Any entry into the event loop could end up deleting the socket object depending on user interaction
}
if (m_socket->state() != TQSocket::Connected) {
return -1;
}
if (m_socket->setUsingKerberos(true) != 0) {
if (!m_socket) return -1; // Any entry into the event loop could end up deleting the socket object depending on user interaction
m_socket->close();
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"));
return -1;
}
connect(m_socket, SIGNAL(connectionClosed()), this, SLOT(connectionClosed()));
try {
m_connectionMutex->lock();
TQString response;
TQDataStream ds(m_socket);
// Read magic number and proto version from server
TQ_UINT32 magicnum;
TQ_UINT32 protover;
ds >> magicnum;
ds >> protover;
printf("[DEBUG] Got magic number %d and protocol version %d\n\r", magicnum, protover); fflush(stdout);
// Request connection to backend server
ds << TQString("SERV");
ds << TQString(CLIENT_LIBRARY);
ds >> response;
printf("[RAJA DEBUG 400.0] Got '%s' from the server\n\r", response.ascii()); fflush(stdout);
if (response == "OK") {
m_connectionMutex->unlock();
return 0;
}
else if (response == "ERRNOCONN") {
KMessageBox::error(0, i18n("<qt>Unable to establish connection with backend server<p>Please verify that you are currently connected to a workspace</qt>"), i18n("Connection Failed"));
m_connectionMutex->unlock();
return -1;
}
else if (response == "ERRNOTAVL") {
KMessageBox::error(0, i18n("<qt>The backend server is not available at this time<p>Please try a different workspace, or try again later</qt>"), i18n("Connection Failed"));
m_connectionMutex->unlock();
return -1;
}
else if (response == "ERRNOSERV") {
KMessageBox::error(0, i18n("<qt>The active laboratory workspace does not support the requested service</qt>"), i18n("Service Unavailable"));
m_connectionMutex->unlock();
return -1;
}
else {
KMessageBox::error(0, i18n("<qt>Unable to establish connection with remote server</qt>"), i18n("Connection Failed"));
m_connectionMutex->unlock();
return -1;
}
// Kerberos connection established!
m_connectionMutex->lock();
TQString response;
TQDataStream ds(m_socket);
// Read magic number and proto version from server
TQ_UINT32 magicnum;
TQ_UINT32 protover;
ds >> magicnum;
ds >> protover;
printf("[DEBUG] Got magic number %d and protocol version %d\n\r", magicnum, protover); fflush(stdout);
// Request connection to backend server
ds << TQString("SERV");
ds << TQString(CLIENT_LIBRARY);
ds >> response;
printf("[RAJA DEBUG 400.0] Got '%s' from the server\n\r", response.ascii()); fflush(stdout);
if (response == "OK") {
m_connectionMutex->unlock();
return 0;
}
catch (exit_exception& e) {
else if (response == "ERRNOCONN") {
KMessageBox::error(0, i18n("<qt>Unable to establish connection with backend server<p>Please verify that you are currently connected to a workspace</qt>"), i18n("Connection Failed"));
m_connectionMutex->unlock();
return -1;
}
else if (response == "ERRNOTAVL") {
KMessageBox::error(0, i18n("<qt>The backend server is not available at this time<p>Please try a different workspace, or try again later</qt>"), i18n("Connection Failed"));
m_connectionMutex->unlock();
return -1;
}
else if (response == "ERRNOSERV") {
KMessageBox::error(0, i18n("<qt>The active laboratory workspace does not support the requested service</qt>"), i18n("Service Unavailable"));
m_connectionMutex->unlock();
return -1;
}
else {
KMessageBox::error(0, i18n("<qt>Unable to establish connection with remote server</qt>"), i18n("Connection Failed"));
m_connectionMutex->unlock();
return -1;
}
m_connectionMutex->unlock();
return 0;
}
void FPGAViewPart::updateDisplay() {

@ -32,6 +32,20 @@
#define NET_SEC_BUF_SIZE (2048)
// When control comes back from processEvents() my object may be completely gone! This attempts to mitigate the risk
#define SAFELY_PROCESS_EVENTS if (!m_canary) { \
m_canary = new bool; \
*m_canary = false; \
} \
bool* canary = m_canary; \
tqApp->processEvents(); \
if (*canary == true) { \
delete canary; \
return -1; \
} \
delete m_canary; \
m_canary = NULL;
/* exception handling */
struct exit_exception {
int c;
@ -79,7 +93,7 @@ static int logSASLMessages(void *context __attribute__((unused)), int priority,
return SASL_OK;
}
TDEKerberosClientSocket::TDEKerberosClientSocket(TQObject *parent, const char *name) : TQSocket(parent, name), m_kerberosRequested(false), m_criticalSection(0), m_bufferLength(0), m_negotiatedMaxBufferSize(NET_SEC_BUF_SIZE) {
TDEKerberosClientSocket::TDEKerberosClientSocket(TQObject *parent, const char *name) : TQSocket(parent, name), m_kerberosRequested(false), m_criticalSection(0), m_bufferLength(0), m_canary(NULL), m_negotiatedMaxBufferSize(NET_SEC_BUF_SIZE) {
saslData = new SASLDataPrivate;
saslData->m_krbConnection = NULL;
m_buffer = new TQBuffer();
@ -87,6 +101,9 @@ TDEKerberosClientSocket::TDEKerberosClientSocket(TQObject *parent, const char *n
}
TDEKerberosClientSocket::~TDEKerberosClientSocket() {
if (m_canary) {
*m_canary = true;
}
m_buffer->close();
delete m_buffer;
delete saslData;
@ -102,9 +119,6 @@ bool TDEKerberosClientSocket::open(int mode) {
void TDEKerberosClientSocket::close() {
TQSocket::close();
if (m_criticalSection > 0) {
throw exit_exception(-1);
}
}
void TDEKerberosClientSocket::flush() {
@ -221,6 +235,10 @@ TQ_LONG TDEKerberosClientSocket::readBlock(char *data, TQ_ULONG maxlen) {
int wrlen;
char* buf = (char*)malloc(m_negotiatedMaxBufferSize);
reclen = receiveEncryptedData(buf, m_negotiatedMaxBufferSize);
if (reclen < 0) {
free(buf);
return -1;
}
if (reclen > 0) {
m_buffer->at(m_bufferLength);
wrlen = m_buffer->writeBlock(buf, reclen);
@ -278,6 +296,10 @@ TQ_LONG TDEKerberosClientSocket::readLine(char *data, TQ_ULONG maxlen) {
int wrlen;
char* buf = (char*)malloc(m_negotiatedMaxBufferSize);
reclen = receiveEncryptedData(buf, m_negotiatedMaxBufferSize);
if (reclen < 0) {
free(buf);
return -1;
}
if (reclen > 0) {
m_buffer->at(m_bufferLength);
wrlen = m_buffer->writeBlock(buf, reclen);
@ -325,6 +347,10 @@ TQString TDEKerberosClientSocket::readLine() {
maxlen = m_negotiatedMaxBufferSize;
char* buf = (char*)malloc(m_negotiatedMaxBufferSize);
reclen = receiveEncryptedData(buf, m_negotiatedMaxBufferSize);
if (reclen < 0) {
free(buf);
return TQString::null;
}
if (reclen > 0) {
m_buffer->at(m_bufferLength);
wrlen = m_buffer->writeBlock(buf, reclen);
@ -410,17 +436,25 @@ void TDEKerberosClientSocket::sendSASLDataToNetwork(const char *buffer, unsigned
free(buf);
}
int TDEKerberosClientSocket::getSASLDataFromNetwork(char *buf, int trunclen) {
int TDEKerberosClientSocket::getSASLDataFromNetwork(char *buf, int trunclen, bool shouldblock) {
m_criticalSection++;
try {
unsigned int len;
int result;
TQByteArray ba(2048);
if (!shouldblock) {
if ((!TQSocket::canReadLine()) || (state() != TQSocket::Connected)) {
return 0;
}
}
len = 0;
while (1) {
tqApp->processEvents();
if (shouldblock) {
SAFELY_PROCESS_EVENTS
}
if (state() != TQSocket::Connected) {
m_criticalSection--;
return -1;
@ -435,7 +469,13 @@ int TDEKerberosClientSocket::getSASLDataFromNetwork(char *buf, int trunclen) {
}
}
else {
usleep(1000);
if (shouldblock) {
usleep(1000);
}
else {
break;
}
}
if (len >= (ba.size()-1)) {
ba.resize(ba.size()+2048);
@ -486,21 +526,21 @@ int TDEKerberosClientSocket::transmitEncryptedData(int fd, const char* readbuf,
data_remaining = data_remaining - data_to_write_len;
remnant_position = remnant_position + data_to_write_len;
if (data_remaining > 0) {
tqApp->processEvents();
SAFELY_PROCESS_EVENTS
}
}
return 0;
}
int TDEKerberosClientSocket::receiveEncryptedData(char *buf, unsigned int trunclen) {
int TDEKerberosClientSocket::receiveEncryptedData(char *buf, unsigned int trunclen, bool shouldblock) {
unsigned int recv_len;
const char *recv_data;
int result;
int len;
char *encbuf = (char*)malloc(m_negotiatedMaxBufferSize);
len = getSASLDataFromNetwork(encbuf, m_negotiatedMaxBufferSize);
len = getSASLDataFromNetwork(encbuf, m_negotiatedMaxBufferSize, shouldblock);
if (len < 0) {
return -1;
}

@ -58,9 +58,9 @@ class TDEKerberosClientSocket : public TQSocket
int initializeKerberosInterface();
void freeKerberosConnection();
void sendSASLDataToNetwork(const char *buffer, unsigned length, int netfd);
int getSASLDataFromNetwork(char *buf, int trunclen);
int getSASLDataFromNetwork(char *buf, int trunclen, bool shouldblock=true);
int transmitEncryptedData(int fd, const char* readbuf, int cc);
int receiveEncryptedData(char *buf, unsigned int trunclen);
int receiveEncryptedData(char *buf, unsigned int trunclen, bool shouldblock=true);
private:
bool m_kerberosRequested;
@ -69,6 +69,7 @@ class TDEKerberosClientSocket : public TQSocket
int m_criticalSection;
TQBuffer* m_buffer;
long m_bufferLength;
bool* m_canary;
private:
SASLDataPrivate *saslData;

@ -32,6 +32,20 @@
#define NET_SEC_BUF_SIZE (2048)
// When control comes back from processEvents() my object may be completely gone! This attempts to mitigate the risk
#define SAFELY_PROCESS_EVENTS if (!m_canary) { \
m_canary = new bool; \
*m_canary = false; \
} \
bool* canary = m_canary; \
tqApp->processEvents(); \
if (*canary == true) { \
delete canary; \
return -1; \
} \
delete m_canary; \
m_canary = NULL;
/* exception handling */
struct exit_exception {
int c;
@ -79,7 +93,7 @@ static int logSASLMessages(void *context __attribute__((unused)), int priority,
return SASL_OK;
}
TDEKerberosServerSocket::TDEKerberosServerSocket(TQObject *parent, const char *name) : TQSocket(parent, name), m_kerberosRequested(false), m_criticalSection(0), m_bufferLength(0), m_negotiatedMaxBufferSize(NET_SEC_BUF_SIZE) {
TDEKerberosServerSocket::TDEKerberosServerSocket(TQObject *parent, const char *name) : TQSocket(parent, name), m_kerberosRequested(false), m_criticalSection(0), m_bufferLength(0), m_canary(NULL), m_negotiatedMaxBufferSize(NET_SEC_BUF_SIZE) {
saslData = new SASLDataPrivate;
saslData->m_krbConnection = NULL;
m_buffer = new TQBuffer();
@ -87,6 +101,9 @@ TDEKerberosServerSocket::TDEKerberosServerSocket(TQObject *parent, const char *n
}
TDEKerberosServerSocket::~TDEKerberosServerSocket() {
if (m_canary) {
*m_canary = true;
}
m_buffer->close();
delete m_buffer;
delete saslData;
@ -102,9 +119,6 @@ bool TDEKerberosServerSocket::open(int mode) {
void TDEKerberosServerSocket::close() {
TQSocket::close();
if (m_criticalSection > 0) {
throw exit_exception(-1);
}
}
void TDEKerberosServerSocket::flush() {
@ -221,6 +235,10 @@ TQ_LONG TDEKerberosServerSocket::readBlock(char *data, TQ_ULONG maxlen) {
int wrlen;
char* buf = (char*)malloc(m_negotiatedMaxBufferSize);
reclen = receiveEncryptedData(buf, m_negotiatedMaxBufferSize);
if (reclen < 0) {
free(buf);
return -1;
}
if (reclen > 0) {
m_buffer->at(m_bufferLength);
wrlen = m_buffer->writeBlock(buf, reclen);
@ -278,6 +296,10 @@ TQ_LONG TDEKerberosServerSocket::readLine(char *data, TQ_ULONG maxlen) {
int wrlen;
char* buf = (char*)malloc(m_negotiatedMaxBufferSize);
reclen = receiveEncryptedData(buf, m_negotiatedMaxBufferSize);
if (reclen < 0) {
free(buf);
return -1;
}
if (reclen > 0) {
m_buffer->at(m_bufferLength);
wrlen = m_buffer->writeBlock(buf, reclen);
@ -325,6 +347,10 @@ TQString TDEKerberosServerSocket::readLine() {
maxlen = m_negotiatedMaxBufferSize;
char* buf = (char*)malloc(m_negotiatedMaxBufferSize);
reclen = receiveEncryptedData(buf, m_negotiatedMaxBufferSize);
if (reclen < 0) {
free(buf);
return TQString::null;
}
if (reclen > 0) {
m_buffer->at(m_bufferLength);
wrlen = m_buffer->writeBlock(buf, reclen);
@ -410,7 +436,7 @@ void TDEKerberosServerSocket::sendSASLDataToNetwork(const char *buffer, unsigned
free(buf);
}
int TDEKerberosServerSocket::getSASLDataFromNetwork(char *buf, int trunclen) {
int TDEKerberosServerSocket::getSASLDataFromNetwork(char *buf, int trunclen, bool shouldblock) {
m_criticalSection++;
try {
unsigned int len;
@ -418,9 +444,17 @@ int TDEKerberosServerSocket::getSASLDataFromNetwork(char *buf, int trunclen) {
TQByteArray ba(2048);
if (!shouldblock) {
if ((!TQSocket::canReadLine()) || (state() != TQSocket::Connected)) {
return 0;
}
}
len = 0;
while (1) {
tqApp->processEvents();
if (shouldblock) {
SAFELY_PROCESS_EVENTS
}
if (state() != TQSocket::Connected) {
m_criticalSection--;
return -1;
@ -435,7 +469,13 @@ int TDEKerberosServerSocket::getSASLDataFromNetwork(char *buf, int trunclen) {
}
}
else {
usleep(1000);
if (shouldblock) {
usleep(1000);
}
else {
break;
}
}
if (len >= (ba.size()-1)) {
ba.resize(ba.size()+2048);
@ -486,21 +526,21 @@ int TDEKerberosServerSocket::transmitEncryptedData(int fd, const char* readbuf,
data_remaining = data_remaining - data_to_write_len;
remnant_position = remnant_position + data_to_write_len;
if (data_remaining > 0) {
tqApp->processEvents();
SAFELY_PROCESS_EVENTS
}
}
return 0;
}
int TDEKerberosServerSocket::receiveEncryptedData(char *buf, unsigned int trunclen) {
int TDEKerberosServerSocket::receiveEncryptedData(char *buf, unsigned int trunclen, bool shouldblock) {
unsigned int recv_len;
const char *recv_data;
int result;
int len;
char *encbuf = (char*)malloc(m_negotiatedMaxBufferSize);
len = getSASLDataFromNetwork(encbuf, m_negotiatedMaxBufferSize);
len = getSASLDataFromNetwork(encbuf, m_negotiatedMaxBufferSize, shouldblock);
if (len < 0) {
return -1;
}

@ -58,9 +58,9 @@ class TDEKerberosServerSocket : public TQSocket
int initializeKerberosInterface();
void freeKerberosConnection();
void sendSASLDataToNetwork(const char *buffer, unsigned length, int netfd);
int getSASLDataFromNetwork(char *buf, int trunclen);
int getSASLDataFromNetwork(char *buf, int trunclen, bool shouldblock=true);
int transmitEncryptedData(int fd, const char* readbuf, int cc);
int receiveEncryptedData(char *buf, unsigned int trunclen);
int receiveEncryptedData(char *buf, unsigned int trunclen, bool shouldblock=true);
protected:
TQString m_authenticatedUserName;
@ -73,6 +73,7 @@ class TDEKerberosServerSocket : public TQSocket
int m_criticalSection;
TQBuffer* m_buffer;
long m_bufferLength;
bool* m_canary;
private:
SASLDataPrivate *saslData;

@ -29,10 +29,6 @@
#include "auth_conn.h"
#define ABORT_SOCKET(s) s->close(); \
tqApp->processEvents(); \
while (s->state() == TQSocket::Closing) { \
tqApp->processEvents(); \
} \
s->disconnect(); \
delete s; \
s = NULL;
@ -49,7 +45,7 @@ struct exit_exception {
instance of this class.
*/
AuthSocket::AuthSocket(int sock, TQObject *parent, const char *name) :
TDEKerberosServerSocket(parent, name), m_criticalSection(0), m_stationID(-1), m_bound(false), 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_servActive(false), m_servState(0), m_servClientSocket(NULL), m_servClientTimeout(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)
{
@ -80,6 +76,9 @@ AuthSocket::~AuthSocket() {
if (m_databaseActivityCursor) {
delete m_databaseActivityCursor;
}
if (m_servClientSocket) {
delete m_servClientSocket;
}
}
void AuthSocket::close() {
@ -122,235 +121,312 @@ int AuthSocket::initiateKerberosHandshake() {
}
}
int AuthSocket::enterCommandLoop() {
m_criticalSection++;
try {
void AuthSocket::servLoop() {
if (m_servActive) {
TQString command;
TQDataStream ds(this);
switch (m_servState) {
case 0:
if (!m_servClientTimeout) {
m_servClientTimeout = new TQTimer();
m_servClientTimeout->start(5000, TRUE);
}
if ((m_servClientSocket->state() == TQSocket::Connecting) || (m_servClientSocket->state() == TQSocket::HostLookup)) {
if (!m_servClientTimeout->isActive()) {
m_servClientSocket->close();
ds << TQString("ERRNOTAVL");
printf("[DEBUG] Connection failed to %s:%d for user %s@%s\n\r", m_srvServiceHostName.ascii(), m_srvServicePort, m_authenticatedUserName.ascii(), m_authenticatedRealmName.ascii()); fflush(stdout);
m_servActive = false;
delete m_servClientTimeout;
m_servClientTimeout = NULL;
}
}
else {
if (m_servClientTimeout) {
m_servClientTimeout->stop();
delete m_servClientTimeout;
m_servClientTimeout = NULL;
}
m_servState = 1;
}
break;
case 1:
if (m_servClientSocket->state() == TQSocket::Connected) {
if (m_servClientSocket->setUsingKerberos(true) != 0) {
m_servClientSocket->close();
ds << TQString("ERRNOTAVL");
printf("[DEBUG] Connection failed to %s:%d for user %s@%s due to Kerberos failure\n\r", m_srvServiceHostName.ascii(), m_srvServicePort, m_authenticatedUserName.ascii(), m_authenticatedRealmName.ascii()); fflush(stdout);
m_servActive = false;
delete m_servClientTimeout;
m_servClientTimeout = NULL;
}
m_servState = 2;
}
else {
m_servClientSocket->close();
ds << TQString("ERRNOTAVL");
printf("[DEBUG] Connection failed to %s:%d for user %s@%s\n\r", m_srvServiceHostName.ascii(), m_srvServicePort, m_authenticatedUserName.ascii(), m_authenticatedRealmName.ascii()); fflush(stdout);
m_servActive = false;
delete m_servClientTimeout;
m_servClientTimeout = NULL;
}
break;
case 2:
if (!m_servClientTimeout) {
m_servClientTimeout = new TQTimer();
m_servClientTimeout->start(5000, TRUE);
}
if (m_servClientSocket->state() == TQSocket::Connected) {
if (m_servClientSocket->canReadLine()) {
TQDataStream clientDS(m_servClientSocket);
TQString server_reply;
while (state() == TQSocket::Connected) {
ds >> command;
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;
}
clientDS >> server_reply;
if (server_reply == "OK") {
ds << TQString("OK");
m_servState = 3;
}
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;
}
else {
m_servClientSocket->close();
ds << TQString("ERRNOTAVL");
printf("[DEBUG] Connection failed to %s:%d for user %s@%s due to remote server returning %s\n\r", m_srvServiceHostName.ascii(), m_srvServicePort, m_authenticatedUserName.ascii(), m_authenticatedRealmName.ascii(), server_reply.ascii()); fflush(stdout);
m_servActive = false;
delete m_servClientTimeout;
m_servClientTimeout = NULL;
}
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();
svt.clientLibrary = m_databaseServiceTypesCursor->value("client_library").toString();
svt.version = m_databaseServiceTypesCursor->value("version").toInt();
}
else {
if (!m_servClientTimeout->isActive()) {
// Timeout!
m_servClientSocket->close();
ds << TQString("ERRNOTAVL");
printf("[DEBUG] Connection failed to %s:%d for user %s@%s\n\r", m_srvServiceHostName.ascii(), m_srvServicePort, m_authenticatedUserName.ascii(), m_authenticatedRealmName.ascii()); fflush(stdout);
m_servActive = false;
delete m_servClientTimeout;
m_servClientTimeout = NULL;
}
}
}
else {
m_servClientSocket->close();
ds << TQString("ERRNOTAVL");
printf("[DEBUG] Connection failed to %s:%d for user %s@%s\n\r", m_srvServiceHostName.ascii(), m_srvServicePort, m_authenticatedUserName.ascii(), m_authenticatedRealmName.ascii()); fflush(stdout);
m_servActive = false;
delete m_servClientTimeout;
m_servClientTimeout = NULL;
}
break;
case 3:
if (m_servClientSocket->state() == TQSocket::Connected) {
TQByteArray ba(8192);
TQ_ULONG reclen;
if (canReadLine()) {
reclen = readBlock(ba.data(), 8192);
m_servClientSocket->writeBlock(ba.data(), reclen);
}
if (m_servClientSocket->canReadLine()) {
reclen = m_servClientSocket->readBlock(ba.data(), 8192);
writeBlock(ba.data(), reclen);
}
}
else {
m_servClientSocket->close();
ds << TQString("ERRNOTAVL");
printf("[DEBUG] Connection terminated by remote host %s:%d for user %s@%s\n\r", m_srvServiceHostName.ascii(), m_srvServicePort, m_authenticatedUserName.ascii(), m_authenticatedRealmName.ascii()); fflush(stdout);
m_servActive = false;
}
break;
}
}
}
void AuthSocket::commandLoop() {
if (m_servActive) {
servLoop();
TQTimer::singleShot(0, this, SLOT(commandLoop()));
return;
}
m_criticalSection++;
try {
if (state() == TQSocket::Connected) {
if (canReadLine()) {
TQString command;
TQDataStream ds(this);
ds >> command;
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;
}
if (svt.name == "") {
svt.name = i18n("<unknown>");
}
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 (svt.description == "") {
svt.description = i18n("<unknown>");
}
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();
svt.clientLibrary = m_databaseServiceTypesCursor->value("client_library").toString();
svt.version = m_databaseServiceTypesCursor->value("version").toInt();
}
if (svt.name == "") {
svt.name = i18n("<unknown>");
}
if (svt.description == "") {
svt.description = i18n("<unknown>");
}
st.services.append(svt);
}
st.services.append(svt);
m_slist.append(st);
}
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;
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;
// Ensure that this user is not already connected
int activeID = -1;
m_databaseActivityCursor->select(TQString("username='%1' AND realmname='%2'").arg(m_authenticatedUserName).arg(m_authenticatedRealmName));
if (m_databaseActivityCursor->next()) {
activeID = m_databaseActivityCursor->value("station").toInt();
}
if (activeID < 0) {
for (StationList::Iterator it(m_slist.begin()); it != m_slist.end(); ++it) {
if ((*it).services == st.services) {
m_stationID = (*it).id;
break;
}
// Ensure that this user is not already connected
int activeID = -1;
m_databaseActivityCursor->select(TQString("username='%1' AND realmname='%2'").arg(m_authenticatedUserName).arg(m_authenticatedRealmName));
if (m_databaseActivityCursor->next()) {
activeID = m_databaseActivityCursor->value("station").toInt();
}
if (activeID < 0) {
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 {
m_bound = true;
if (m_stationID < 0) {
ds << TQString("ERRUNAVAL");
// 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 {
m_bound = true;
// 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");
ds << TQString("ERRPREVCN");
}
}
else {
ds << TQString("ERRPREVCN");
}
}
else if (command == "SERV") {
// Get client library name from the client
TQString libname;
ds >> libname;
m_databaseActivityCursor->select(TQString("username='%1' AND realmname='%2'").arg(m_authenticatedUserName).arg(m_authenticatedRealmName));
if (m_databaseActivityCursor->next()) {
m_stationID = m_databaseActivityCursor->value("station").toInt();
}
if (m_bound == true) {
ds << TQString("ERRINVCMD");
}
else {
if (m_stationID < 0) {
ds << TQString("ERRNOCONN");
else if (command == "SERV") {
// Get client library name from the client
TQString libname;
ds >> libname;
m_databaseActivityCursor->select(TQString("username='%1' AND realmname='%2'").arg(m_authenticatedUserName).arg(m_authenticatedRealmName));
if (m_databaseActivityCursor->next()) {
m_stationID = m_databaseActivityCursor->value("station").toInt();
}
if (m_bound == true) {
ds << TQString("ERRINVCMD");
}
else {
// Find the service ID for the specified client library name
TQ_INT32 sid = -1;
m_databaseServiceTypesCursor->select(TQString("client_library='%1'").arg(libname));
if (m_databaseServiceTypesCursor->next()) {
sid = m_databaseServiceTypesCursor->value("serviceid").toInt();
}
if (sid < 0) {
ds << TQString("ERRNOSERV");
if (m_stationID < 0) {
ds << TQString("ERRNOCONN");
}
else {
// Attempt to connect to the backend server
m_databaseServicesCursor->select(TQString("pk=%1 AND station=%2").arg(sid).arg(m_stationID));
if (m_databaseServicesCursor->next()) {
TQString serviceHostName = m_databaseServicesCursor->value("hostname").toString();
int servicePort = m_databaseServicesCursor->value("port").toInt();
TDEKerberosClientSocket clientSocket;
clientSocket.setServiceName("remotefpga");
clientSocket.setServerFQDN(serviceHostName);
clientSocket.connectToHost(serviceHostName, servicePort);
TQTimer connectionTimeout;
connectionTimeout.start(5000, TRUE);
while ((clientSocket.state() == TQSocket::Connecting) || (clientSocket.state() == TQSocket::HostLookup)) {
tqApp->processEvents();
if (!connectionTimeout.isActive()) {
break;
}
}
connectionTimeout.stop();
if (clientSocket.state() == TQSocket::Connected) {
if (clientSocket.setUsingKerberos(true) != 0) {
clientSocket.close();
ds << TQString("ERRNOTAVL");
printf("[DEBUG] Connection failed to %s:%d for user %s@%s due to Kerberos failure\n\r", serviceHostName.ascii(), servicePort, m_authenticatedUserName.ascii(), m_authenticatedRealmName.ascii()); fflush(stdout);
}
else {
TQDataStream clientDS(&clientSocket);
TQString server_reply;
connectionTimeout.start(5000, TRUE);
while ((!clientSocket.canReadLine()) && (clientSocket.state() == TQSocket::Connected)) {
tqApp->processEvents();
if (!connectionTimeout.isActive()) {
break;
}
}
connectionTimeout.stop();
if ((clientSocket.canReadLine()) && (clientSocket.state() == TQSocket::Connected)) {
clientDS >> server_reply;
}
if (server_reply == "OK") {
ds << TQString("OK");
TQByteArray ba(8192);
TQ_ULONG reclen;
while ((state() == TQSocket::Connected) && (clientSocket.state() == TQSocket::Connected)) {
// RAJA FIXME
if (canReadLine()) {
reclen = readBlock(ba.data(), 8192);
clientSocket.writeBlock(ba.data(), reclen);
}
if (clientSocket.canReadLine()) {
reclen = clientSocket.readBlock(ba.data(), 8192);
writeBlock(ba.data(), reclen);
}
tqApp->processEvents();
}
clientSocket.close();
}
else {
clientSocket.close();
ds << TQString("ERRNOTAVL");
printf("[DEBUG] Connection failed to %s:%d for user %s@%s due to remote server returning %s\n\r", serviceHostName.ascii(), servicePort, m_authenticatedUserName.ascii(), m_authenticatedRealmName.ascii(), server_reply.ascii()); fflush(stdout);
}
}
// Find the service ID for the specified client library name
TQ_INT32 sid = -1;
m_databaseServiceTypesCursor->select(TQString("client_library='%1'").arg(libname));
if (m_databaseServiceTypesCursor->next()) {
sid = m_databaseServiceTypesCursor->value("serviceid").toInt();
}
if (sid < 0) {
ds << TQString("ERRNOSERV");
}
else {
// Attempt to connect to the backend server
m_databaseServicesCursor->select(TQString("pk=%1 AND station=%2").arg(sid).arg(m_stationID));
if (m_databaseServicesCursor->next()) {
m_srvServiceHostName = m_databaseServicesCursor->value("hostname").toString();
m_srvServicePort = m_databaseServicesCursor->value("port").toInt();
if (!m_servClientSocket) m_servClientSocket = new TDEKerberosClientSocket;
m_servClientSocket->setServiceName("remotefpga");
m_servClientSocket->setServerFQDN(m_srvServiceHostName);
m_servClientSocket->connectToHost(m_srvServiceHostName, m_srvServicePort);
m_servState = 0;
m_servActive = true;
}
else {
clientSocket.close();
ds << TQString("ERRNOTAVL");
printf("[DEBUG] Connection failed to %s:%d for user %s@%s\n\r", serviceHostName.ascii(), servicePort, m_authenticatedUserName.ascii(), m_authenticatedRealmName.ascii()); fflush(stdout);
ds << TQString("ERRNOSERV");
}
}
else {
ds << TQString("ERRNOSERV");
}
}
}
}
}
else {
ds << TQString("ERRINVCMD");
else {
ds << TQString("ERRINVCMD");
}
}
}
tqApp->processEvents();
}
m_criticalSection--;
return 0;
m_criticalSection--;
TQTimer::singleShot(0, this, SLOT(commandLoop()));
return;
}
}
catch (...) {
m_criticalSection--;
return -1;
return;
}
}
int AuthSocket::enterCommandLoop() {
TQTimer::singleShot(0, this, SLOT(commandLoop()));
return 0;
}
int AuthSocket::connectToDatabase() {
if (m_database) {
return -2;

@ -57,6 +57,8 @@ class AuthSocket : public TDEKerberosServerSocket
private slots:
int connectToDatabase();
void connectionClosedHandler();
void commandLoop();
void servLoop();
private:
int line;
@ -65,6 +67,13 @@ class AuthSocket : public TDEKerberosServerSocket
int m_stationID;
bool m_bound;
bool m_servActive;
int m_servState;
TDEKerberosClientSocket* m_servClientSocket;
TQTimer* m_servClientTimeout;
TQString m_srvServiceHostName;
int m_srvServicePort;
KSimpleConfig* m_config;
TQSqlDatabase* m_database;
TQSqlCursor* m_databaseStationsCursor;

@ -41,10 +41,6 @@
#include "fpga_conn.h"
#define ABORT_SOCKET(s) s->close(); \
tqApp->processEvents(); \
while (s->state() == TQSocket::Closing) { \
tqApp->processEvents(); \
} \
s->disconnect(); \
delete s; \
s = NULL;
@ -153,13 +149,13 @@ int FPGASocket::setupSerial() {
return 0;
}
int FPGASocket::enterCommandLoop() {
void FPGASocket::commandLoop() {
int cc;
char buffer[10000];
m_criticalSection++;
try {
while (state() == TQSocket::Connected) {
if (state() == TQSocket::Connected) {
cc = read(m_fd_tty, buffer, 10000);
if (cc > 0) {
writeBlock(buffer, cc);
@ -175,16 +171,21 @@ int FPGASocket::enterCommandLoop() {
}
}
}
m_criticalSection--;
return 0;
TQTimer::singleShot(0, this, SLOT(commandLoop()));
return;
}
catch (...) {
m_criticalSection--;
return -1;
return;
}
}
int FPGASocket::enterCommandLoop() {
TQTimer::singleShot(0, this, SLOT(commandLoop()));
return 0;
}
/*
The FPGAServer class handles new connections to the server. For every
client that connects, it creates a new FPGASocket -- that instance is now

@ -54,6 +54,7 @@ class FPGASocket : public TDEKerberosServerSocket
private slots:
void connectionClosedHandler();
int setupSerial();
void commandLoop();
private:
int line;

Loading…
Cancel
Save