SocketStreams v1.11.1
Loading...
Searching...
No Matches
Network.h
Go to the documentation of this file.
1#pragma once
2
3#include <iostream>
4#include <vector>
5#include <queue>
6#include <string>
7#include <any>
8#include <memory>
9#include <chrono>
10
11#ifdef __LINUX__
12#include <sys/types.h>
13#include <sys/socket.h>
14#include <sys/ioctl.h>
15#include <netdb.h>
16#include <unistd.h>
17#include <netinet/in.h>
18#else
19#include <WinSock2.h>
20#include <WS2tcpip.h>
21#endif // __LINUX__
22
23#include "WebException.h"
24#include "ContainerWrapper.h"
25
26#ifndef __LINUX__
27#pragma comment (lib, "ws2_32.lib")
28#endif // !__LINUX__
29
30#ifdef __LINUX__
31#ifndef WINDOWS_STYLE_DEFINITION
32#define WINDOWS_STYLE_DEFINITION
33
34#define closesocket close
35#define SOCKET int
36#define INVALID_SOCKET -1
37#define SOCKET_ERROR -1
38#define DWORD uint32_t
39
40#endif // WINDOWS_STYLE_DEFINITION
41#endif // __LINUX__
42
43namespace web
44{
45 template<typename T>
46 concept Timeout = requires(T value)
47 {
48 { std::chrono::duration_cast<std::chrono::milliseconds>(value) };
49 };
50
51 using namespace std::chrono_literals;
52
54 class Network
55 {
56 protected:
57 std::shared_ptr<SOCKET> handle;
58 std::queue<std::string_view> buffers;
59
60 protected:
61 virtual int sendBytesImplementation(const char* data, int size, int flags = 0);
62
63 virtual int receiveBytesImplementation(char* data, int size, int flags = 0);
64
65 virtual void throwException(int line, std::string_view file) const;
66
67 protected:
68 void setTimeout(int64_t timeout);
69
70 protected:
71 Network(std::string_view ip, std::string_view port, int64_t timeout);
72
73 public:
79 template<Timeout T = std::chrono::seconds>
80 Network(std::string_view ip, std::string_view port, T timeout = 30s);
81
84 template<Timeout T = std::chrono::seconds>
85 Network(SOCKET clientSocket, T timeout = 30s);
86
91 bool isDataAvailable(int* availableBytes = nullptr) const;
92
99 virtual int sendData(const utility::ContainerWrapper& data, bool& endOfStream, int flags = 0);
100
107 virtual int sendRawData(const char* data, int size, bool& endOfStream, int flags = 0);
108
115 virtual int receiveData(utility::ContainerWrapper& data, bool& endOfStream, int flags = 0);
116
123 virtual int receiveRawData(char* data, int size, bool& endOfStream, int flags = 0);
124
128 virtual void log(const std::string& message, std::any&& data = "");
129
134 void addReceiveBuffer(std::string_view buffer);
135
138 SOCKET getClientSocket() const;
139
148 template<typename DataT>
149 int sendBytes(const DataT* data, int size, bool& endOfStream, int flags = 0);
150
159 template<typename DataT>
160 int receiveBytes(DataT* data, int size, bool& endOfStream, int flags = 0);
161
162 virtual ~Network() = default;
163 };
164
165 template<Timeout T>
166 Network::Network(std::string_view ip, std::string_view port, T timeout) :
167 Network(ip, port, std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count())
168 {
169
170 }
171
172 template<Timeout T>
173 Network::Network(SOCKET clientSocket, T timeout)
174 {
175#ifndef __LINUX__
176 WSADATA wsaData;
177
178 if (WSAStartup(MAKEWORD(2, 2), &wsaData))
179 {
181 }
182#endif // !__LINUX__
183
184 handle = std::shared_ptr<SOCKET>(new SOCKET(clientSocket), [](SOCKET* ptr) { closesocket(*ptr); delete ptr; });
185
186 this->setTimeout(std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count());
187 }
188
189 template<typename DataT>
190 int Network::sendBytes(const DataT* data, int size, bool& endOfStream, int flags)
191 {
192 int lastSend = 0;
193 int totalSent = 0;
194
195 endOfStream = false;
196
197 do
198 {
199 lastSend = this->sendBytesImplementation(reinterpret_cast<const char*>(data) + totalSent, size - totalSent, flags);
200
201 if (lastSend == SOCKET_ERROR)
202 {
203 this->throwException(__LINE__, __FILE__);
204 }
205 else if (!lastSend)
206 {
207 endOfStream = true;
208
209 return totalSent;
210 }
211
212 totalSent += lastSend;
213 } while (totalSent < size);
214
215 return totalSent;
216 }
217
218 template<typename DataT>
219 int Network::receiveBytes(DataT* data, int size, bool& endOfStream, int flags)
220 {
221 int receive = 0;
222 char* actualData = reinterpret_cast<char*>(data);
223
224 while (buffers.size())
225 {
226 std::string_view receiveBuffer = buffers.front();
227 int fromBufferSize = std::min<int>(static_cast<int>(receiveBuffer.size()), size);
228
229 std::copy(receiveBuffer.data(), receiveBuffer.data() + fromBufferSize, actualData);
230
231 receiveBuffer = std::string_view(receiveBuffer.data() + fromBufferSize, receiveBuffer.size() - fromBufferSize);
232
233 actualData += fromBufferSize;
234 receive += fromBufferSize;
235 size -= fromBufferSize;
236
237 if (receiveBuffer.empty())
238 {
239 buffers.pop();
240 }
241 }
242
243 if (size)
244 {
245 receive += this->receiveBytesImplementation(actualData, size, flags);
246 }
247
248 endOfStream = !static_cast<bool>(receive);
249
250 if (receive == SOCKET_ERROR)
251 {
252 this->throwException(__LINE__, __FILE__);
253 }
254
255 return receive;
256 }
257}
#define THROW_WEB_EXCEPTION
Definition WebException.h:46
Base network class.
Definition Network.h:55
void addReceiveBuffer(std::string_view buffer)
Add additional data that uses before getting bytes from network.
Definition Network.cpp:211
virtual int receiveRawData(char *data, int size, bool &endOfStream, int flags=0)
Receive data through network.
Definition Network.cpp:184
virtual ~Network()=default
virtual int sendRawData(const char *data, int size, bool &endOfStream, int flags=0)
Send raw data through network.
Definition Network.cpp:136
bool isDataAvailable(int *availableBytes=nullptr) const
Check if Network contains data.
Definition Network.cpp:88
virtual int receiveData(utility::ContainerWrapper &data, bool &endOfStream, int flags=0)
Receive data through network.
Definition Network.cpp:157
std::shared_ptr< SOCKET > handle
Definition Network.h:57
int sendBytes(const DataT *data, int size, bool &endOfStream, int flags=0)
Send raw bytes through network.
Definition Network.h:190
virtual void log(const std::string &message, std::any &&data="")
Errors logging, default implementation uses clog.
Definition Network.cpp:216
std::queue< std::string_view > buffers
Definition Network.h:58
int receiveBytes(DataT *data, int size, bool &endOfStream, int flags=0)
Definition Network.h:219
virtual int sendBytesImplementation(const char *data, int size, int flags=0)
Definition Network.cpp:5
virtual void throwException(int line, std::string_view file) const
Definition Network.cpp:15
virtual int sendData(const utility::ContainerWrapper &data, bool &endOfStream, int flags=0)
Send data through network.
Definition Network.cpp:114
void setTimeout(int64_t timeout)
Definition Network.cpp:20
virtual int receiveBytesImplementation(char *data, int size, int flags=0)
Definition Network.cpp:10
SOCKET getClientSocket() const
clientSocket getter
Definition Network.cpp:221
Network(std::string_view ip, std::string_view port, int64_t timeout)
Definition Network.cpp:42
Wrap Container concept instance.
Definition ContainerWrapper.h:27
Definition Network.h:46
Definition BufferArray.cpp:11
Definition ContainerWrapper.cpp:4