Blame server.cpp

71057f
71057f
#include <cstring></cstring>
71057f
71057f
#include <chrono></chrono>
71057f
#include <thread></thread>
71057f
#include <mutex></mutex>
71057f
b42f0a
#include <unistd.h></unistd.h>
b42f0a
#include <sys types.h=""></sys>
b42f0a
#include <sys socket.h=""></sys>
b42f0a
#include <sys epoll.h=""></sys>
b42f0a
#include <netinet in.h=""></netinet>
b42f0a
71057f
#include "protocol.h"
71057f
#include "server.h"
71057f
71057f
61c265
#define DebugMSG ShowDebugMSG
61c265
61c265
71057f
Server::Server():
b42f0a
	connFirst(), connLast()
71057f
	{ }
71057f
71057f
b42f0a
Server::~Server()
b42f0a
	{ destroy();} 
71057f
71057f
b42f0a
bool Server::open(Protocol &protocol, void *address, size_t addressSize)
b42f0a
	{ OpenLock lock(*this, protocol, address, addressSize); return lock.success; }
71057f
71057f
b42f0a
void Server::handleDisconnect(Connection &connection, bool error) {
b42f0a
	onDisconnect(&connection, error);
b42f0a
	if (!connFirst && stateLocal == STATE_CLOSING_CONNECTIONS) {
b42f0a
		DebugMSG("to closing");
b42f0a
		state = stateLocal = STATE_CLOSING;
b42f0a
		stateProtector.wait();
b42f0a
		onClose(error);
b42f0a
		enqueue();
b42f0a
	}
71057f
}
71057f
71057f
b42f0a
void Server::handleState() {
b42f0a
	if (stateLocal == STATE_NONE) {
b42f0a
		DebugMSG("none");
b42f0a
		int sockId = -1;
b42f0a
		if (addressSize >= sizeof(sa_family_t)) {
b42f0a
			struct sockaddr *addr = (struct sockaddr*)address;
b42f0a
			sockId = ::socket(addr->sa_family, SOCK_STREAM, 0);
b42f0a
			if (sockId >= 0) {
b42f0a
				initSocket(sockId);
b42f0a
				if ( 0 != ::bind(sockId, addr, (int)addressSize)
b42f0a
					|| 0 != ::listen(sockId, 128) )
b42f0a
				{
b42f0a
					DebugMSG("cannot bind/listen");
b42f0a
					::close(sockId);
b42f0a
					sockId = -1;
b42f0a
				}
b42f0a
			} else {
b42f0a
				DebugMSG("cannot create socket");
b42f0a
			}
b42f0a
		}
b42f0a
		
b42f0a
		if (sockId >= 0) {
b42f0a
			DebugMSG("to open");
b42f0a
			prev = protocol->sockLast;
b42f0a
			(prev ? prev->next : protocol->sockFirst) = this;
b42f0a
			this->sockId = sockId;
b42f0a
			
b42f0a
			updateEvents(true, false);
b42f0a
			
b42f0a
			state = stateLocal = STATE_OPEN;
b42f0a
			stateProtector.wait();
b42f0a
			onOpen(address, addressSize);
b42f0a
		} else {
b42f0a
			DebugMSG("opening error -> to closed");
b42f0a
			onOpeningError();
b42f0a
			state = STATE_CLOSED;
b42f0a
			while(closeWaiters > 0)
b42f0a
				{ closeCondition.notify_all(); std::this_thread::yield(); }
b42f0a
			state = STATE_FINISHED;
b42f0a
			DebugMSG("opening error -> finished");
b42f0a
		}
71057f
	} else {
b42f0a
		State sw = stateWanted;
b42f0a
		if ( stateLocal == STATE_OPEN
b42f0a
		  && sw == STATE_CLOSE_REQ )
b42f0a
		{
b42f0a
			DebugMSG("to close req");
b42f0a
			for(Connection *conn = connFirst; conn; conn = conn->srvNext)
b42f0a
				conn->closeReq();
b42f0a
			updateEvents(false, false);
b42f0a
			state = stateLocal = STATE_CLOSE_REQ;
b42f0a
			stateProtector.wait();
b42f0a
			onCloseReqested();
b42f0a
		}
71057f
		
b42f0a
		if ( stateLocal >= STATE_OPEN
b42f0a
		  && stateLocal <= STATE_CLOSE_REQ
b42f0a
		  && sw == STATE_CLOSING )
71057f
		{
b42f0a
			DebugMSG("to closing connections");
b42f0a
			updateEvents(false, false);
b42f0a
			if (connFirst) {
b42f0a
				for(Connection *conn = connFirst; conn; conn = conn->srvNext)
b42f0a
					conn->close(true);
b42f0a
				state = stateLocal = STATE_CLOSING_CONNECTIONS;
b42f0a
				stateProtector.wait();
b42f0a
			} else {
b42f0a
				DebugMSG("to closing");
b42f0a
				state = stateLocal = STATE_CLOSING;
b42f0a
				stateProtector.wait();
b42f0a
				onClose(error);
71057f
			}
71057f
		}
71057f
		
b42f0a
		if ( stateLocal == STATE_CLOSING && !enqueued ) {
b42f0a
			DebugMSG("to closed");
b42f0a
			if (sockId >= 0) {
b42f0a
				struct epoll_event event = {};
b42f0a
				epoll_ctl(protocol->epollFd, EPOLL_CTL_DEL, sockId, &event);
b42f0a
				::close(sockId);
b42f0a
				sockId = -1;
b42f0a
			}
b42f0a
			events = 0xffffffff;
b42f0a
			(prev ? prev->next : protocol->sockFirst) = next;
b42f0a
			(next ? next->prev : protocol->sockLast ) = prev;
b42f0a
			protocol = nullptr;
b42f0a
			memset(this->address, 0, sizeof(address));
b42f0a
			addressSize = 0;
b42f0a
			stateWanted = STATE_NONE;
b42f0a
			stateLocal = STATE_NONE;
b42f0a
			DebugMSG("closeWaiters");
b42f0a
			state = STATE_CLOSED;
b42f0a
			while(closeWaiters > 0)
b42f0a
				{ closeCondition.notify_all(); std::this_thread::yield(); }
b42f0a
			state = STATE_FINISHED;
b42f0a
			DebugMSG("finished");
b42f0a
		}
b42f0a
	}
b42f0a
}
b42f0a
b42f0a
b42f0a
void Server::handleEvents(unsigned int events) {
b42f0a
	if (events & (EPOLLHUP | EPOLLERR)) {
b42f0a
		if ( stateLocal >= STATE_OPEN
b42f0a
		  && stateLocal < STATE_CLOSING )
b42f0a
			close((bool)(events & EPOLLERR));
b42f0a
		return;
71057f
	}
71057f
	
b42f0a
	if (events & EPOLLIN) {
b42f0a
		if ( stateLocal >= STATE_OPEN
b42f0a
		  && stateLocal < STATE_CLOSE_REQ)
b42f0a
		{
b42f0a
			unsigned char address[MAX_ADDR_SIZE] = {};
b42f0a
			socklen_t len = sizeof(address);
b42f0a
			int res = ::accept(sockId, (struct sockaddr*)address, &len);
b42f0a
			assert(len < sizeof(address));
b42f0a
			if (res >= 0)
b42f0a
				if (Connection *conn = onConnect(address, len))
b42f0a
					if (!conn->open(*protocol, address, len, res, this))
b42f0a
						onDisconnect(conn, true);
b42f0a
		}
b42f0a
	}
71057f
}
71057f
71057f
b42f0a
51b3f0
Connection* Server::onConnect(const void*, size_t) { return nullptr; }
71057f
void Server::onDisconnect(Connection*, bool) { }
71057f