|
|
91ef56 |
#ifndef TCP_H
|
|
|
91ef56 |
#define TCP_H
|
|
|
91ef56 |
|
|
|
91ef56 |
|
|
|
91ef56 |
#include <atomic></atomic>
|
|
|
91ef56 |
#include <thread></thread>
|
|
|
91ef56 |
#include <vector></vector>
|
|
|
0ea18d |
#include <list></list>
|
|
|
0ea18d |
#include <mutex></mutex>
|
|
|
91ef56 |
|
|
|
91ef56 |
#include "error.h"
|
|
|
91ef56 |
|
|
|
91ef56 |
|
|
|
91ef56 |
enum : ErrorCode {
|
|
|
91ef56 |
ERR_TCP_COMMON = ERR_TCP,
|
|
|
91ef56 |
ERR_TCP_RESOLVE_FAILED,
|
|
|
91ef56 |
ERR_TCP_BAD_ADDRESS,
|
|
|
91ef56 |
ERR_TCP_BAD_HANDLER,
|
|
|
91ef56 |
ERR_TCP_CONNECTION_FAILED,
|
|
|
91ef56 |
ERR_TCP_CONNECTION_LOST,
|
|
|
91ef56 |
ERR_TCP_LISTEN_FAILED,
|
|
|
91ef56 |
ERR_TCP_LISTEN_LOST,
|
|
|
91ef56 |
};
|
|
|
91ef56 |
|
|
|
91ef56 |
|
|
|
91ef56 |
namespace Tcp {
|
|
|
91ef56 |
|
|
|
91ef56 |
enum Status {
|
|
|
91ef56 |
STATUS_NONE,
|
|
|
91ef56 |
STATUS_OPEN,
|
|
|
91ef56 |
STATUS_CLOSED,
|
|
|
91ef56 |
STATUS_LOST,
|
|
|
91ef56 |
};
|
|
|
91ef56 |
|
|
|
91ef56 |
|
|
|
91ef56 |
typedef int SockId;
|
|
|
91ef56 |
|
|
|
91ef56 |
|
|
|
91ef56 |
class Address {
|
|
|
91ef56 |
public:
|
|
|
91ef56 |
unsigned char ip[4];
|
|
|
91ef56 |
unsigned short port;
|
|
|
91ef56 |
|
|
|
91ef56 |
inline Address():
|
|
|
91ef56 |
ip(), port() { }
|
|
|
91ef56 |
inline Address(unsigned char ip0, unsigned char ip1, unsigned char ip2, unsigned char ip3, unsigned short port):
|
|
|
91ef56 |
port(port) { ip[0] = ip0, ip[1] = ip1, ip[2] = ip2, ip[3] = ip3; }
|
|
|
91ef56 |
inline Address(unsigned char *ip, unsigned short port):
|
|
|
91ef56 |
Address(ip[0], ip[1], ip[2], ip[3], port) { }
|
|
|
91ef56 |
|
|
|
91ef56 |
inline bool isValidIp() const
|
|
|
91ef56 |
{ return ip[0] || ip[1] || ip[2] || ip[3]; }
|
|
|
91ef56 |
inline bool isValidPort() const
|
|
|
91ef56 |
{ return port; }
|
|
|
91ef56 |
inline bool isValid() const
|
|
|
91ef56 |
{ return isValidIp() && isValidPort(); }
|
|
|
91ef56 |
|
|
|
91ef56 |
ErrorCode resolve(const char *addrString);
|
|
|
91ef56 |
};
|
|
|
91ef56 |
|
|
|
91ef56 |
|
|
|
91ef56 |
class Connection {
|
|
|
91ef56 |
private:
|
|
|
91ef56 |
Status status;
|
|
|
91ef56 |
ErrorCode lastError;
|
|
|
91ef56 |
SockId sockId;
|
|
|
91ef56 |
Address remoteAddr;
|
|
|
91ef56 |
std::atomic<bool> stopping;</bool>
|
|
|
91ef56 |
|
|
|
91ef56 |
Connection(const Connection&) = delete;
|
|
|
91ef56 |
Connection& operator=(const Connection&) = delete;
|
|
|
91ef56 |
|
|
|
91ef56 |
public:
|
|
|
91ef56 |
Connection();
|
|
|
91ef56 |
Connection(SockId sockId, const Address &remoteAddr);
|
|
|
91ef56 |
~Connection();
|
|
|
91ef56 |
|
|
|
91ef56 |
inline Status getStatus() const
|
|
|
91ef56 |
{ return status; }
|
|
|
91ef56 |
ErrorCode getLastError() const
|
|
|
91ef56 |
{ return lastError; }
|
|
|
91ef56 |
inline SockId getSockId() const
|
|
|
91ef56 |
{ return sockId; }
|
|
|
91ef56 |
inline const Address& getRemoteAddr() const
|
|
|
91ef56 |
{ return remoteAddr; }
|
|
|
91ef56 |
|
|
|
91ef56 |
inline void stop()
|
|
|
91ef56 |
{ stopping = true; }
|
|
|
91ef56 |
inline bool check() {
|
|
|
91ef56 |
if (stopping) close(ERR_TCP_CONNECTION_LOST);
|
|
|
91ef56 |
return status == STATUS_OPEN;
|
|
|
91ef56 |
}
|
|
|
91ef56 |
|
|
|
91ef56 |
bool open(const Address &remoteAddr);
|
|
|
91ef56 |
void close(ErrorCode errorCode = ERR_NONE);
|
|
|
91ef56 |
|
|
|
91ef56 |
bool read(void *data, size_t size);
|
|
|
91ef56 |
bool write(const void *data, size_t size);
|
|
|
91ef56 |
};
|
|
|
91ef56 |
|
|
|
91ef56 |
|
|
|
91ef56 |
class Handler {
|
|
|
91ef56 |
public:
|
|
|
91ef56 |
virtual ~Handler();
|
|
|
91ef56 |
virtual void handleTcpConnection(Connection &connection) = 0;
|
|
|
91ef56 |
};
|
|
|
91ef56 |
|
|
|
91ef56 |
|
|
|
91ef56 |
class Server {
|
|
|
91ef56 |
public:
|
|
|
91ef56 |
struct ConnDesc {
|
|
|
91ef56 |
Connection *connection;
|
|
|
91ef56 |
std::thread *thread;
|
|
|
91ef56 |
};
|
|
|
0ea18d |
typedef std::list<conndesc> ConnList;</conndesc>
|
|
|
0ea18d |
typedef std::vector<conndesc> ConnVector;</conndesc>
|
|
|
91ef56 |
|
|
|
91ef56 |
private:
|
|
|
91ef56 |
Status status;
|
|
|
91ef56 |
ErrorCode lastError;
|
|
|
91ef56 |
SockId sockId;
|
|
|
91ef56 |
Address localAddr;
|
|
|
91ef56 |
Handler *handler;
|
|
|
91ef56 |
std::thread *thread;
|
|
|
91ef56 |
std::atomic<bool> stopping;</bool>
|
|
|
91ef56 |
|
|
|
0ea18d |
std::mutex connectionsMutex;
|
|
|
0ea18d |
ConnList connections;
|
|
|
0ea18d |
ConnVector connectionsFinished;
|
|
|
0ea18d |
|
|
|
91ef56 |
Server(const Server&) = delete;
|
|
|
91ef56 |
Server& operator=(const Server&) = delete;
|
|
|
91ef56 |
|
|
|
0ea18d |
void cleanConnections();
|
|
|
0ea18d |
void handleConnection(ConnList::iterator iter);
|
|
|
91ef56 |
void listen();
|
|
|
91ef56 |
|
|
|
91ef56 |
public:
|
|
|
91ef56 |
Server();
|
|
|
91ef56 |
~Server();
|
|
|
91ef56 |
|
|
|
91ef56 |
inline Status getStatus() const
|
|
|
91ef56 |
{ return status; }
|
|
|
91ef56 |
ErrorCode getLastError() const
|
|
|
91ef56 |
{ return lastError; }
|
|
|
91ef56 |
inline SockId getSockId() const
|
|
|
91ef56 |
{ return sockId; }
|
|
|
91ef56 |
inline const Address& getLocalAddr() const
|
|
|
91ef56 |
{ return localAddr; }
|
|
|
91ef56 |
inline Handler* getHandler() const
|
|
|
91ef56 |
{ return handler; }
|
|
|
91ef56 |
|
|
|
91ef56 |
inline bool check()
|
|
|
91ef56 |
{ return !stopping && status == STATUS_OPEN; }
|
|
|
91ef56 |
|
|
|
91ef56 |
bool start(const Address &localAddr, Handler *handler);
|
|
|
91ef56 |
void join();
|
|
|
91ef56 |
void stop();
|
|
|
91ef56 |
};
|
|
|
91ef56 |
|
|
|
91ef56 |
} // Tcp
|
|
|
91ef56 |
|
|
|
91ef56 |
#endif
|