-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathevilsocket.cc
143 lines (124 loc) · 3.6 KB
/
evilsocket.cc
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "evilsocket.h"
#include <memory>
errno_t es_init() {
WSADATA wsaData{};
return WSAStartup(MAKEWORD(2, 2), &wsaData);
}
void es_deinit() {
WSACleanup();
}
errno_t es_last_error() {
return WSAGetLastError();
}
std::string es_error_message(errno_t error_code) {
char* s = NULL;
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, error_code,
MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
(LPSTR)&s, 0, NULL);
std::string string(s);
LocalFree(s);
return string;
}
SOCKET es_connect(const std::string& host, int port, int keepalivems) {
SOCKET handle = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (handle == INVALID_SOCKET) {
return INVALID_SOCKET;
}
SOCKADDR_IN serverAddress{};
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = inet_addr(host.c_str());
serverAddress.sin_port = htons(port);
auto res = connect(handle, reinterpret_cast<SOCKADDR*>(&serverAddress), sizeof(serverAddress));
if (res != 0)
return INVALID_SOCKET;
char keepalive = 1;
if (setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)) == SOCKET_ERROR) {
return handle;
}
tcp_keepalive alivein{};
alivein.onoff = true;
alivein.keepalivetime = keepalivems;
alivein.keepaliveinterval = keepalivems;
tcp_keepalive aliveout{};
unsigned long buffer = 0;
if (WSAIoctl(handle, SIO_KEEPALIVE_VALS, &alivein, sizeof(alivein), &aliveout, sizeof(aliveout), &buffer, nullptr, nullptr) == SOCKET_ERROR) {
return handle;
}
return handle;
}
void es_close(SOCKET handle) {
if (handle != INVALID_SOCKET)
closesocket(handle);
}
size_t es_write_string(SOCKET handle, const std::string& string) {
if (handle == INVALID_SOCKET) {
WSASetLastError(ERROR_INVALID_HANDLE);
return 0;
}
if (string.length() == 0) {
WSASetLastError(0);
return 0;
}
auto res = send(handle, string.c_str(), string.length(), 0);
if (res == SOCKET_ERROR) {
return 0;
}
return res;
}
std::string es_recv_string(SOCKET handle, int limit) {
if (handle == INVALID_SOCKET) {
WSASetLastError(WSA_INVALID_HANDLE);
return std::string();
}
auto buffer = std::make_unique<char[]>(limit + 1);
buffer[limit] = 0;
auto res = recv(handle, buffer.get(), limit, 0);
if (res == SOCKET_ERROR) {
return std::string();
}
auto string = std::string(buffer.get());
return std::move(string);
}
std::string es_recv_string(SOCKET handle, char terminator) {
if (handle == INVALID_SOCKET) {
WSASetLastError(WSA_INVALID_HANDLE);
return std::string();
}
char buffer = 0;
std::string string;
do {
auto res = recv(handle, &buffer, 1, 0);
if (res == SOCKET_ERROR) {
break;
}
if (buffer != terminator)
string += buffer;
} while (buffer != terminator);
return std::move(string);
}
SOCKET es_listen(int port, int backlog) {
SOCKET handle = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (handle == INVALID_SOCKET) {
return INVALID_SOCKET;
}
SOCKADDR_IN serverAddress{};
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = INADDR_ANY;
serverAddress.sin_port = htons(port);
auto res = bind(handle, reinterpret_cast<SOCKADDR*>(&serverAddress), sizeof(serverAddress));
if (res == SOCKET_ERROR) {
return INVALID_SOCKET;
}
listen(handle, backlog);
return handle;
}
std::pair<SOCKADDR_IN, SOCKET> es_accept(SOCKET handle, int keepalivesec, bool wait) {
SOCKADDR_IN clientAddress{};
int len = sizeof(clientAddress);
if (handle == INVALID_SOCKET) {
WSASetLastError(WSA_INVALID_HANDLE);
return std::pair(clientAddress, INVALID_SOCKET);
}
return std::pair(clientAddress, accept(handle, reinterpret_cast<SOCKADDR*>(&clientAddress), &len));
}