#ifndef CONNECTION_H
#define CONNECTION_H
#include <cassert>
#include <atomic>
#include <condition_variable>
#include "utils.h"
#define MAX_ADDR_SIZE 256
class Protocol;
class Server;
class Root {
public:
virtual ~Root() { }
};
class Connection: public Root {
public:
enum State: int {
STATE_NONE,
STATE_OPENING,
STATE_INITIALIZING,
STATE_RESOLVING,
STATE_CONNECTING,
STATE_OPEN,
STATE_CLOSE_REQ,
STATE_CLOSING,
STATE_CLOSED,
STATE_FINISHED
};
struct Task {
void *data;
size_t size;
size_t completion;
bool watch;
Task *next;
inline explicit Task(
void *data = nullptr,
size_t size = 0,
size_t completion = 0,
bool watch = false,
Task *next = nullptr
):
data(data), size(size), completion(completion), watch(watch), next(next)
{ assert(!!data == !!size); }
};
typedef CounteredQueueMISO<Task, &Task::next> TaskQueue;
private:
friend class Protocol;
std::atomic<State> state;
std::atomic<State> stateWanted;
ReadProtector stateProtector;
std::atomic<bool> enqueued;
std::atomic<bool> error;
std::atomic<int> closeWaiters;
std::atomic<int> finishWaiters;
std::condition_variable closeCondition;
unsigned char address[MAX_ADDR_SIZE];
size_t addressSize;
Protocol *protocol;
Server *server;
Connection *prev, *next;
Connection *srvPrev, *srvNext;
Connection *queueNext;
int sockId;
State stateLocal;
bool errorLocal;
std::atomic<unsigned int> events;
TaskQueue readQueue;
TaskQueue writeQueue;
void wantState(State state, bool error);
public:
typedef QueueMISO<Connection, &Connection::queueNext> Queue;
friend class QueueMISO<Connection, &Connection::queueNext>;
friend class ChainFuncs<Connection, &Connection::queueNext>;
public:
Connection();
virtual ~Connection();
bool open(Protocol &protocol, void *address, size_t addressSize, int sockId = -1, Server *server = nullptr);
void closeReq();
void close(bool error);
void closeWait(unsigned long long timeoutUs = 0, bool withReq = true, bool error = true);
bool read(Task &task);
bool write(Task &task);
protected:
virtual void onOpeningError();
virtual void onOpen(const void *address, size_t addressSize);
virtual bool onReadReady(Task &task, bool error);
virtual bool onWriteReady(Task &task, bool error);
virtual void onCloseReqested();
virtual void onClose(bool error);
};
#endif