/* * Remote Laboratory FPGA Server * * 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 3 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., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * (c) 2012 Timothy Pearson * Raptor Engineering * http://www.raptorengineeringinc.com */ #include #include #include "fpga_conn.h" /* exception handling */ struct exit_exception { int c; exit_exception(int c):c(c) { } }; /* The FPGASocket class provides a socket that is connected with a client. For every client that connects to the server, the server creates a new instance of this class. */ FPGASocket::FPGASocket(int sock, TQObject *parent, const char *name) : TDEKerberosServerSocket(parent, name), m_criticalSection(0), m_stationID(-1), m_config(static_cast(parent)->m_config), m_database(NULL), m_databaseStationsCursor(NULL) { setServiceName("remotefpga"); line = 0; connect(this, SIGNAL(connectionClosed()), SLOT(connectionClosedHandler())); setSocket(sock); } FPGASocket::~FPGASocket() { // } void FPGASocket::close() { TDEKerberosServerSocket::close(); connectionClosedHandler(); } void FPGASocket::connectionClosedHandler() { printf("[DEBUG] Connection from %s closed\n\r", m_remoteHost.ascii()); if (m_criticalSection > 0) { throw exit_exception(-1); } } int FPGASocket::initiateKerberosHandshake() { if (setUsingKerberos(true) == 0) { TQDataStream ds(this); ds << TQString("OK"); return 0; } else { return -1; } } void FPGASocket::enterCommandLoop() { // RAJA FIXME } /* The FPGAServer class handles new connections to the server. For every client that connects, it creates a new FPGASocket -- that instance is now responsible for the communication with that client. */ FPGAServer::FPGAServer(TQObject* parent, int port, KSimpleConfig* config) : TQServerSocket( port, 1, parent ), m_config(config), m_numberOfConnections(0) { if ( !ok() ) { printf("[ERROR] Failed to bind to port %d\n\r", port); exit(1); } socketDevice()->setAddressReusable(false); printf("[INFO] Server started on port %d\n\r", port); fflush(stdout); } FPGAServer::~FPGAServer() { // } void FPGAServer::newConnection(int socket) { FPGASocket *s = new FPGASocket(socket, this); s->m_remoteHost = s->peerAddress().toString(); printf("[DEBUG] New connection from %s\n\r", s->m_remoteHost.ascii()); if (m_numberOfConnections > 0) { printf("[DEBUG] Connection from %s closed due to multiple access attempt\n\r", m_remoteHost.ascii()); s->close(); delete s; s = NULL; } if (s->initiateKerberosHandshake() != 0) { printf("[DEBUG] Connection from %s closed due to Kerberos failure\n\r", m_remoteHost.ascii()); s->close(); delete s; s = NULL; } else { m_numberOfConnections++; connect(s, SIGNAL(connectionClosed()), s, SLOT(deleteLater())); connect(s, SIGNAL(connectionClosed()), this, SLOT(remoteConnectionClosed())); emit newConnect(s); s->enterCommandLoop(); } } void FPGAServer::remoteConnectionClosed() { m_numberOfConnections--; }