Blame protocol.cpp

f07ad6
646228
#include "utils.h"
f07ad6
#include "protocol.h"
f07ad6
#include "server.h"
f07ad6
#include "connection.h"
f07ad6
f07ad6
541903
541903
Socket::Socket(
541903
	Protocol &protocol,
541903
	const Connection::Handle &connection,
541903
	const Server::Handle &server,
541903
	const Address &address
541903
):
541903
	protocol(protocol), connection(connection), server(server), address(address),
9bbba5
	flags(), prev(), next(), chPrev(), chNext()
f07ad6
{
f07ad6
	prev = protocol.last;
f07ad6
	(prev ? prev->next : protocol.first) = this;
f07ad6
}
f07ad6
f07ad6
541903
Socket::~Socket() {
541903
	setChanged(false);
f07ad6
	(prev ? prev->next : protocol.first) = next;
f07ad6
	(next ? next->prev : protocol.last) = prev;
541903
	prev = next = nullptr;
541903
}
541903
541903
9bbba5
void Socket::onConstructionComplete() {
9bbba5
	flags |= CREATED;
9bbba5
	setChanged(true);
9bbba5
}
9bbba5
9bbba5
541903
void Socket::setChanged(bool changed) {
541903
	if ((bool)(flags & CHANGED) == changed) return;
541903
	if (changed) {
541903
		flags |= CHANGED;
541903
		chPrev = protocol.chLast;
541903
		(chPrev ? chPrev->chNext : protocol.chFirst) = this;
646228
		protocol.onSocketChanged(this);
541903
	} else {
9bbba5
		flags &= ~(CHANGED | CREATED);
541903
		(chPrev ? chPrev->chNext : protocol.chFirst) = chNext;
541903
		(chNext ? chNext->chPrev : protocol.chLast) = chPrev;
541903
		chPrev = chNext = nullptr;
541903
	}
541903
}
541903
541903
541903
void Socket::setWantRead(bool want) {
541903
	Protocol::Lock lock(protocol.mutex);
541903
	if ((bool)(flags & WANTREAD) == want) return;
541903
	flags = want ? flags | WANTREAD : flags & ~WANTREAD;
541903
	setChanged(true);
541903
}
541903
541903
541903
void Socket::setWantWrite(bool want) {
541903
	Protocol::Lock lock(protocol.mutex);
541903
	if ((bool)(flags & WANTWRITE) == want) return;
541903
	flags = want ? flags | WANTWRITE : flags & ~WANTWRITE;
541903
	setChanged(true);
541903
}
541903
541903
541903
void Socket::finalize() {
541903
	Protocol::Lock lock(protocol.mutex);
541903
	if (flags & REMOVED) return;
541903
	flags |= REMOVED;
541903
	setChanged(true);
f07ad6
}
f07ad6
f07ad6
f07ad6
f07ad6
Protocol::Protocol():
646228
	first(), last(), chFirst(), chLast(),
2499ad
	started(), switching(), stopRequested(), stopTimeUs() { }
f07ad6
f07ad6
646228
Protocol::~Protocol() {
646228
	Lock lockStartStop(mutexStartStop);
646228
	Lock lock(mutex);
646228
	assert(!started);
646228
	clean();
2a209b
}
2a209b
2a209b
9bbba5
ErrorCode Protocol::connectionOpen(const Connection::Handle &connection, Socket *socket) {
9bbba5
	if (!connection || !socket) return ERR_INVALID_ARGS;
9bbba5
	if (!isFullActive()) return ERR_PROTOCOL_NOT_INITIALIZED;
9bbba5
	return connection->open(socket);
9bbba5
}
9bbba5
9bbba5
9bbba5
ErrorCode Protocol::serverStart(const Server::Handle &server, Socket *socket) {
9bbba5
	if (!server || !socket) return ERR_INVALID_ARGS;
9bbba5
	if (!isFullActive()) return ERR_PROTOCOL_NOT_INITIALIZED;
9bbba5
	return server->start(socket);
9bbba5
}
9bbba5
9bbba5
9bbba5
Connection::Handle Protocol::serverConnect(const Server::Handle &server, const Address &address) {
9bbba5
	if (!server) return nullptr;
9bbba5
	if (!isFullActive()) return nullptr;
9bbba5
	return server->connect(address);
9bbba5
}
646228
646228
5a39be
void Protocol::serverDisconnect(const Server::Handle &server, const Connection::Handle &connection) {
5a39be
	if (!server || !connection) return;
5a39be
	server->disconnect(connection);
5a39be
}
5a39be
5a39be
5a39be
646228
int Protocol::stopServer(Server &server) {
f07ad6
	Lock lock(mutex);
646228
	int count = 0;
646228
	if (started)
646228
		for(Socket *s = socketFirst(); s; s = socketNext(s))
9bbba5
			if (socketToRemove(s) && s->server == &server && s->connection)
646228
				{ s->connection->close(ERR_CONNECTION_LOST); ++count; }
646228
	return count;
f07ad6
}
f07ad6
f07ad6
646228
int Protocol::stopServerReq(Server &server) {
646228
	Lock lock(mutex);
646228
	int count = 0;
646228
	if (started)
646228
		for(Socket *s = socketFirst(); s; s = socketNext(s))
9bbba5
			if (socketToRemove(s) && s->server == &server && s->connection)
646228
				{ s->connection->closeReq(); ++count; }
646228
	return count;
646228
}
646228
646228
646228
void Protocol::clean() {
646228
	assert(!socketFirst());
646228
	while(socketFirst()) delete socketFirst();
646228
	started = false;
646228
	stopRequested = false;
646228
	stopTimeUs = 0;
646228
}
646228
646228
646228
ErrorCode Protocol::start() {
646228
	Lock lockStartStop(mutexStartStop);
646228
	Lock lock(mutex);
646228
	stop();
646228
	
646228
	if (switching) return ERR_PROTOCOL_IS_SWITCHING;
646228
	
646228
	switching = true;
646228
	ErrorCode errorCode = onStart();
646228
	if (errorCode) clean(); else started = true;
646228
	switching = false;
646228
	
646228
	return errorCode;
646228
}
646228
646228
646228
void Protocol::stop(ErrorCode errorCode) {
646228
	Lock lockStartStop(mutexStartStop);
646228
	Lock lock(mutex);
646228
	if (!started || switching) return;
646228
	
646228
	switching = true;
646228
	int unfinishedConnections = 0;
646228
	for(Socket *s = socketFirst(); s; s = socketNext(s)) {
9bbba5
		if (!socketToRemove(s)) {
646228
			if (!s->server && s->connection) {
646228
				s->connection->close(ERR_CONNECTION_LOST);
646228
				++unfinishedConnections;
646228
			} else
646228
			if (s->server && !s->connection) {
646228
				s->server->stop(ERR_SERVER_LISTENING_LOST);
646228
				++unfinishedConnections;
646228
			}
646228
		}
646228
	}
646228
	if (!errorCode && unfinishedConnections) errorCode = ERR_PROTOCOL_UNFINISHED_CONNECTIONS;
646228
	onStop(errorCode);
646228
	clean();
646228
	switching = false;
646228
	
646228
	stopWaitCondition.notify_all();
646228
}
646228
646228
646228
void Protocol::stopReq() {
646228
	Lock lock(mutex);
2499ad
	if (!started || switching || stopRequested) return;
646228
	stopRequested = true;
646228
	for(Socket *s = socketFirst(); s; s = socketNext(s)) {
646228
		if (!(socketFlags(s) & Socket::REMOVED)) {
646228
			if (!s->server && s->connection)
646228
				s->connection->closeReq();
646228
			else
646228
			if (s->server && !s->connection)
646228
				s->server->stopReq();
646228
		}
646228
	}
9bbba5
	onStopRequested();
646228
}
646228
646228
646228
void Protocol::stopWait(unsigned long long timeoutUs, bool withRequest) {
646228
	std::unique_lock<mutex> uniqlock(mutex);</mutex>
646228
	
2499ad
	if (!started || switching) return;
646228
	if (withRequest) stopReq();
646228
	unsigned long long timeUs = monotonicTimeUs() + timeoutUs;
646228
	if (stopTimeUs > timeUs)
646228
		{ stopTimeUs = timeUs; stopWaitCondition.notify_all(); }
646228
	
646228
	while(started) {
646228
		unsigned long long timeUs = monotonicTimeUs();
646228
		if (timeUs >= stopTimeUs)
646228
			{ stop(); break; }
646228
		stopWaitCondition.wait_for(uniqlock, std::chrono::microseconds(stopTimeUs - timeUs));
646228
	}
646228
}
646228
646228
646228
ErrorCode Protocol::connect(const Connection::Handle &connection, const Address &address) {
646228
	if (!connection) return ERR_INVALID_ARGS;	
9bbba5
	Address resolvedAddress = address;
9bbba5
	ErrorCode errorCode = resolve(resolvedAddress);
9bbba5
	if (errorCode) return errorCode;
9bbba5
646228
	Lock lock(mutex);
646228
	if (!isFullActive()) return ERR_PROTOCOL_NOT_INITIALIZED;
9bbba5
	return onConnect(connection, resolvedAddress);
646228
}
646228
646228
646228
ErrorCode Protocol::listen(const Server::Handle &server, const Address &address) {
646228
	if (!server) return ERR_INVALID_ARGS;	
9bbba5
	Address resolvedAddress = address;
9bbba5
	ErrorCode errorCode = resolve(resolvedAddress);
9bbba5
	if (errorCode) return errorCode;
9bbba5
	
646228
	Lock lock(mutex);
646228
	if (!isFullActive()) return ERR_PROTOCOL_NOT_INITIALIZED;
9bbba5
	return onListen(server, resolvedAddress);
646228
}
646228
646228
646228
ErrorCode Protocol::resolve(Address&)
541903
	{ return ERR_ADDRESS_INCORRECT; }
646228
646228
646228
ErrorCode Protocol::onStart()
646228
	{ return ERR_NONE; }
9bbba5
void Protocol::onStopRequested()
646228
	{ }
9bbba5
void Protocol::onStop(ErrorCode)
646228
	{ }
9bbba5
void Protocol::onSocketChanged(Socket *socket)
9bbba5
	{ if (socketToRemove(socket)) socketRemove(socket); }
646228
ErrorCode Protocol::onConnect(const Connection::Handle&, const Address&)
f07ad6
	{ return ERR_CONNECTION_FAILED; }
646228
ErrorCode Protocol::onListen(const Server::Handle&, const Address&)
f07ad6
	{ return ERR_SERVER_LISTENING_FAILED; }
646228
646228