This repository has been archived by the owner on Aug 27, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 14
/
Connection.hpp
129 lines (107 loc) · 3.71 KB
/
Connection.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#pragma once
/*
* Connection is a simple wrapper around a TCP socket connection.
* You don't create 'Connection' objects yourself, rather, you
* create a Client or Server object which will manage connection(s)
* for you.
* For example:
//simple server
int main(int argc, char **argv) {
Server server("1337"); //start a server on port 1337
while (true) {
server.poll([](Connection *connection, Connection::Event evt){
if (evt == Connection::OnRecv) {
//extract and erase data from the connection's recv_buffer:
std::vector< uint8_t > data = connection->recv_buffer;
connection->recv_buffer.clear();
//send to other connections:
}
},
1.0 //timeout (in seconds)
);
}
}
//simple client
int main(int argc, char **argv) {
Client client("localhost", "1337"); //connect to a local server at port 1337
while (true) {
client.poll([](Connection *connection, Connection::Event evt){
},
0.0 //timeout (in seconds)
);
}
}
*/
//NOTE: much of the sockets code herein is based on http-tweak's single-header http server
// see: https://github.com/ixchow/http-tweak
//--------- 'Socket' is of different types on different OS's -------
#ifdef _WIN32
// (this is a work-around so that we don't expose the rest of the code
// to the horrors of windows.h )
//on windows, 'Socket' will match 'SOCKET' / 'INVALID_SOCKET'
#ifdef _WIN64
typedef unsigned __int64 Socket;
#else
typedef unsigned int Socket;
#endif
constexpr const Socket InvalidSocket = (Socket)-1;
#else
//on linux, 'Socket' is just int and we'll use '-1' for an invalid value:
typedef int Socket;
constexpr const Socket InvalidSocket = -1;
#endif
//--------- ---------------------------------- ---------
#include <vector>
#include <list>
#include <string>
#include <functional>
#include <cstdint>
//Thin wrapper around a (polling-based) TCP socket connection:
struct Connection {
//Helper that will append any type to the send buffer:
template< typename T >
void send(T const &t) {
send_raw(&t, sizeof(T));
}
//Helper that will append raw bytes to the send buffer:
void send_raw(void const *data, size_t size) {
send_buffer.insert(send_buffer.end(), reinterpret_cast< uint8_t const * >(data), reinterpret_cast< uint8_t const * >(data) + size);
}
//Call 'close' to mark a connection for discard:
void close();
//so you can if(connection) ... to check for validity:
explicit operator bool() { return socket != InvalidSocket; }
//To send data over a connection, append it to send_buffer:
std::vector< uint8_t > send_buffer;
//When the connection receives data, it is appended to recv_buffer:
std::vector< uint8_t > recv_buffer;
//internals:
Socket socket = InvalidSocket;
enum Event {
OnOpen,
OnRecv,
OnClose
};
};
struct Server {
Server(std::string const &port); //pass the port number to listen on, as a string (servname, really)
//poll() updates the list of active connections and sends/receives data if possible:
// (will wait up to 'timeout' for first event)
void poll(
std::function< void(Connection *, Connection::Event event) > const &connection_event = nullptr,
double timeout = 0.0 //timeout (seconds)
);
std::list< Connection > connections;
Socket listen_socket = InvalidSocket;
};
struct Client {
Client(std::string const &host, std::string const &port);
//poll() checks the status of the active connection and sends/receives data if possible:
// (will wait up to 'timeout' for first event)
void poll(
std::function< void(Connection *, Connection::Event event) > const &connection_event = nullptr,
double timeout = 0.0 //timeout (seconds)
);
std::list< Connection > connections; //will only ever contain exactly one connection
Connection &connection; //reference to the only connection in the connections list
};