#include "protocol.h"
#include "server.h"
#include "connection.h"
Socket::Socket(
Protocol &protocol,
const Connection::Handle &connection,
const Server::Handle &server,
const Address &address
):
protocol(protocol), connection(connection), server(server), address(address),
flags(CREATED), prev(), next(), chPrev(), chNext()
{
prev = protocol.last;
(prev ? prev->next : protocol.first) = this;
setChanged(true);
}
Socket::~Socket() {
setChanged(false);
(prev ? prev->next : protocol.first) = next;
(next ? next->prev : protocol.last) = prev;
prev = next = nullptr;
}
void Socket::setChanged(bool changed) {
if ((bool)(flags & CHANGED) == changed) return;
if (changed) {
flags |= CHANGED;
chPrev = protocol.chLast;
(chPrev ? chPrev->chNext : protocol.chFirst) = this;
protocol.wakeup();
} else {
flags &= ~CHANGED;
(chPrev ? chPrev->chNext : protocol.chFirst) = chNext;
(chNext ? chNext->chPrev : protocol.chLast) = chPrev;
chPrev = chNext = nullptr;
}
}
void Socket::setWantRead(bool want) {
Protocol::Lock lock(protocol.mutex);
if ((bool)(flags & WANTREAD) == want) return;
flags = want ? flags | WANTREAD : flags & ~WANTREAD;
setChanged(true);
}
void Socket::setWantWrite(bool want) {
Protocol::Lock lock(protocol.mutex);
if ((bool)(flags & WANTWRITE) == want) return;
flags = want ? flags | WANTWRITE : flags & ~WANTWRITE;
setChanged(true);
}
void Socket::finalize() {
Protocol::Lock lock(protocol.mutex);
if (flags & REMOVED) return;
flags |= REMOVED;
setChanged(true);
}
Protocol::Protocol():
first(), last(), chFirst(), chLast() { }
Protocol::~Protocol()
{ assert(!first); }
void Protocol::connectionOpen(const Connection::Handle &connection, Socket *socket) {
assert(connection && socket);
connection->open(socket);
}
void Protocol::closeAll() {
Lock lock(mutex);
while(first)
if (first->connection) first->connection->close(); else
if (first->server) first->server->close(); else
first->finalize();
}
void Protocol::wakeup()
{ }
ErrorCode Protocol::resolve(Address&)
{ return ERR_ADDRESS_INCORRECT; }
ErrorCode Protocol::connect(const Connection::Handle&, const Address&)
{ return ERR_CONNECTION_FAILED; }
ErrorCode Protocol::listen(const Server::Handle&, const Address&)
{ return ERR_SERVER_LISTENING_FAILED; }