]> git.localhorst.tv Git - blank.git/blob - src/net/tcp.hpp
somewhat self-cleaning temp dir
[blank.git] / src / net / tcp.hpp
1 #ifndef BLANK_NET_TCP_HPP_
2 #define BLANK_NET_TCP_HPP_
3
4 #include <algorithm>
5 #include <list>
6 #include <SDL_net.h>
7 #include <string>
8
9
10 namespace blank {
11 namespace tcp {
12
13 /// all failing functions throw NetError
14 class Socket {
15
16 public:
17         /// create an empty socket that is not connected to anything
18         Socket();
19         /// create TCP socket bound to given port
20         explicit Socket(unsigned short port);
21         /// connect to given host:port
22         Socket(const std::string &host, unsigned short port);
23 private:
24         /// wrap given SDLNet TCP socket
25         /// for use with Accept()
26         explicit Socket(TCPsocket sock);
27 public:
28         ~Socket() noexcept;
29
30         Socket(const Socket &) = delete;
31         Socket &operator =(const Socket &) = delete;
32
33         Socket(Socket &&) noexcept;
34         Socket &operator =(Socket &&) noexcept;
35
36         explicit operator bool() const noexcept { return sock; }
37
38         bool operator ==(const Socket &other) const noexcept {
39                 return sock == other.sock;
40         }
41         bool operator <(const Socket &other) const noexcept {
42                 return sock < other.sock;
43         }
44
45 public:
46         /// create a socket for an incoming connection
47         /// @return an empty socket if there are none
48         Socket Accept() noexcept;
49         /// check if there is data available to read
50         bool Ready() const noexcept;
51         /// receive data into given buffer
52         /// @return number of bytes read, at most max_len
53         /// non-blocking if Ready() is true
54         std::size_t Recv(void *buf, std::size_t max_len);
55         /// send data from given buffer, at most max_len bytes
56         /// @return number of bytes written
57         ///         may be less than len as soon as I get to
58         ///         making it non-blocking
59         std::size_t Send(const void *buf, std::size_t max_len);
60
61         int AddTo(SDLNet_SocketSet);
62         int RemoveFrom(SDLNet_SocketSet);
63
64 private:
65         TCPsocket sock;
66
67 };
68
69
70 struct IOHandler {
71
72         virtual ~IOHandler() = default;
73
74         void Close() noexcept { closed = true; }
75         bool Closed() const noexcept { return closed; }
76
77         virtual void OnCreate(Socket &) { }
78         virtual void OnRemove(Socket &) noexcept { }
79
80         virtual void OnSend(Socket &) { };
81         virtual void OnRecv(Socket &) { };
82         virtual void OnError(Socket &) noexcept { Close(); }
83
84 private:
85         bool closed = false;
86
87 };
88
89
90 class Pool {
91
92 public:
93         using ConnectionSet = std::list<std::pair<Socket, IOHandler *>>;
94
95 public:
96         explicit Pool(int max_conn = 32, std::size_t buf_siz = 1500);
97         ~Pool() noexcept;
98
99         Pool(const Pool &) = delete;
100         Pool &operator =(const Pool &) = delete;
101
102 public:
103         void AddConnection(Socket, IOHandler *);
104         void Send();
105         bool Check(unsigned long timeout);
106         void Receive();
107         void Clean();
108
109         int FreeSlots() const noexcept { return max_conn - use_conn; }
110         int OccupiedSlots() const noexcept { return use_conn; }
111         int TotalSlots() const noexcept { return max_conn; }
112         /// reallocate the pool to accomodate at least new_max sockets
113         void Resize(int new_max);
114
115 private:
116         SDLNet_SocketSet set;
117         ConnectionSet connections;
118         int use_conn;
119         int max_conn;
120         std::size_t buf_siz;
121
122 };
123
124 }
125 }
126
127 #endif