AES-DH Implementation
Loading...
Searching...
No Matches
network.h
1#pragma once
2
3#include <arpa/inet.h> // For Converting IP/Port into the right format.
4#include <sys/socket.h> // For sockets.
5#include <unistd.h> // For various functions.
6#include <string.h> // For strings.
7#include <poll.h> // For the poll function for timeouts.
8#include <stdexcept> // For exceptions.
9
13namespace network {
14
20 int sock = -1;
21
25 int connection = -1;
26
41 typedef enum {
42 ERROR, EMPTY, DATA, HMAC, NONCE, IV,
43 FINAL, MESSAGE, ACK, REFUSED, REEXCHANGE,
44 } meta;
45
46 // The size of the buffer
47 #define PACKET_SIZE 1024
48
56 typedef struct {
57 meta m = EMPTY; // Describe what the packet is.
58 char data[PACKET_SIZE] = {0}; // The actual data.
59 } packet;
60
61
68 int send_packet(const packet& p, const size_t& timeout=5) {
69 struct pollfd fd;
70 fd.fd = connection;
71 fd.events = POLLOUT;
72
73 switch (poll(&fd, 1, timeout * 1000)) {
74 case -1: case 0: return -1;
75 default: return send(connection, reinterpret_cast<const void*>(&p), sizeof(p), 0);
76 }
77 }
78
79
87 packet recv_packet(const size_t& timeout=5) {
88 packet p;
89 struct pollfd fd;
90 fd.fd = connection;
91 fd.events = POLLIN;
92
93 switch (poll(&fd, 1, timeout * 1000)) {
94 case -1: case 0: p.m = network::meta::ERROR; break;
95 default: recv(connection, reinterpret_cast<void*>(&p), sizeof(p), 0); break;
96 }
97 return p;
98 }
99
100
109 template <typename T> inline int send_value(const T& value, const network::meta& type = DATA, const size_t& timeout=5) {
110 packet p = {.m = type};
111
112 // Pack the value into a string.
113 std::stringstream in; in << value;
114 auto str = in.str();
115 if (str.length() > PACKET_SIZE) {
116 throw std::runtime_error("Value exceeds packet size!");
117 }
118 strncpy(&p.data[0], str.c_str(), PACKET_SIZE);
119
120 return send_packet(p, timeout);
121 }
122
123
131 template <typename T> inline const T recv_value(const size_t& timeout=5) {
132 auto p = recv_packet(timeout);
133 if (p.m = network::meta::ERROR) throw std::runtime_error("Failed to read from socket!");
134
135 // Get the value from the string.
136 auto str = std::string(&p.data[0], PACKET_SIZE);
137 T ret = {};
138 std::istringstream (str) >> ret;
139 return ret;
140 }
141
142
153 inline int send_string(const std::string& message, const network::meta& type = DATA, const size_t& timeout=5) {
154
155 // Send the length of the message, so that we can trim the string accordingly.
156 send_value<uint64_t>(message.length(), DATA, timeout);
157
158 // We'll reuse this packet with the correct type
159 packet p = {.m = type};
160 size_t x = 0;
161 p.data[0] = message[0];
162
163 // Simply increment through the message, and once we hit PACKET_SIZE,
164 // send the package before overwriting the old data.
165 for (x = 1; x < message.length(); ++x) {
166 if (x % PACKET_SIZE == 0) {
167 if (send_packet(p, timeout) == -1)
168 return -1;
169 }
170 p.data[x % PACKET_SIZE] = message[x];
171 }
172
173 // Fill the remainder of the packet with 0's (Since previous data will be there)
174 // And then send a FINAL packet.
175 p.m = FINAL;
176 while (x % PACKET_SIZE != 0) p.data[x++ % PACKET_SIZE] = 0;
177 if (send_packet(p, timeout) == -1)
178 return -1;
179 return 0;
180 }
181
182
188 inline std::string recv_string(const size_t& timeout=5) {
189
190 // Get the string ready, and receive the size.
191 std::string ret;
192 packet p;
193
194 auto length = recv_value<uint64_t>();
195
196 // Simply receive packets until the sender provides a FINAL packet.
197 while (true) {
198 p = recv_packet();
199 if (p.m == ERROR) throw std::runtime_error("Failure recieving packet!");
200
201 // Just append it.
202 ret.append(p.data, PACKET_SIZE);
203 if (p.m == FINAL) break;
204 }
205
206 // Trim to length and return.
207 return std::string(ret.c_str(), length);
208 }
209
210
220 void get_client(const int& port) {
221
222 // Make our socket.
223 if (sock == -1) {
224 sock = socket(AF_INET, SOCK_STREAM, 0);
225 if (sock == -1) return;
226
227 // Bind the socket
228 sockaddr_in serverAddress = {
229 .sin_family = AF_INET,
230 .sin_port = htons(port),
231 .sin_addr = {.s_addr = INADDR_ANY}
232 };
233
234 // The main socket has a 30 timeout.
235 // The connection socket
236 struct timeval timeout;
237 timeout.tv_sec = 30;
238 timeout.tv_usec = 0;
239 setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
240
241 if (bind(sock, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == -1) {
242 close(sock);
243 sock = -1;
244 return;
245 }
246 }
247
248 // We only have a single connection
249 if (listen(sock, 1) == -1) {
250 close(sock);
251 sock = -1;
252 return;
253 }
254
255 // Accept connections
256 sockaddr_in clientAddress;
257 socklen_t clientSize = sizeof(clientAddress);
258 connection = accept(sock, (struct sockaddr *)&clientAddress, &clientSize);
259 }
260
261
272 void get_server(const size_t& port, const char address[] = "127.0.0.1") {
273
274 // There is only one communication socket.
275 if (connection != -1)
276 close(connection);
277
278 connection = socket(AF_INET, SOCK_STREAM, 0);
279 if (connection == -1) return;
280
281 // Connect to the server
282 sockaddr_in serverAddress = {
283 .sin_family = AF_INET,
284 .sin_port = htons(port),
285 .sin_addr = {.s_addr = inet_addr(address)}
286 };
287
288 if (connect(connection, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) == -1) {
289 close(connection);
290 connection = -1;
291 }
292 }
293}
The namespace for communication along a socket.
Definition network.h:13
int send_packet(const packet &p, const size_t &timeout=5)
Send a packet.
Definition network.h:68
int sock
The FD sock for when the program is in Listen mode.
Definition network.h:20
std::string recv_string(const size_t &timeout=5)
Receive a string.
Definition network.h:188
int send_value(const T &value, const network::meta &type=DATA, const size_t &timeout=5)
Send a value.
Definition network.h:109
int connection
the FD sock that peers communicate over.
Definition network.h:25
int send_string(const std::string &message, const network::meta &type=DATA, const size_t &timeout=5)
Send a string of any size.
Definition network.h:153
const T recv_value(const size_t &timeout=5)
Receive a value.
Definition network.h:131
packet recv_packet(const size_t &timeout=5)
Receive a packet.
Definition network.h:87
void get_server(const size_t &port, const char address[]="127.0.0.1")
Try and connect to the server.
Definition network.h:272
void get_client(const int &port)
Listen on the socket for a client to initiate a connection.
Definition network.h:220
Definition network.h:56