-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPing.cpp
More file actions
145 lines (109 loc) · 4.14 KB
/
Ping.cpp
File metadata and controls
145 lines (109 loc) · 4.14 KB
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
144
145
#include "Ping.h"
Ping::Ping(wchar_t* server, int length) {
run = false;
hIcmpFile = NULL;
dwRetVal = 0;
replySize = 0;
//memset(&hints, 0, sizeof(hints)); // Initialize hints to 0
hints.ai_family = AF_UNSPEC; // Any address family (IPv4 or IPv6)
hints.ai_socktype = SOCK_STREAM; // TCP sockets
pingVector.reset(new std::vector<int>(length));
setAddress(server);
}
Ping::~Ping() {
stop();
WSACleanup();
}
void Ping::start() {
if (!run.load()) {
run.store(true);
hIcmpFile = IcmpCreateFile();
hThread = CreateThread(NULL, 0, ThreadLoop, this, 0, NULL);
}
}
void Ping::stop() {
if (run.load()){
run.store(false);
IcmpCloseHandle(hIcmpFile);
CloseHandle(hThread);
}
}
DWORD WINAPI Ping::ThreadLoop(LPVOID lpParam) {
Ping* ping = static_cast<Ping*>(lpParam);
while (ping->run.load()) {
ping->insert(ping->ping());
int sum = 0;
ping->maximum = *std::max_element(ping->pingVector->begin(), ping->pingVector->end());
ping->minimum = *std::min_element(ping->pingVector->begin(), ping->pingVector->end());
for (int const& p : *ping->pingVector) sum += p;
ping->average = (double)sum / (ping->pingVector->size());
sum = 0;
for (int const& p : *ping->pingVector) sum += (int)pow(p - ping->average, 2);
ping->instability = sqrt((double)sum / (ping->pingVector->size() - 1));
int delay = PING_LOOP_INTERVAL - ping->getPing();
if (delay > 0) std::this_thread::sleep_for(std::chrono::milliseconds(delay));
}
return 0;
}
void Ping::setAddress(wchar_t* server) {
this->server = server;
ipAddress = INADDR_NONE;
if (InetPton(AF_INET, server, &ipAddress) != 1)
{
int status = GetAddrInfoW(server, L"80", &hints, &addressInfo);
if (status != 0)
{
OutputDebugStringA("Error resolving address: ");
OutputDebugString(gai_strerror(status));
OutputDebugStringA("\n");
return;
}
// Loop through the linked list of addresses
for (addrinfoW* info = addressInfo; info != nullptr; info = info->ai_next) {
wchar_t addressString[INET6_ADDRSTRLEN];
void* address;
// Get address string based on family
if (info->ai_family == AF_INET)
address = &((sockaddr_in*)info->ai_addr)->sin_addr;
else
address = &((sockaddr_in6*)info->ai_addr)->sin6_addr;
InetNtop(info->ai_family, address, addressString, sizeof(addressString));
InetPton(info->ai_family, addressString, &ipAddress);
OutputDebugStringA("Addresses: ");
OutputDebugStringW(addressString);
OutputDebugStringA("\n");
}
FreeAddrInfoW(addressInfo);
}
else {
OutputDebugStringA("Addresses: ");
OutputDebugStringW(server);
OutputDebugStringA("\n");
}
}
int Ping::ping() {
if (hIcmpFile == INVALID_HANDLE_VALUE) return DISCONNECT_VALUE;
if (ipAddress == INADDR_NONE) {
setAddress(this->server);
return DISCONNECT_VALUE;
}
replySize = sizeof(ICMP_ECHO_REPLY) + sizeof(sendData) + 8;
void* replyBuffer = (VOID*)malloc(replySize);
if (replyBuffer == NULL) return DISCONNECT_VALUE;
int tripTime = DISCONNECT_VALUE;
dwRetVal = IcmpSendEcho(hIcmpFile, ipAddress, sendData, sizeof(sendData), NULL, replyBuffer, replySize, PING_TIME_OUT);
if (dwRetVal != 0) tripTime = ((PICMP_ECHO_REPLY)replyBuffer)->RoundTripTime;
free(replyBuffer);
return tripTime;
}
void Ping::insert(int pingValue) {
pingVector->insert(pingVector->begin(), pingValue);
pingVector->pop_back();
}
int Ping::getPing() { return pingVector->front(); }
int Ping::getPing(int index) { return (index < 0 || index >= pingVector->size()) ? DISCONNECT_VALUE : pingVector->at(index); }
int Ping::getMax() { return maximum; }
int Ping::getMin() { return minimum; }
double Ping::getInstability() { return instability; }
double Ping::getAverage() { return average; }
bool Ping::isRunning() { return run; }