|
|
b42f0a |
#ifndef SOCKET_H
|
|
|
b42f0a |
#define SOCKET_H
|
|
|
b42f0a |
|
|
|
b42f0a |
|
|
|
b42f0a |
#include <cassert></cassert>
|
|
|
b42f0a |
|
|
|
b42f0a |
#include <atomic></atomic>
|
|
|
b42f0a |
#include <condition_variable></condition_variable>
|
|
|
b42f0a |
|
|
|
b42f0a |
#include "utils.h"
|
|
|
b42f0a |
|
|
|
b42f0a |
|
|
|
b42f0a |
#define MAX_ADDR_SIZE 256
|
|
|
b42f0a |
|
|
|
b42f0a |
|
|
|
b42f0a |
|
|
|
b42f0a |
enum State: int {
|
|
|
b42f0a |
STATE_NONE,
|
|
|
b42f0a |
STATE_OPENING,
|
|
|
b42f0a |
STATE_INITIALIZING,
|
|
|
b42f0a |
STATE_RESOLVING,
|
|
|
b42f0a |
STATE_CONNECTING,
|
|
|
b42f0a |
STATE_OPEN,
|
|
|
b42f0a |
STATE_CLOSE_REQ,
|
|
|
b42f0a |
STATE_CLOSING_CONNECTIONS,
|
|
|
b42f0a |
STATE_CLOSING,
|
|
|
b42f0a |
STATE_CLOSED,
|
|
|
b42f0a |
STATE_FINISHED,
|
|
|
b42f0a |
STATE_DESTROYED
|
|
|
b42f0a |
};
|
|
|
b42f0a |
|
|
|
b42f0a |
|
|
|
b42f0a |
class Protocol;
|
|
|
b42f0a |
class Connection;
|
|
|
b42f0a |
class Server;
|
|
|
b42f0a |
|
|
|
b42f0a |
|
|
|
b42f0a |
class Socket {
|
|
|
b42f0a |
private:
|
|
|
b42f0a |
friend class Protocol;
|
|
|
b42f0a |
friend class Connection;
|
|
|
b42f0a |
friend class Server;
|
|
|
b42f0a |
|
|
|
b42f0a |
std::atomic<state> state;</state>
|
|
|
b42f0a |
std::atomic<state> stateWanted;</state>
|
|
|
b42f0a |
ReadProtector stateProtector;
|
|
|
b42f0a |
std::atomic<bool> enqueued;</bool>
|
|
|
b42f0a |
std::atomic<bool> error;</bool>
|
|
|
b42f0a |
|
|
|
b42f0a |
std::atomic<int> closeWaiters;</int>
|
|
|
b42f0a |
std::atomic<int> finishWaiters;</int>
|
|
|
b42f0a |
std::condition_variable closeCondition;
|
|
|
b42f0a |
|
|
|
b42f0a |
unsigned char address[MAX_ADDR_SIZE];
|
|
|
b42f0a |
size_t addressSize;
|
|
|
b42f0a |
|
|
|
b42f0a |
Protocol *protocol;
|
|
|
b42f0a |
Socket *prev, *next;
|
|
|
b42f0a |
Socket *queueNext;
|
|
|
b42f0a |
int sockId;
|
|
|
b42f0a |
State stateLocal;
|
|
|
b42f0a |
|
|
|
b42f0a |
std::atomic<unsigned int=""> events;</unsigned>
|
|
|
b42f0a |
|
|
|
b42f0a |
struct OpenLock {
|
|
|
b42f0a |
Socket &socket;
|
|
|
b42f0a |
const bool success;
|
|
|
b42f0a |
OpenLock(Socket &socket, Protocol &protocol, void *address, size_t addressSize):
|
|
|
b42f0a |
socket(socket), success(socket.openBegin(protocol, address, addressSize)) { }
|
|
|
b42f0a |
~OpenLock()
|
|
|
b42f0a |
{ if (success) socket.openEnd(); }
|
|
|
b42f0a |
};
|
|
|
b42f0a |
|
|
|
b42f0a |
bool openBegin(Protocol &protocol, void *address, size_t addressSize);
|
|
|
b42f0a |
void openEnd();
|
|
|
b42f0a |
|
|
|
b42f0a |
void initSocket(int sockId);
|
|
|
b42f0a |
void enqueue();
|
|
|
b42f0a |
void updateEvents(bool wantRead, bool wantWrite);
|
|
|
b42f0a |
void wantState(State state, bool error);
|
|
|
b42f0a |
|
|
|
b42f0a |
void destroy();
|
|
|
b42f0a |
|
|
|
b42f0a |
public:
|
|
|
b42f0a |
typedef QueueMISO<socket, &socket::queuenext=""> Queue;</socket,>
|
|
|
b42f0a |
friend class QueueMISO<socket, &socket::queuenext="">;</socket,>
|
|
|
b42f0a |
friend class ChainFuncs<socket, &socket::queuenext="">;</socket,>
|
|
|
b42f0a |
|
|
|
b42f0a |
public:
|
|
|
b42f0a |
Socket();
|
|
|
b42f0a |
virtual ~Socket();
|
|
|
b42f0a |
|
|
|
b42f0a |
void closeReq();
|
|
|
b42f0a |
void close(bool error);
|
|
|
b42f0a |
void closeWait(unsigned long long timeoutUs = 0, bool withReq = true, bool error = true);
|
|
|
b42f0a |
|
|
|
b42f0a |
private:
|
|
|
b42f0a |
virtual void handleState() = 0;
|
|
|
b42f0a |
virtual void handleEvents(unsigned int events) = 0;
|
|
|
b42f0a |
|
|
|
b42f0a |
protected:
|
|
|
b42f0a |
virtual void onOpeningError();
|
|
|
b42f0a |
virtual void onOpen(const void *address, size_t addressSize);
|
|
|
b42f0a |
virtual void onCloseReqested();
|
|
|
b42f0a |
virtual void onClose(bool error);
|
|
|
b42f0a |
};
|
|
|
b42f0a |
|
|
|
b42f0a |
|
|
|
b42f0a |
#endif
|