-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathIRSimulator.cpp
254 lines (229 loc) · 6.92 KB
/
IRSimulator.cpp
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
#include <WinSock2.h>
#include <Ws2tcpip.h>
#include "TestFramework.h"
#include "IRSimulator.h"
#include "VortexLib.h"
#include <stdio.h>
#define DEFAULT_PORT "33456"
#pragma comment(lib, "ws2_32.lib")
SOCKET IRSimulator::m_sock = -1;
SOCKET IRSimulator::m_clientSock = -1;
bool IRSimulator::m_isServer = false;
bool IRSimulator::m_isConnected = false;
HANDLE IRSimulator::m_hServerMutex = nullptr;
bool IRSimulator::init()
{
WSAData wsaData;
// Initialize Winsock
int res = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (res != 0) {
printf("WSAStartup failed with error: %d\n", res);
return false;
}
// use a mutex to detect if server is running yet
m_hServerMutex = CreateMutex(NULL, TRUE, "VortexServerMutex");
if (!m_hServerMutex || GetLastError() == ERROR_ALREADY_EXISTS) {
// otherwise try to connect client to server
startClient();
}
return true;
}
bool IRSimulator::receive_message(uint32_t &out_message)
{
SOCKET target_sock = m_sock;
if (m_isServer) {
target_sock = m_clientSock;
}
if (recv(target_sock, (char *)&out_message, sizeof(out_message), 0) <= 0) {
int err = WSAGetLastError();
if (err != 10035) {
printf("Recv failed with error: %d\n", err);
}
return false;
}
return true;
}
bool IRSimulator::send_message(uint32_t message)
{
SOCKET target_sock = m_sock;
if (m_isServer) {
target_sock = m_clientSock;
}
//static uint32_t counter = 0;
//printf("Sending[%u]: %u\n", counter++, message);
if (send(target_sock, (char *)&message, sizeof(message), 0) == SOCKET_ERROR) {
// most likely server closed
printf("send failed with error: %d\n", WSAGetLastError());
return false;
}
return true;
}
// wait for a connection from client
bool IRSimulator::accept_connection()
{
// Wait for a client connection and accept it
m_clientSock = accept(m_sock, NULL, NULL);
if (m_clientSock == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
return 1;
}
printf("Received connection!\n");
return true;
}
DWORD __stdcall IRSimulator::wait_connection(void *arg)
{
// block till a client connects and clear the output files
if (!accept_connection()) {
return 0;
}
printf("Accepted connection\n");
m_isConnected = true;
// idk when another one launches the first ones strip unpaints
PostMessage(NULL, WM_PAINT, NULL, NULL);
process_incoming_messages();
printf("Connection closed\n");
return 0;
}
void IRSimulator::process_incoming_messages()
{
if (!m_isConnected) {
return;
}
while (1) {
uint32_t message = 0;
if (!receive_message(message)) {
//break;
continue;
}
bool is_mark = (message & (1 << 31)) != 0;
message &= ~(1 << 31);
Vortex::IRDeliver(message);
}
}
// initialize the server
bool IRSimulator::startServer()
{
struct addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
struct addrinfo *result = NULL;
int res = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (res != 0) {
printf("getaddrinfo failed with error: %d\n", res);
WSACleanup();
return false;
}
// Create a SOCKET for connecting to server
m_sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (m_sock == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
return false;
}
// Setup the TCP listening socket
res = bind(m_sock, result->ai_addr, (int)result->ai_addrlen);
freeaddrinfo(result);
if (res == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
closesocket(m_sock);
return false;
}
// start listening
if (listen(m_sock, SOMAXCONN) == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
return false;
}
CreateThread(NULL, 0, wait_connection, NULL, 0, NULL);
printf("Success listening on *:8080\n");
m_isServer = true;
g_pTestFramework->setWindowTitle(g_pTestFramework->getWindowTitle() + " Receiver");
g_pTestFramework->setWindowPos(LED_COUNT == 28 ? 975 : 900, 350);
// launch another instance of the test framwork to act as the sender
if (m_isServer) {
char filename[2048] = { 0 };
GetModuleFileName(GetModuleHandle(NULL), filename, sizeof(filename));
PROCESS_INFORMATION procInfo;
memset(&procInfo, 0, sizeof(procInfo));
STARTUPINFO startInfo;
memset(&startInfo, 0, sizeof(startInfo));
CreateProcess(filename, NULL, NULL, NULL, false, 0, NULL, NULL, &startInfo, &procInfo);
}
m_isConnected = true;
return true;
}
// initialize the network client for server mode, thanks msdn for the code
bool IRSimulator::startClient()
{
struct addrinfo *addrs = NULL;
struct addrinfo *ptr = NULL;
struct addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC; // allows ipv4 or ipv6
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
int res = getaddrinfo("127.0.0.1", DEFAULT_PORT, &hints, &addrs);
if (res != 0) {
printf("Could not resolve addr info\n");
return false;
}
//info("Attempting to connect to %s", config.server_ip.c_str());
// Attempt to connect to an address until one succeeds
for (ptr = addrs; ptr != NULL; ptr = ptr->ai_next) {
// Create a SOCKET for connecting to server
m_sock = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (m_sock == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return false;
}
// Attempt to connect to the server
res = connect(m_sock, ptr->ai_addr, (int)ptr->ai_addrlen);
if (res == SOCKET_ERROR) {
closesocket(m_sock);
m_sock = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(addrs);
if (m_sock == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
return false;
}
printf("Connected to server!\n");
m_isConnected = true;
// turn on non-blocking for the socket so the module cannot
// get stuck in the send() call if the server is closed
u_long iMode = 1; // 1 = non-blocking mode
res = ioctlsocket(m_sock, FIONBIO, &iMode);
if (res != NO_ERROR) {
printf("Failed to ioctrl on socket\n");
closesocket(m_sock);
return false;
}
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)process_incoming_messages, NULL, 0, NULL);
g_pTestFramework->setWindowTitle(g_pTestFramework->getWindowTitle() + " Sender");
g_pTestFramework->setWindowPos(LED_COUNT == 28 ? 300 : 250, 350);
return true;
}
void IRSimulator::cleanup()
{
if (m_sock != -1) {
closesocket(m_sock);
m_sock = -1;
}
if (m_clientSock != -1) {
closesocket(m_clientSock);
m_clientSock = -1;
}
if (m_isServer) {
// give the server time to shutdown before another instance takes its place
Sleep(100);
}
WSACleanup();
}