Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "assert.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Qt includes
Toshihiro Shimizu 890ddd
#include <qdatastream></qdatastream>
Toshihiro Shimizu 890ddd
#include <qdebug></qdebug>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tipc.h"
Toshihiro Shimizu 890ddd
#include "tipcmsg.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tipcsrvP.h"
Toshihiro Shimizu 890ddd
#include "tipcsrv.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*******************************************************************************
Toshihiro Shimizu 890ddd
//    Diagnostics stuff
Toshihiro Shimizu 890ddd
//*******************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//#define TIPC_DEBUG
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef TIPC_DEBUG
Toshihiro Shimizu 890ddd
#define tipc_debug(expr) expr
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
#define tipc_debug(expr)
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef TIPC_DEBUG
Toshihiro Shimizu 890ddd
#include <qtime></qtime>
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*******************************************************************************
Toshihiro Shimizu 890ddd
//    tipc::SocketListener implementation
Toshihiro Shimizu 890ddd
//*******************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void tipc::SocketController::onReadyRead()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Deliver the message to the server for interpretation.
Toshihiro Shimizu 890ddd
	m_server->dispatchSocket(m_socket);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void tipc::SocketController::onDisconnected()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_socket->QObject::disconnect(SIGNAL(readyRead()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Auto-delete this
Toshihiro Shimizu 890ddd
	delete this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*******************************************************************************
Toshihiro Shimizu 890ddd
//    Server implementation
Toshihiro Shimizu 890ddd
//*******************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
tipc::Server::Server()
Toshihiro Shimizu 890ddd
	: m_lock(false)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	connect(this, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Add default parsers
Toshihiro Shimizu 890ddd
	addParser(new DefaultMessageParser<shmem_request>);</shmem_request>
Toshihiro Shimizu 890ddd
	addParser(new DefaultMessageParser<shmem_release>);</shmem_release>
Toshihiro Shimizu 890ddd
	addParser(new DefaultMessageParser<tmpfile_request>);</tmpfile_request>
Toshihiro Shimizu 890ddd
	addParser(new DefaultMessageParser<tmpfile_release>);</tmpfile_release>
Toshihiro Shimizu 890ddd
	addParser(new DefaultMessageParser<quit_on_error>);</quit_on_error>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
tipc::Server::~Server()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Release parsers
Toshihiro Shimizu 890ddd
	QHash<qstring, *="" messageparser="">::iterator it;</qstring,>
Toshihiro Shimizu 890ddd
	for (it = m_parsers.begin(); it != m_parsers.end(); ++it)
Toshihiro Shimizu 890ddd
		delete it.value();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void tipc::Server::addParser(MessageParser *parser)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_parsers.insert(parser->header(), parser);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void tipc::Server::removeParser(QString header)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	MessageParser *parser = m_parsers.take(header);
Toshihiro Shimizu 890ddd
	if (parser)
Toshihiro Shimizu 890ddd
		delete parser;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void tipc::Server::onNewConnection()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	tipc_debug(qDebug("new connection"));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Accept the connection
Toshihiro Shimizu 890ddd
	QLocalSocket *socket = nextPendingConnection();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Allocate a controller for the socket
Toshihiro Shimizu 890ddd
	SocketController *controller = new SocketController;
Toshihiro Shimizu 890ddd
	controller->m_server = this;
Toshihiro Shimizu 890ddd
	controller->m_socket = socket;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Connect the controller to the socket's signals
Toshihiro Shimizu 890ddd
	connect(socket, SIGNAL(readyRead()), controller, SLOT(onReadyRead()));
Toshihiro Shimizu 890ddd
	connect(socket, SIGNAL(disconnected()), controller, SLOT(onDisconnected()));
Toshihiro Shimizu 890ddd
	connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
Toshihiro Shimizu 890ddd
	connect(socket, SIGNAL(error(QLocalSocket::LocalSocketError)),
Toshihiro Shimizu 890ddd
			this, SLOT(onError(QLocalSocket::LocalSocketError)));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void tipc::Server::onError(QLocalSocket::LocalSocketError error)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	tipc_debug(qDebug() << "Server error #" << error << ": " << errorString());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void tipc::Server::dispatchSocket(QLocalSocket *socket)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//The lock is established when a message is currently being processed.
Toshihiro Shimizu 890ddd
	//Returning if the lock is set avoids having recursive message processing;
Toshihiro Shimizu 890ddd
	//which is possible if a parser expects further message packets.
Toshihiro Shimizu 890ddd
	if (m_lock)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	tipc::Stream stream(socket);
Toshihiro Shimizu 890ddd
	QString header;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while (socket->bytesAvailable() > 0) {
Toshihiro Shimizu 890ddd
		if (!stream.messageReady())
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		Message msg;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		stream >> msg;
Toshihiro Shimizu 890ddd
		msg >> header;
Toshihiro Shimizu 890ddd
		assert(!header.isEmpty());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		tipc_debug(qDebug() << header << endl);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		QHash<qstring, *="" messageparser="">::iterator it = m_parsers.find(header);</qstring,>
Toshihiro Shimizu 890ddd
		if (it == m_parsers.end()) {
Toshihiro Shimizu 890ddd
			tipc_debug(qDebug() << "Error: Unrecognized command" << endl);
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_lock = true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		MessageParser *parser = it.value();
Toshihiro Shimizu 890ddd
		parser->m_socket = socket;
Toshihiro Shimizu 890ddd
		parser->m_stream = &stream;
Toshihiro Shimizu 890ddd
		parser->operator()(msg);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_lock = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//The Message has been read and processed. Send the reply.
Toshihiro Shimizu 890ddd
		if (msg.ba().size() > 0)
Toshihiro Shimizu 890ddd
			stream << msg;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}