comparison megawifi.c @ 1969:852393cdec7c

megawifi: implement UDP sockets
author doragasu <doragasu@hotmail.com>
date Fri, 08 May 2020 00:25:24 -0700
parents c16dabdb0aad
children 41b9509ede38
comparison
equal deleted inserted replaced
1968:c16dabdb0aad 1969:852393cdec7c
6 #define WINVER 0x501 6 #define WINVER 0x501
7 #include <winsock2.h> 7 #include <winsock2.h>
8 #include <ws2tcpip.h> 8 #include <ws2tcpip.h>
9 #else 9 #else
10 #include <sys/socket.h> 10 #include <sys/socket.h>
11 #include <arpa/inet.h>
11 #include <unistd.h> 12 #include <unistd.h>
12 #include <netinet/in.h> 13 #include <netinet/in.h>
13 #include <netdb.h> 14 #include <netdb.h>
14 #endif 15 #endif
15 #include <errno.h> 16 #include <errno.h>
59 SOCKST_TCP_LISTEN, 60 SOCKST_TCP_LISTEN,
60 SOCKST_TCP_EST, 61 SOCKST_TCP_EST,
61 SOCKST_UDP_READY 62 SOCKST_UDP_READY
62 }; 63 };
63 64
65 // TCP/UDP address message
66 struct mw_addr_msg {
67 char dst_port[6];
68 char src_port[6];
69 uint8_t channel;
70 char host[];
71 };
64 72
65 #define FLAG_ONLINE 73 #define FLAG_ONLINE
66 74
67 typedef struct { 75 typedef struct {
68 uint32_t transmit_bytes; 76 uint32_t transmit_bytes;
77 uint8_t transmit_state; 85 uint8_t transmit_state;
78 uint8_t module_state; 86 uint8_t module_state;
79 uint8_t flags; 87 uint8_t flags;
80 uint8_t transmit_buffer[4096]; 88 uint8_t transmit_buffer[4096];
81 uint8_t receive_buffer[4096]; 89 uint8_t receive_buffer[4096];
90 struct sockaddr_in remote_addr[15]; // Needed for UDP sockets
82 } megawifi; 91 } megawifi;
83 92
84 static megawifi *get_megawifi(void *context) 93 static megawifi *get_megawifi(void *context)
85 { 94 {
86 m68k_context *m68k = context; 95 m68k_context *m68k = context;
121 } 130 }
122 memcpy(mw->receive_buffer + mw->receive_bytes, src, count); 131 memcpy(mw->receive_buffer + mw->receive_bytes, src, count);
123 mw->receive_bytes += count; 132 mw->receive_bytes += count;
124 } 133 }
125 134
126 static void mw_putraw(megawifi *mw, const char *data, size_t len)
127 {
128 if ((mw->receive_bytes + len) > sizeof(mw->receive_buffer)) {
129 return;
130 }
131 memcpy(mw->receive_buffer + mw->receive_bytes, data, len);
132 mw->receive_bytes += len;
133 }
134
135 static void mw_puts(megawifi *mw, const char *s) 135 static void mw_puts(megawifi *mw, const char *s)
136 { 136 {
137 size_t len = strlen(s); 137 size_t len = strlen(s);
138 mw_putraw(mw, s, len); 138 mw_copy(mw, (uint8_t*)s, len);
139 }
140
141 static void udp_recv(megawifi *mw, uint8_t idx)
142 {
143 ssize_t recvd;
144 int s = mw->sock_fds[idx];
145 struct sockaddr_in remote;
146 socklen_t addr_len = sizeof(struct sockaddr_in);
147
148 if (mw->remote_addr[idx].sin_addr.s_addr != htonl(INADDR_ANY)) {
149 // Receive only from specified address
150 recvd = recvfrom(s, (char*)mw->receive_buffer + 3, MAX_RECV_SIZE, 0,
151 (struct sockaddr*)&remote, &addr_len);
152 if (recvd > 0) {
153 if (remote.sin_addr.s_addr != mw->remote_addr[idx].sin_addr.s_addr) {
154 printf("Discarding UDP packet from unknown addr %s:%d\n",
155 inet_ntoa(remote.sin_addr), ntohs(remote.sin_port));
156 recvd = 0;
157 }
158 }
159 } else {
160 // Reuse mode, data is preceded by remote IPv4 and port
161 recvd = recvfrom(s, (char*)mw->receive_buffer + 9, MAX_RECV_SIZE - 6,
162 0, (struct sockaddr*)&remote, &addr_len);
163 if (recvd > 0) {
164 mw->receive_buffer[3] = remote.sin_addr.s_addr;
165 mw->receive_buffer[4] = remote.sin_addr.s_addr>>8;
166 mw->receive_buffer[5] = remote.sin_addr.s_addr>>16;
167 mw->receive_buffer[6] = remote.sin_addr.s_addr>>24;
168 mw->receive_buffer[7] = remote.sin_port;
169 mw->receive_buffer[8] = remote.sin_port>>8;
170 recvd += 6;
171 }
172 }
173
174 if (recvd > 0) {
175 mw_putc(mw, STX);
176 mw_putc(mw, (recvd >> 8) | ((idx+1) << 4));
177 mw_putc(mw, recvd);
178 mw->receive_bytes += recvd;
179 mw_putc(mw, ETX);
180 //should this set the channel flag?
181 } else if (recvd < 0 && !socket_error_is_wouldblock()) {
182 socket_close(mw->sock_fds[idx]);
183 mw->channel_state[idx] = SOCKST_NONE;
184 mw->channel_flags |= 1 << (idx + 1);
185 }
186 }
187
188 static void udp_send(megawifi *mw, uint8_t idx)
189 {
190 struct sockaddr_in remote;
191 int s = mw->sock_fds[idx];
192 int sent;
193 char *data = (char*)mw->transmit_buffer;
194
195 if (mw->remote_addr[idx].sin_addr.s_addr != htonl(INADDR_ANY)) {
196 sent = sendto(s, data, mw->transmit_bytes, 0, (struct sockaddr*)&mw->remote_addr[idx],
197 sizeof(struct sockaddr_in));
198 } else {
199 // Reuse mode, extract address from leading bytes
200 // NOTE: mw->remote_addr[idx].sin_addr.s_addr == INADDR_ANY
201 remote.sin_addr.s_addr = *((int32_t*)data);
202 remote.sin_port = *((int16_t*)(data + 4));
203 remote.sin_family = AF_INET;
204 memset(remote.sin_zero, 0, sizeof(remote.sin_zero));
205 sent = sendto(s, data + 6, mw->transmit_bytes - 6, 0, (struct sockaddr*)&remote,
206 sizeof(struct sockaddr_in)) + 6;
207 }
208 if (sent < 0 && !socket_error_is_wouldblock()) {
209 socket_close(s);
210 mw->sock_fds[idx] = -1;
211 mw->channel_state[idx] = SOCKST_NONE;
212 mw->channel_flags |= 1 << (idx + 1);
213 } else if (sent < mw->transmit_bytes) {
214 //TODO: save this data somewhere so it can be sent in poll_socket
215 printf("Sent %d bytes on channel %d, but %d were requested\n", sent, idx + 1, mw->transmit_bytes);
216 }
139 } 217 }
140 218
141 static void poll_socket(megawifi *mw, uint8_t channel) 219 static void poll_socket(megawifi *mw, uint8_t channel)
142 { 220 {
143 if (mw->sock_fds[channel] < 0) { 221 if (mw->sock_fds[channel] < 0) {
154 } else if (errno != EAGAIN && errno != EWOULDBLOCK) { 232 } else if (errno != EAGAIN && errno != EWOULDBLOCK) {
155 socket_close(mw->sock_fds[channel]); 233 socket_close(mw->sock_fds[channel]);
156 mw->channel_state[channel] = SOCKST_NONE; 234 mw->channel_state[channel] = SOCKST_NONE;
157 mw->channel_flags |= 1 << (channel + 1); 235 mw->channel_flags |= 1 << (channel + 1);
158 } 236 }
159 } else if (mw->channel_state[channel] == SOCKST_TCP_EST && mw->receive_bytes < sizeof(mw->receive_buffer) - 4) { 237 } else if (mw->channel_state[channel] == SOCKST_TCP_EST && mw->receive_bytes < (sizeof(mw->receive_buffer) - 4)) {
160 size_t max = sizeof(mw->receive_buffer) - 4 - mw->receive_bytes; 238 size_t max = sizeof(mw->receive_buffer) - 4 - mw->receive_bytes;
161 if (max > MAX_RECV_SIZE) { 239 if (max > MAX_RECV_SIZE) {
162 max = MAX_RECV_SIZE; 240 max = MAX_RECV_SIZE;
163 } 241 }
164 int bytes = recv(mw->sock_fds[channel], (char*)(mw->receive_buffer + mw->receive_bytes + 3), max, 0); 242 int bytes = recv(mw->sock_fds[channel], (char*)(mw->receive_buffer + mw->receive_bytes + 3), max, 0);
172 } else if (bytes < 0 && !socket_error_is_wouldblock()) { 250 } else if (bytes < 0 && !socket_error_is_wouldblock()) {
173 socket_close(mw->sock_fds[channel]); 251 socket_close(mw->sock_fds[channel]);
174 mw->channel_state[channel] = SOCKST_NONE; 252 mw->channel_state[channel] = SOCKST_NONE;
175 mw->channel_flags |= 1 << (channel + 1); 253 mw->channel_flags |= 1 << (channel + 1);
176 } 254 }
255 } else if (mw->channel_state[channel] == SOCKST_UDP_READY && !mw->receive_bytes) {
256 udp_recv(mw, channel);
177 } 257 }
178 } 258 }
179 259
180 static void poll_all_sockets(megawifi *mw) 260 static void poll_all_sockets(megawifi *mw)
181 { 261 {
220 sprintf(ssid, "BLASTEM! SSID %d", slot + 1); 300 sprintf(ssid, "BLASTEM! SSID %d", slot + 1);
221 sprintf(pass, "BLASTEM! PASS %d", slot + 1); 301 sprintf(pass, "BLASTEM! PASS %d", slot + 1);
222 start_reply(mw, CMD_OK); 302 start_reply(mw, CMD_OK);
223 mw_putc(mw, slot); 303 mw_putc(mw, slot);
224 mw_putc(mw, 7); /// 11bgn 304 mw_putc(mw, 7); /// 11bgn
225 mw_putraw(mw, ssid, 32); 305 mw_copy(mw, (uint8_t*)ssid, 32);
226 mw_putraw(mw, pass, 64); 306 mw_copy(mw, (uint8_t*)pass, 64);
227 end_reply(mw); 307 end_reply(mw);
228 } 308 }
229 309
230 static void cmd_ip_cfg_get(megawifi *mw) 310 static void cmd_ip_cfg_get(megawifi *mw)
231 { 311 {
234 start_reply(mw, CMD_OK); 314 start_reply(mw, CMD_OK);
235 mw_putc(mw, mw->transmit_buffer[4]); 315 mw_putc(mw, mw->transmit_buffer[4]);
236 mw_putc(mw, 0); 316 mw_putc(mw, 0);
237 mw_putc(mw, 0); 317 mw_putc(mw, 0);
238 mw_putc(mw, 0); 318 mw_putc(mw, 0);
239 mw_putraw(mw, (char*)ipv4s, sizeof(ipv4s)); 319 mw_copy(mw, (uint8_t*)ipv4s, sizeof(ipv4s));
240 end_reply(mw); 320 end_reply(mw);
241 } 321 }
242 322
243 static void cmd_tcp_con(megawifi *mw, uint32_t size) 323 static void cmd_tcp_con(megawifi *mw, uint32_t size)
244 { 324 {
325 struct mw_addr_msg *addr = (struct mw_addr_msg*)(mw->transmit_buffer + 4);
245 struct addrinfo hints; 326 struct addrinfo hints;
246 struct addrinfo *res = NULL; 327 struct addrinfo *res = NULL;
247 char dst_port[6];
248 char src_port[6];
249 char host[MAX_RECV_SIZE - 13];
250 int s; 328 int s;
251
252 int err; 329 int err;
253 330
254 uint8_t channel = mw->transmit_buffer[16]; 331 uint8_t channel = addr->channel;
255 if (!channel || channel > 15 || mw->sock_fds[channel - 1] >= 0) { 332 if (!channel || channel > 15 || mw->sock_fds[channel - 1] >= 0) {
256 start_reply(mw, CMD_ERROR); 333 start_reply(mw, CMD_ERROR);
257 end_reply(mw); 334 end_reply(mw);
258 return; 335 return;
259 } 336 }
260 channel--; 337 channel--;
261
262 strncpy(dst_port, (char*)&mw->transmit_buffer[4], 5);
263 dst_port[5] = '\0';
264 // TODO src_port is unused
265 strncpy(src_port, (char*)&mw->transmit_buffer[10], 5);
266 src_port[5] = '\0';
267 strncpy(host, (char*)&mw->transmit_buffer[17], MAX_RECV_SIZE - 14);
268 host[MAX_RECV_SIZE - 14] = '\0';
269 338
270 memset(&hints, 0, sizeof(hints)); 339 memset(&hints, 0, sizeof(hints));
271 hints.ai_family = AF_INET; 340 hints.ai_family = AF_INET;
272 #ifndef _WIN32 341 #ifndef _WIN32
273 hints.ai_flags = AI_NUMERICSERV; 342 hints.ai_flags = AI_NUMERICSERV;
274 #endif 343 #endif
275 hints.ai_socktype = SOCK_STREAM; 344 hints.ai_socktype = SOCK_STREAM;
276 345
277 if ((err = getaddrinfo(host, dst_port, &hints, &res)) != 0) { 346 if ((err = getaddrinfo(addr->host, addr->dst_port, &hints, &res)) != 0) {
278 printf("getaddrinfo failed: %s\n", gai_strerror(err)); 347 printf("getaddrinfo failed: %s\n", gai_strerror(err));
279 start_reply(mw, CMD_ERROR); 348 start_reply(mw, CMD_ERROR);
280 end_reply(mw); 349 end_reply(mw);
281 return; 350 return;
282 } 351 }
293 362
294 socket_blocking(s, 0); 363 socket_blocking(s, 0);
295 mw->sock_fds[channel] = s; 364 mw->sock_fds[channel] = s;
296 mw->channel_state[channel] = SOCKST_TCP_EST; 365 mw->channel_state[channel] = SOCKST_TCP_EST;
297 mw->channel_flags |= 1 << (channel + 1); 366 mw->channel_flags |= 1 << (channel + 1);
298 printf("Connection established on ch %d with %s:%s\n", channel + 1, host, dst_port); 367 printf("Connection established on ch %d with %s:%s\n", channel + 1,
368 addr->host, addr->dst_port);
299 369
300 if (res) { 370 if (res) {
301 freeaddrinfo(res); 371 freeaddrinfo(res);
302 } 372 }
303 start_reply(mw, CMD_OK); 373 start_reply(mw, CMD_OK);
304 end_reply(mw); 374 end_reply(mw);
305 return; 375 return;
306 376
307 err: 377 err:
308 freeaddrinfo(res); 378 freeaddrinfo(res);
309 printf("Connection to %s:%s failed, %s\n", host, dst_port, strerror(errno)); 379 printf("Connection to %s:%s failed, %s\n", addr->host, addr->dst_port, strerror(errno));
310 start_reply(mw, CMD_ERROR); 380 start_reply(mw, CMD_ERROR);
311 end_reply(mw); 381 end_reply(mw);
312 } 382 }
313 383
384 static void cmd_close(megawifi *mw)
385 {
386 int channel = mw->transmit_buffer[4] - 1;
387
388 if (channel >= 15 || mw->sock_fds[channel] < 0) {
389 start_reply(mw, CMD_ERROR);
390 end_reply(mw);
391 return;
392 }
393
394 socket_close(mw->sock_fds[channel]);
395 mw->sock_fds[channel] = -1;
396 mw->channel_state[channel] = SOCKST_NONE;
397 mw->channel_flags |= 1 << (channel + 1);
398 start_reply(mw, CMD_OK);
399 end_reply(mw);
400 }
401
402 static void cmd_udp_set(megawifi *mw)
403 {
404 struct mw_addr_msg *addr = (struct mw_addr_msg*)(mw->transmit_buffer + 4);
405 unsigned int local_port, remote_port;
406 int s;
407 struct addrinfo *raddr;
408 struct addrinfo hints;
409 struct sockaddr_in local;
410 int err;
411
412 uint8_t channel = addr->channel;
413 if (!channel || channel > 15 || mw->sock_fds[channel - 1] >= 0) {
414 goto err;
415 }
416 channel--;
417 local_port = atoi(addr->src_port);
418 remote_port = atoi(addr->dst_port);
419
420 if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
421 printf("Datagram socket creation failed\n");
422 goto err;
423 }
424
425 memset(local.sin_zero, 0, sizeof(local.sin_zero));
426 local.sin_family = AF_INET;
427 local.sin_addr.s_addr = htonl(INADDR_ANY);
428 local.sin_port = htons(local_port);
429 if (remote_port && addr->host[0]) {
430 // Communication with remote peer
431 printf("Set UDP ch %d, port %d to addr %s:%d\n", addr->channel,
432 local_port, addr->host, remote_port);
433
434 memset(&hints, 0, sizeof(hints));
435 hints.ai_family = AF_INET;
436 #ifndef _WIN32
437 hints.ai_flags = AI_NUMERICSERV;
438 #endif
439 hints.ai_socktype = SOCK_DGRAM;
440
441 if ((err = getaddrinfo(addr->host, addr->dst_port, &hints, &raddr)) != 0) {
442 printf("getaddrinfo failed: %s\n", gai_strerror(err));
443 goto err;
444 }
445 mw->remote_addr[channel] = *((struct sockaddr_in*)raddr->ai_addr);
446 freeaddrinfo(raddr);
447 } else if (local_port) {
448 // Server in reuse mode
449 printf("Set UDP ch %d, src port %d\n", addr->channel, local_port);
450 mw->remote_addr[channel] = local;
451 } else {
452 printf("Invalid UDP socket data\n");
453 goto err;
454 }
455
456 if (bind(s, (struct sockaddr*)&local, sizeof(struct sockaddr_in)) < 0) {
457 printf("bind to port %d failed\n", local_port);
458 goto err;
459 }
460
461 socket_blocking(s, 0);
462 mw->sock_fds[channel] = s;
463 mw->channel_state[channel] = SOCKST_UDP_READY;
464 mw->channel_flags |= 1 << (channel + 1);
465
466 start_reply(mw, CMD_OK);
467 end_reply(mw);
468
469 return;
470
471 err:
472 start_reply(mw, CMD_ERROR);
473 end_reply(mw);
474 }
475
314 #define AVATAR_BYTES (32 * 48 / 2) 476 #define AVATAR_BYTES (32 * 48 / 2)
315 static void cmd_gamertag_get(megawifi *mw) 477 static void cmd_gamertag_get(megawifi *mw)
316 { 478 {
317 uint32_t id = htonl(1); 479 uint32_t id = htonl(1);
318 char buf[AVATAR_BYTES]; 480 char buf[AVATAR_BYTES];
319 481
320 start_reply(mw, CMD_OK); 482 start_reply(mw, CMD_OK);
321 // TODO Get items from config file 483 // TODO Get items from config file
322 mw_putraw(mw, (const char*)&id, 4); 484 mw_copy(mw, (uint8_t*)&id, 4);
323 strncpy(buf, "doragasu on Blastem!", 32); 485 strncpy(buf, "doragasu on Blastem!", 32);
324 mw_putraw(mw, buf, 32); 486 mw_copy(mw, (uint8_t*)buf, 32);
325 strncpy(buf, "My cool password", 32); 487 strncpy(buf, "My cool password", 32);
326 mw_putraw(mw, buf, 32); 488 mw_copy(mw, (uint8_t*)buf, 32);
327 strncpy(buf, "All your WiFi are belong to me!", 32); 489 strncpy(buf, "All your WiFi are belong to me!", 32);
328 mw_putraw(mw, buf, 32); 490 mw_copy(mw, (uint8_t*)buf, 32);
329 memset(buf, 0, 64); // Telegram token 491 memset(buf, 0, 64); // Telegram token
330 mw_putraw(mw, buf, 64); 492 mw_copy(mw, (uint8_t*)buf, 64);
331 mw_putraw(mw, buf, AVATAR_BYTES); // Avatar tiles 493 mw_copy(mw, (uint8_t*)buf, AVATAR_BYTES); // Avatar tiles
332 mw_putraw(mw, buf, 32); // Avatar palette 494 mw_copy(mw, (uint8_t*)buf, 32); // Avatar palette
333 end_reply(mw); 495 end_reply(mw);
334 } 496 }
335 497
336 static void cmd_hrng_get(megawifi *mw) 498 static void cmd_hrng_get(megawifi *mw)
337 { 499 {
463 socket_blocking(mw->sock_fds[channel], 0); 625 socket_blocking(mw->sock_fds[channel], 0);
464 } 626 }
465 end_reply(mw); 627 end_reply(mw);
466 break; 628 break;
467 } 629 }
630 case CMD_CLOSE:
631 cmd_close(mw);
632 break;
633 case CMD_UDP_SET:
634 cmd_udp_set(mw);
635 break;
468 case CMD_SOCK_STAT: { 636 case CMD_SOCK_STAT: {
469 uint8_t channel = mw->transmit_buffer[4]; 637 uint8_t channel = mw->transmit_buffer[4];
470 if (!channel || channel > 15) { 638 if (!channel || channel > 15) {
471 start_reply(mw, CMD_ERROR); 639 start_reply(mw, CMD_ERROR);
472 end_reply(mw); 640 end_reply(mw);
518 process_command(mw); 686 process_command(mw);
519 } else { 687 } else {
520 uint8_t channel = mw->transmit_channel - 1; 688 uint8_t channel = mw->transmit_channel - 1;
521 int channel_state = mw->channel_state[channel]; 689 int channel_state = mw->channel_state[channel];
522 int sock_fd = mw->sock_fds[channel]; 690 int sock_fd = mw->sock_fds[channel];
523 // TODO Handle UDP type sockets
524 if (sock_fd >= 0 && channel_state == SOCKST_TCP_EST) { 691 if (sock_fd >= 0 && channel_state == SOCKST_TCP_EST) {
525 int sent = send(sock_fd, (char*)mw->transmit_buffer, mw->transmit_bytes, 0); 692 int sent = send(sock_fd, (char*)mw->transmit_buffer, mw->transmit_bytes, 0);
526 if (sent < 0 && !socket_error_is_wouldblock()) { 693 if (sent < 0 && !socket_error_is_wouldblock()) {
527 socket_close(sock_fd); 694 socket_close(sock_fd);
528 mw->sock_fds[channel] = -1; 695 mw->sock_fds[channel] = -1;
530 mw->channel_flags |= 1 << mw->transmit_channel; 697 mw->channel_flags |= 1 << mw->transmit_channel;
531 } else if (sent < mw->transmit_bytes) { 698 } else if (sent < mw->transmit_bytes) {
532 //TODO: save this data somewhere so it can be sent in poll_socket 699 //TODO: save this data somewhere so it can be sent in poll_socket
533 printf("Sent %d bytes on channel %d, but %d were requested\n", sent, mw->transmit_channel, mw->transmit_bytes); 700 printf("Sent %d bytes on channel %d, but %d were requested\n", sent, mw->transmit_channel, mw->transmit_bytes);
534 } 701 }
702 } else if (sock_fd >= 0 && channel_state == SOCKST_UDP_READY) {
703 udp_send(mw, channel);
535 } else { 704 } else {
536 printf("Unhandled receive of MegaWiFi data on channel %d\n", mw->transmit_channel); 705 printf("Unhandled receive of MegaWiFi data on channel %d\n", mw->transmit_channel);
537 } 706 }
538 } 707 }
539 mw->transmit_bytes = mw->expected_bytes = 0; 708 mw->transmit_bytes = mw->expected_bytes = 0;