comparison megawifi.c @ 1983:a7b753e260a2 mame_interp

Merge from default
author Michael Pavone <pavone@retrodev.com>
date Sat, 09 May 2020 23:39:44 -0700
parents 41b9509ede38
children a8e3e816a50d
comparison
equal deleted inserted replaced
1937:cafde1255ad3 1983:a7b753e260a2
4 #include <sys/types.h> 4 #include <sys/types.h>
5 #ifdef _WIN32 5 #ifdef _WIN32
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 #include <sys/param.h>
9 #else 10 #else
10 #include <sys/socket.h> 11 #include <sys/socket.h>
12 #include <arpa/inet.h>
11 #include <unistd.h> 13 #include <unistd.h>
12 #include <netinet/in.h> 14 #include <netinet/in.h>
15 #include <netdb.h>
13 #endif 16 #endif
14 #include <errno.h> 17 #include <errno.h>
15 #include <fcntl.h> 18 #include <fcntl.h>
19 #include <time.h>
16 #include "genesis.h" 20 #include "genesis.h"
17 #include "net.h" 21 #include "net.h"
22 #include "util.h"
23
24 #ifdef _WIN32
25 # if BYTE_ORDER == LITTLE_ENDIAN
26 #define htobe64(val) ((((uint64_t)htonl((val)&0xFFFFFFFF))<<32) | htonl((val)>>32))
27 # else
28 #define htobe64(val) (val)
29 # endif
30 #endif
18 31
19 enum { 32 enum {
20 TX_IDLE, 33 TX_IDLE,
21 TX_LEN1, 34 TX_LEN1,
22 TX_LEN2, 35 TX_LEN2,
23 TX_PAYLOAD, 36 TX_PAYLOAD,
24 TX_WAIT_ETX 37 TX_WAIT_ETX
25 }; 38 };
26 #define STX 0x7E 39 #define STX 0x7E
27 #define ETX 0x7E 40 #define ETX 0x7E
28 #define MAX_RECV_SIZE 1440 41 #define MAX_RECV_SIZE 1460
29 42
30 #define E(N) N 43 #define E(N) N
31 enum { 44 enum {
32 #include "mw_commands.c" 45 #include "mw_commands.c"
33 CMD_ERROR = 255 46 CMD_ERROR = 255
41 54
42 #ifndef MSG_NOSIGNAL 55 #ifndef MSG_NOSIGNAL
43 #define MSG_NOSIGNAL 0 56 #define MSG_NOSIGNAL 0
44 #endif 57 #endif
45 58
46 enum { 59 enum mw_state {
47 STATE_IDLE=1, 60 STATE_IDLE=1,
48 STATE_AP_JOIN, 61 STATE_AP_JOIN,
49 STATE_SCAN, 62 STATE_SCAN,
50 STATE_READY, 63 STATE_READY,
51 STATE_TRANSPARENT 64 STATE_TRANSPARENT
65 };
66
67 enum {
68 SOCKST_NONE = 0,
69 SOCKST_TCP_LISTEN,
70 SOCKST_TCP_EST,
71 SOCKST_UDP_READY
72 };
73
74 // TCP/UDP address message
75 struct mw_addr_msg {
76 char dst_port[6];
77 char src_port[6];
78 uint8_t channel;
79 char host[];
52 }; 80 };
53 81
54 #define FLAG_ONLINE 82 #define FLAG_ONLINE
55 83
56 typedef struct { 84 typedef struct {
66 uint8_t transmit_state; 94 uint8_t transmit_state;
67 uint8_t module_state; 95 uint8_t module_state;
68 uint8_t flags; 96 uint8_t flags;
69 uint8_t transmit_buffer[4096]; 97 uint8_t transmit_buffer[4096];
70 uint8_t receive_buffer[4096]; 98 uint8_t receive_buffer[4096];
99 struct sockaddr_in remote_addr[15]; // Needed for UDP sockets
71 } megawifi; 100 } megawifi;
72 101
73 static megawifi *get_megawifi(void *context) 102 static megawifi *get_megawifi(void *context)
74 { 103 {
75 m68k_context *m68k = context; 104 m68k_context *m68k = context;
76 genesis_context *gen = m68k->system; 105 genesis_context *gen = m68k->system;
77 if (!gen->extra) { 106 if (!gen->extra) {
107 socket_init();
78 gen->extra = calloc(1, sizeof(megawifi)); 108 gen->extra = calloc(1, sizeof(megawifi));
79 megawifi *mw = gen->extra; 109 megawifi *mw = gen->extra;
80 mw->module_state = STATE_IDLE; 110 mw->module_state = STATE_IDLE;
81 for (int i = 0; i < 15; i++) 111 mw->flags = 0xE0; // cfg_ok, dt_ok, online
82 { 112 for (int i = 0; i < 15; i++) {
83 mw->sock_fds[i] = -1; 113 mw->sock_fds[i] = -1;
84 } 114 }
85 } 115 }
86 return gen->extra; 116 return gen->extra;
87 } 117 }
110 } 140 }
111 memcpy(mw->receive_buffer + mw->receive_bytes, src, count); 141 memcpy(mw->receive_buffer + mw->receive_bytes, src, count);
112 mw->receive_bytes += count; 142 mw->receive_bytes += count;
113 } 143 }
114 144
115 static void mw_puts(megawifi *mw, char *s) 145 static void mw_puts(megawifi *mw, const char *s)
116 { 146 {
117 uint32_t len = strlen(s); 147 size_t len = strlen(s);
118 if ((mw->receive_bytes + len) > sizeof(mw->receive_buffer)) { 148 mw_copy(mw, (uint8_t*)s, len);
119 return; 149 }
120 } 150
121 memcpy(mw->receive_buffer + mw->receive_bytes, s, len); 151 static void udp_recv(megawifi *mw, uint8_t idx)
122 mw->receive_bytes += len; 152 {
153 ssize_t recvd;
154 int s = mw->sock_fds[idx];
155 struct sockaddr_in remote;
156 socklen_t addr_len = sizeof(struct sockaddr_in);
157
158 if (mw->remote_addr[idx].sin_addr.s_addr != htonl(INADDR_ANY)) {
159 // Receive only from specified address
160 recvd = recvfrom(s, (char*)mw->receive_buffer + 3, MAX_RECV_SIZE, 0,
161 (struct sockaddr*)&remote, &addr_len);
162 if (recvd > 0) {
163 if (remote.sin_addr.s_addr != mw->remote_addr[idx].sin_addr.s_addr) {
164 printf("Discarding UDP packet from unknown addr %s:%d\n",
165 inet_ntoa(remote.sin_addr), ntohs(remote.sin_port));
166 recvd = 0;
167 }
168 }
169 } else {
170 // Reuse mode, data is preceded by remote IPv4 and port
171 recvd = recvfrom(s, (char*)mw->receive_buffer + 9, MAX_RECV_SIZE - 6,
172 0, (struct sockaddr*)&remote, &addr_len);
173 if (recvd > 0) {
174 mw->receive_buffer[3] = remote.sin_addr.s_addr;
175 mw->receive_buffer[4] = remote.sin_addr.s_addr>>8;
176 mw->receive_buffer[5] = remote.sin_addr.s_addr>>16;
177 mw->receive_buffer[6] = remote.sin_addr.s_addr>>24;
178 mw->receive_buffer[7] = remote.sin_port;
179 mw->receive_buffer[8] = remote.sin_port>>8;
180 recvd += 6;
181 }
182 }
183
184 if (recvd > 0) {
185 mw_putc(mw, STX);
186 mw_putc(mw, (recvd >> 8) | ((idx+1) << 4));
187 mw_putc(mw, recvd);
188 mw->receive_bytes += recvd;
189 mw_putc(mw, ETX);
190 //should this set the channel flag?
191 } else if (recvd < 0 && !socket_error_is_wouldblock()) {
192 socket_close(mw->sock_fds[idx]);
193 mw->channel_state[idx] = SOCKST_NONE;
194 mw->channel_flags |= 1 << (idx + 1);
195 }
196 }
197
198 static void udp_send(megawifi *mw, uint8_t idx)
199 {
200 struct sockaddr_in remote;
201 int s = mw->sock_fds[idx];
202 int sent;
203 char *data = (char*)mw->transmit_buffer;
204
205 if (mw->remote_addr[idx].sin_addr.s_addr != htonl(INADDR_ANY)) {
206 sent = sendto(s, data, mw->transmit_bytes, 0, (struct sockaddr*)&mw->remote_addr[idx],
207 sizeof(struct sockaddr_in));
208 } else {
209 // Reuse mode, extract address from leading bytes
210 // NOTE: mw->remote_addr[idx].sin_addr.s_addr == INADDR_ANY
211 remote.sin_addr.s_addr = *((int32_t*)data);
212 remote.sin_port = *((int16_t*)(data + 4));
213 remote.sin_family = AF_INET;
214 memset(remote.sin_zero, 0, sizeof(remote.sin_zero));
215 sent = sendto(s, data + 6, mw->transmit_bytes - 6, 0, (struct sockaddr*)&remote,
216 sizeof(struct sockaddr_in)) + 6;
217 }
218 if (sent < 0 && !socket_error_is_wouldblock()) {
219 socket_close(s);
220 mw->sock_fds[idx] = -1;
221 mw->channel_state[idx] = SOCKST_NONE;
222 mw->channel_flags |= 1 << (idx + 1);
223 } else if (sent < mw->transmit_bytes) {
224 //TODO: save this data somewhere so it can be sent in poll_socket
225 printf("Sent %d bytes on channel %d, but %d were requested\n", sent, idx + 1, mw->transmit_bytes);
226 }
123 } 227 }
124 228
125 static void poll_socket(megawifi *mw, uint8_t channel) 229 static void poll_socket(megawifi *mw, uint8_t channel)
126 { 230 {
127 if (mw->sock_fds[channel] < 0) { 231 if (mw->sock_fds[channel] < 0) {
128 return; 232 return;
129 } 233 }
130 if (mw->channel_state[channel] == 1) { 234 if (mw->channel_state[channel] == SOCKST_TCP_LISTEN) {
131 int res = accept(mw->sock_fds[channel], NULL, NULL); 235 int res = accept(mw->sock_fds[channel], NULL, NULL);
132 if (res >= 0) { 236 if (res >= 0) {
133 close(mw->sock_fds[channel]); 237 socket_close(mw->sock_fds[channel]);
134 #ifndef _WIN32 238 socket_blocking(res, 0);
135 //FIXME: Set nonblocking on Windows too
136 fcntl(res, F_SETFL, O_NONBLOCK);
137 #endif
138 mw->sock_fds[channel] = res; 239 mw->sock_fds[channel] = res;
139 mw->channel_state[channel] = 2; 240 mw->channel_state[channel] = SOCKST_TCP_EST;
140 mw->channel_flags |= 1 << (channel + 1); 241 mw->channel_flags |= 1 << (channel + 1);
141 } else if (errno != EAGAIN && errno != EWOULDBLOCK) { 242 } else if (errno != EAGAIN && errno != EWOULDBLOCK) {
142 close(mw->sock_fds[channel]); 243 socket_close(mw->sock_fds[channel]);
143 mw->channel_state[channel] = 0; 244 mw->channel_state[channel] = SOCKST_NONE;
144 mw->channel_flags |= 1 << (channel + 1); 245 mw->channel_flags |= 1 << (channel + 1);
145 } 246 }
146 } else if (mw->channel_state[channel] == 2 && mw->receive_bytes < sizeof(mw->receive_buffer) - 4) { 247 } else if (mw->channel_state[channel] == SOCKST_TCP_EST && mw->receive_bytes < (sizeof(mw->receive_buffer) - 4)) {
147 size_t max = sizeof(mw->receive_buffer) - 4 - mw->receive_bytes; 248 size_t max = sizeof(mw->receive_buffer) - 4 - mw->receive_bytes;
148 if (max > MAX_RECV_SIZE) { 249 if (max > MAX_RECV_SIZE) {
149 max = MAX_RECV_SIZE; 250 max = MAX_RECV_SIZE;
150 } 251 }
151 int bytes = recv(mw->sock_fds[channel], mw->receive_buffer + mw->receive_bytes + 3, max, 0); 252 int bytes = recv(mw->sock_fds[channel], (char*)(mw->receive_buffer + mw->receive_bytes + 3), max, 0);
152 if (bytes > 0) { 253 if (bytes > 0) {
153 mw_putc(mw, STX); 254 mw_putc(mw, STX);
154 mw_putc(mw, bytes >> 8 | (channel+1) << 4); 255 mw_putc(mw, bytes >> 8 | (channel+1) << 4);
155 mw_putc(mw, bytes); 256 mw_putc(mw, bytes);
156 mw->receive_bytes += bytes; 257 mw->receive_bytes += bytes;
157 mw_putc(mw, ETX); 258 mw_putc(mw, ETX);
158 //should this set the channel flag? 259 //should this set the channel flag?
159 } else if (bytes < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { 260 } else if (bytes < 0 && !socket_error_is_wouldblock()) {
160 close(mw->sock_fds[channel]); 261 socket_close(mw->sock_fds[channel]);
161 mw->channel_state[channel] = 0; 262 mw->channel_state[channel] = SOCKST_NONE;
162 mw->channel_flags |= 1 << (channel + 1); 263 mw->channel_flags |= 1 << (channel + 1);
163 } 264 }
265 } else if (mw->channel_state[channel] == SOCKST_UDP_READY && !mw->receive_bytes) {
266 udp_recv(mw, channel);
164 } 267 }
165 } 268 }
166 269
167 static void poll_all_sockets(megawifi *mw) 270 static void poll_all_sockets(megawifi *mw)
168 { 271 {
169 for (int i = 0; i < 15; i++) 272 for (int i = 0; i < 15; i++)
170 { 273 {
171 poll_socket(mw, i); 274 poll_socket(mw, i);
172 } 275 }
173 } 276 }
277
174 278
175 static void start_reply(megawifi *mw, uint8_t cmd) 279 static void start_reply(megawifi *mw, uint8_t cmd)
176 { 280 {
177 mw_putc(mw, STX); 281 mw_putc(mw, STX);
178 //reserve space for length 282 //reserve space for length
195 mw->receive_buffer[5] = len >> 8; 299 mw->receive_buffer[5] = len >> 8;
196 mw->receive_buffer[6] = len; 300 mw->receive_buffer[6] = len;
197 mw_putc(mw, ETX); 301 mw_putc(mw, ETX);
198 } 302 }
199 303
304 static void cmd_ap_cfg_get(megawifi *mw)
305 {
306 char ssid[32] = {0};
307 char pass[64] = {0};
308 uint8_t slot = mw->transmit_buffer[4];
309
310 sprintf(ssid, "BLASTEM! SSID %d", slot + 1);
311 sprintf(pass, "BLASTEM! PASS %d", slot + 1);
312 start_reply(mw, CMD_OK);
313 mw_putc(mw, slot);
314 mw_putc(mw, 7); /// 11bgn
315 mw_copy(mw, (uint8_t*)ssid, 32);
316 mw_copy(mw, (uint8_t*)pass, 64);
317 end_reply(mw);
318 }
319
320 static void cmd_ip_cfg_get(megawifi *mw)
321 {
322 uint32_t ipv4s[5] = {0};
323
324 start_reply(mw, CMD_OK);
325 mw_putc(mw, mw->transmit_buffer[4]);
326 mw_putc(mw, 0);
327 mw_putc(mw, 0);
328 mw_putc(mw, 0);
329 mw_copy(mw, (uint8_t*)ipv4s, sizeof(ipv4s));
330 end_reply(mw);
331 }
332
333 static void cmd_tcp_con(megawifi *mw, uint32_t size)
334 {
335 struct mw_addr_msg *addr = (struct mw_addr_msg*)(mw->transmit_buffer + 4);
336 struct addrinfo hints;
337 struct addrinfo *res = NULL;
338 int s;
339 int err;
340
341 uint8_t channel = addr->channel;
342 if (!channel || channel > 15 || mw->sock_fds[channel - 1] >= 0) {
343 start_reply(mw, CMD_ERROR);
344 end_reply(mw);
345 return;
346 }
347 channel--;
348
349 memset(&hints, 0, sizeof(hints));
350 hints.ai_family = AF_INET;
351 #ifndef _WIN32
352 hints.ai_flags = AI_NUMERICSERV;
353 #endif
354 hints.ai_socktype = SOCK_STREAM;
355
356 if ((err = getaddrinfo(addr->host, addr->dst_port, &hints, &res)) != 0) {
357 printf("getaddrinfo failed: %s\n", gai_strerror(err));
358 start_reply(mw, CMD_ERROR);
359 end_reply(mw);
360 return;
361 }
362
363 s = socket(AF_INET, SOCK_STREAM, 0);
364 if (s < 0) {
365 goto err;
366 }
367
368 // Should this be handled in a separate thread to avoid blocking emulation?
369 if (connect(s, res->ai_addr, res->ai_addrlen) != 0) {
370 goto err;
371 }
372
373 socket_blocking(s, 0);
374 mw->sock_fds[channel] = s;
375 mw->channel_state[channel] = SOCKST_TCP_EST;
376 mw->channel_flags |= 1 << (channel + 1);
377 printf("Connection established on ch %d with %s:%s\n", channel + 1,
378 addr->host, addr->dst_port);
379
380 if (res) {
381 freeaddrinfo(res);
382 }
383 start_reply(mw, CMD_OK);
384 end_reply(mw);
385 return;
386
387 err:
388 freeaddrinfo(res);
389 printf("Connection to %s:%s failed, %s\n", addr->host, addr->dst_port, strerror(errno));
390 start_reply(mw, CMD_ERROR);
391 end_reply(mw);
392 }
393
394 static void cmd_close(megawifi *mw)
395 {
396 int channel = mw->transmit_buffer[4] - 1;
397
398 if (channel >= 15 || mw->sock_fds[channel] < 0) {
399 start_reply(mw, CMD_ERROR);
400 end_reply(mw);
401 return;
402 }
403
404 socket_close(mw->sock_fds[channel]);
405 mw->sock_fds[channel] = -1;
406 mw->channel_state[channel] = SOCKST_NONE;
407 mw->channel_flags |= 1 << (channel + 1);
408 start_reply(mw, CMD_OK);
409 end_reply(mw);
410 }
411
412 static void cmd_udp_set(megawifi *mw)
413 {
414 struct mw_addr_msg *addr = (struct mw_addr_msg*)(mw->transmit_buffer + 4);
415 unsigned int local_port, remote_port;
416 int s;
417 struct addrinfo *raddr;
418 struct addrinfo hints;
419 struct sockaddr_in local;
420 int err;
421
422 uint8_t channel = addr->channel;
423 if (!channel || channel > 15 || mw->sock_fds[channel - 1] >= 0) {
424 goto err;
425 }
426 channel--;
427 local_port = atoi(addr->src_port);
428 remote_port = atoi(addr->dst_port);
429
430 if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
431 printf("Datagram socket creation failed\n");
432 goto err;
433 }
434
435 memset(local.sin_zero, 0, sizeof(local.sin_zero));
436 local.sin_family = AF_INET;
437 local.sin_addr.s_addr = htonl(INADDR_ANY);
438 local.sin_port = htons(local_port);
439 if (remote_port && addr->host[0]) {
440 // Communication with remote peer
441 printf("Set UDP ch %d, port %d to addr %s:%d\n", addr->channel,
442 local_port, addr->host, remote_port);
443
444 memset(&hints, 0, sizeof(hints));
445 hints.ai_family = AF_INET;
446 #ifndef _WIN32
447 hints.ai_flags = AI_NUMERICSERV;
448 #endif
449 hints.ai_socktype = SOCK_DGRAM;
450
451 if ((err = getaddrinfo(addr->host, addr->dst_port, &hints, &raddr)) != 0) {
452 printf("getaddrinfo failed: %s\n", gai_strerror(err));
453 goto err;
454 }
455 mw->remote_addr[channel] = *((struct sockaddr_in*)raddr->ai_addr);
456 freeaddrinfo(raddr);
457 } else if (local_port) {
458 // Server in reuse mode
459 printf("Set UDP ch %d, src port %d\n", addr->channel, local_port);
460 mw->remote_addr[channel] = local;
461 } else {
462 printf("Invalid UDP socket data\n");
463 goto err;
464 }
465
466 if (bind(s, (struct sockaddr*)&local, sizeof(struct sockaddr_in)) < 0) {
467 printf("bind to port %d failed\n", local_port);
468 goto err;
469 }
470
471 socket_blocking(s, 0);
472 mw->sock_fds[channel] = s;
473 mw->channel_state[channel] = SOCKST_UDP_READY;
474 mw->channel_flags |= 1 << (channel + 1);
475
476 start_reply(mw, CMD_OK);
477 end_reply(mw);
478
479 return;
480
481 err:
482 start_reply(mw, CMD_ERROR);
483 end_reply(mw);
484 }
485
486 #define AVATAR_BYTES (32 * 48 / 2)
487 static void cmd_gamertag_get(megawifi *mw)
488 {
489 uint32_t id = htonl(1);
490 char buf[AVATAR_BYTES];
491
492 start_reply(mw, CMD_OK);
493 // TODO Get items from config file
494 mw_copy(mw, (uint8_t*)&id, 4);
495 strncpy(buf, "doragasu on Blastem!", 32);
496 mw_copy(mw, (uint8_t*)buf, 32);
497 strncpy(buf, "My cool password", 32);
498 mw_copy(mw, (uint8_t*)buf, 32);
499 strncpy(buf, "All your WiFi are belong to me!", 32);
500 mw_copy(mw, (uint8_t*)buf, 32);
501 memset(buf, 0, 64); // Telegram token
502 mw_copy(mw, (uint8_t*)buf, 64);
503 mw_copy(mw, (uint8_t*)buf, AVATAR_BYTES); // Avatar tiles
504 mw_copy(mw, (uint8_t*)buf, 32); // Avatar palette
505 end_reply(mw);
506 }
507
508 static void cmd_hrng_get(megawifi *mw)
509 {
510 uint16_t len = (mw->transmit_buffer[4]<<8) + mw->transmit_buffer[5];
511 if (len > (MAX_RECV_SIZE - 4)) {
512 start_reply(mw, CMD_ERROR);
513 end_reply(mw);
514 return;
515 }
516 // Pseudo-random, but who cares
517 start_reply(mw, CMD_OK);
518 srand(time(NULL));
519 for (uint16_t i = 0; i < len; i++) {
520 mw_putc(mw, rand());
521 }
522 end_reply(mw);
523 }
524
525 static void cmd_datetime(megawifi *mw)
526 {
527 start_reply(mw, CMD_OK);
528 #ifdef _WIN32
529 __time64_t t = _time64(NULL);
530 int64_t t_be = htobe64(t);
531 mw_copy(mw, (uint8_t*)&t_be, sizeof(int64_t));
532 mw_puts(mw, _ctime64(&t));
533 #else
534 time_t t = time(NULL);
535 int64_t t_be = htobe64(t);
536 mw_copy(mw, (uint8_t*)&t_be, sizeof(int64_t));
537 mw_puts(mw, ctime(&t));
538 #endif
539
540 mw_putc(mw, '\0');
541 end_reply(mw);
542 }
543
544 static void process_command(megawifi *mw)
545 {
546 uint32_t command = mw->transmit_buffer[0] << 8 | mw->transmit_buffer[1];
547 uint32_t size = mw->transmit_buffer[2] << 8 | mw->transmit_buffer[3];
548 if (size > mw->transmit_bytes - 4) {
549 size = mw->transmit_bytes - 4;
550 }
551 int orig_receive_bytes = mw->receive_bytes;
552 switch (command)
553 {
554 case CMD_VERSION:
555 start_reply(mw, CMD_OK);
556 mw_putc(mw, 1);
557 mw_putc(mw, 3);
558 mw_putc(mw, 0);
559 mw_puts(mw, "blastem");
560 mw_putc(mw, '\0');
561 end_reply(mw);
562 break;
563 case CMD_ECHO:
564 mw->receive_bytes = mw->transmit_bytes;
565 memcpy(mw->receive_buffer, mw->transmit_buffer, mw->transmit_bytes);
566 break;
567 case CMD_AP_CFG_GET:
568 cmd_ap_cfg_get(mw);
569 break;
570 case CMD_IP_CURRENT: {
571 iface_info i;
572 if (get_host_address(&i)) {
573 start_reply(mw, CMD_OK);
574 //config number and reserved bytes
575 mw_set(mw, 0, 4);
576 //ip
577 mw_copy(mw, i.ip, sizeof(i.ip));
578 //net mask
579 mw_copy(mw, i.net_mask, sizeof(i.net_mask));
580 //gateway guess
581 mw_putc(mw, i.ip[0] & i.net_mask[0]);
582 mw_putc(mw, i.ip[1] & i.net_mask[1]);
583 mw_putc(mw, i.ip[2] & i.net_mask[2]);
584 mw_putc(mw, (i.ip[3] & i.net_mask[3]) + 1);
585 //dns
586 static const uint8_t localhost[] = {127,0,0,1};
587 mw_copy(mw, localhost, sizeof(localhost));
588 mw_copy(mw, localhost, sizeof(localhost));
589
590 } else {
591 start_reply(mw, CMD_ERROR);
592 }
593 end_reply(mw);
594 break;
595 }
596 case CMD_IP_CFG_GET:
597 cmd_ip_cfg_get(mw);
598 break;
599 case CMD_DEF_AP_CFG_GET:
600 start_reply(mw, CMD_OK);
601 mw_putc(mw, 0);
602 end_reply(mw);
603 break;
604 case CMD_AP_JOIN:
605 mw->module_state = STATE_READY;
606 start_reply(mw, CMD_OK);
607 end_reply(mw);
608 break;
609 case CMD_TCP_CON:
610 cmd_tcp_con(mw, size);
611 break;
612 case CMD_TCP_BIND:{
613 if (size < 7){
614 start_reply(mw, CMD_ERROR);
615 end_reply(mw);
616 break;
617 }
618 uint8_t channel = mw->transmit_buffer[10];
619 if (!channel || channel > 15) {
620 start_reply(mw, CMD_ERROR);
621 end_reply(mw);
622 break;
623 }
624 channel--;
625 if (mw->sock_fds[channel] >= 0) {
626 socket_close(mw->sock_fds[channel]);
627 }
628 mw->sock_fds[channel] = socket(AF_INET, SOCK_STREAM, 0);
629 if (mw->sock_fds[channel] < 0) {
630 start_reply(mw, CMD_ERROR);
631 end_reply(mw);
632 break;
633 }
634 int value = 1;
635 setsockopt(mw->sock_fds[channel], SOL_SOCKET, SO_REUSEADDR, (char*)&value, sizeof(value));
636 struct sockaddr_in bind_addr;
637 memset(&bind_addr, 0, sizeof(bind_addr));
638 bind_addr.sin_family = AF_INET;
639 bind_addr.sin_port = htons(mw->transmit_buffer[8] << 8 | mw->transmit_buffer[9]);
640 if (bind(mw->sock_fds[channel], (struct sockaddr *)&bind_addr, sizeof(bind_addr)) != 0) {
641 socket_close(mw->sock_fds[channel]);
642 mw->sock_fds[channel] = -1;
643 start_reply(mw, CMD_ERROR);
644 end_reply(mw);
645 break;
646 }
647 int res = listen(mw->sock_fds[channel], 2);
648 start_reply(mw, res ? CMD_ERROR : CMD_OK);
649 if (res) {
650 socket_close(mw->sock_fds[channel]);
651 mw->sock_fds[channel] = -1;
652 } else {
653 mw->channel_flags |= 1 << (channel + 1);
654 mw->channel_state[channel] = SOCKST_TCP_LISTEN;
655 socket_blocking(mw->sock_fds[channel], 0);
656 }
657 end_reply(mw);
658 break;
659 }
660 case CMD_CLOSE:
661 cmd_close(mw);
662 break;
663 case CMD_UDP_SET:
664 cmd_udp_set(mw);
665 break;
666 case CMD_SOCK_STAT: {
667 uint8_t channel = mw->transmit_buffer[4];
668 if (!channel || channel > 15) {
669 start_reply(mw, CMD_ERROR);
670 end_reply(mw);
671 break;
672 }
673 mw->channel_flags &= ~(1 << channel);
674 channel--;
675 poll_socket(mw, channel);
676 start_reply(mw, CMD_OK);
677 mw_putc(mw, mw->channel_state[channel]);
678 end_reply(mw);
679 break;
680 }
681 case CMD_DATETIME:
682 cmd_datetime(mw);
683 break;
684 case CMD_SYS_STAT:
685 poll_all_sockets(mw);
686 start_reply(mw, CMD_OK);
687 mw_putc(mw, mw->module_state);
688 mw_putc(mw, mw->flags);
689 mw_putc(mw, mw->channel_flags >> 8);
690 mw_putc(mw, mw->channel_flags);
691 end_reply(mw);
692 break;
693 case CMD_GAMERTAG_GET:
694 cmd_gamertag_get(mw);
695 break;
696 case CMD_LOG:
697 start_reply(mw, CMD_OK);
698 puts((char*)&mw->transmit_buffer[4]);
699 end_reply(mw);
700 break;
701 case CMD_HRNG_GET:
702 cmd_hrng_get(mw);
703 break;
704 case CMD_SERVER_URL_GET:
705 start_reply(mw, CMD_OK);
706 // FIXME: This should be get from config file
707 mw_puts(mw, "doragasu.com");
708 mw_putc(mw,'\0');
709 end_reply(mw);
710 break;
711 default:
712 printf("Unhandled MegaWiFi command %s(%d) with length %X\n", cmd_names[command], command, size);
713 break;
714 }
715 }
716
200 static void process_packet(megawifi *mw) 717 static void process_packet(megawifi *mw)
201 { 718 {
202 if (mw->transmit_channel == 0) { 719 if (mw->transmit_channel == 0) {
203 uint32_t command = mw->transmit_buffer[0] << 8 | mw->transmit_buffer[1]; 720 process_command(mw);
204 uint32_t size = mw->transmit_buffer[2] << 8 | mw->transmit_buffer[3]; 721 } else {
205 if (size > mw->transmit_bytes - 4) { 722 uint8_t channel = mw->transmit_channel - 1;
206 size = mw->transmit_bytes - 4; 723 int channel_state = mw->channel_state[channel];
207 } 724 int sock_fd = mw->sock_fds[channel];
208 int orig_receive_bytes = mw->receive_bytes; 725 if (sock_fd >= 0 && channel_state == SOCKST_TCP_EST) {
209 switch (command) 726 int sent = send(sock_fd, (char*)mw->transmit_buffer, mw->transmit_bytes, 0);
210 { 727 if (sent < 0 && !socket_error_is_wouldblock()) {
211 case CMD_VERSION: 728 socket_close(sock_fd);
212 start_reply(mw, CMD_OK); 729 mw->sock_fds[channel] = -1;
213 mw_putc(mw, 1); 730 mw->channel_state[channel] = SOCKST_NONE;
214 mw_putc(mw, 0); 731 mw->channel_flags |= 1 << mw->transmit_channel;
215 mw_puts(mw, "blastem"); 732 } else if (sent < mw->transmit_bytes) {
216 end_reply(mw); 733 //TODO: save this data somewhere so it can be sent in poll_socket
217 break; 734 printf("Sent %d bytes on channel %d, but %d were requested\n", sent, mw->transmit_channel, mw->transmit_bytes);
218 case CMD_ECHO:
219 mw->receive_bytes = mw->transmit_bytes;
220 memcpy(mw->receive_buffer, mw->transmit_buffer, mw->transmit_bytes);
221 break;
222 case CMD_IP_CURRENT: {
223 iface_info i;
224 if (get_host_address(&i)) {
225 start_reply(mw, CMD_OK);
226 //config number and reserved bytes
227 mw_set(mw, 0, 4);
228 //ip
229 mw_copy(mw, i.ip, sizeof(i.ip));
230 //net mask
231 mw_copy(mw, i.net_mask, sizeof(i.net_mask));
232 //gateway guess
233 mw_putc(mw, i.ip[0] & i.net_mask[0]);
234 mw_putc(mw, i.ip[1] & i.net_mask[1]);
235 mw_putc(mw, i.ip[2] & i.net_mask[2]);
236 mw_putc(mw, (i.ip[3] & i.net_mask[3]) + 1);
237 //dns
238 static const uint8_t localhost[] = {127,0,0,1};
239 mw_copy(mw, localhost, sizeof(localhost));
240 mw_copy(mw, localhost, sizeof(localhost));
241
242 } else {
243 start_reply(mw, CMD_ERROR);
244 } 735 }
245 end_reply(mw); 736 } else if (sock_fd >= 0 && channel_state == SOCKST_UDP_READY) {
246 break; 737 udp_send(mw, channel);
247 } 738 } else {
248 case CMD_AP_JOIN: 739 printf("Unhandled receive of MegaWiFi data on channel %d\n", mw->transmit_channel);
249 mw->module_state = STATE_READY; 740 }
250 start_reply(mw, CMD_OK);
251 end_reply(mw);
252 break;
253 case CMD_TCP_BIND:{
254 if (size < 7){
255 start_reply(mw, CMD_ERROR);
256 end_reply(mw);
257 break;
258 }
259 uint8_t channel = mw->transmit_buffer[10];
260 if (!channel || channel > 15) {
261 start_reply(mw, CMD_ERROR);
262 end_reply(mw);
263 break;
264 }
265 channel--;
266 if (mw->sock_fds[channel] >= 0) {
267 close(mw->sock_fds[channel]);
268 }
269 mw->sock_fds[channel] = socket(AF_INET, SOCK_STREAM, 0);
270 if (mw->sock_fds[channel] < 0) {
271 start_reply(mw, CMD_ERROR);
272 end_reply(mw);
273 break;
274 }
275 int value = 1;
276 setsockopt(mw->sock_fds[channel], SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
277 struct sockaddr_in bind_addr;
278 memset(&bind_addr, 0, sizeof(bind_addr));
279 bind_addr.sin_family = AF_INET;
280 bind_addr.sin_port = htons(mw->transmit_buffer[8] << 8 | mw->transmit_buffer[9]);
281 if (bind(mw->sock_fds[channel], (struct sockaddr *)&bind_addr, sizeof(bind_addr)) != 0) {
282 close(mw->sock_fds[channel]);
283 mw->sock_fds[channel] = -1;
284 start_reply(mw, CMD_ERROR);
285 end_reply(mw);
286 break;
287 }
288 int res = listen(mw->sock_fds[channel], 2);
289 start_reply(mw, res ? CMD_ERROR : CMD_OK);
290 if (res) {
291 close(mw->sock_fds[channel]);
292 mw->sock_fds[channel] = -1;
293 } else {
294 mw->channel_flags |= 1 << (channel + 1);
295 mw->channel_state[channel] = 1;
296 #ifndef _WIN32
297 //FIXME: Set nonblocking on Windows too
298 fcntl(mw->sock_fds[channel], F_SETFL, O_NONBLOCK);
299 #endif
300 }
301 end_reply(mw);
302 break;
303 }
304 case CMD_SOCK_STAT: {
305 uint8_t channel = mw->transmit_buffer[4];
306 if (!channel || channel > 15) {
307 start_reply(mw, CMD_ERROR);
308 end_reply(mw);
309 break;
310 }
311 mw->channel_flags &= ~(1 << channel);
312 channel--;
313 poll_socket(mw, channel);
314 start_reply(mw, CMD_OK);
315 mw_putc(mw, mw->channel_state[channel]);
316 end_reply(mw);
317 break;
318 }
319 case CMD_SYS_STAT:
320 poll_all_sockets(mw);
321 start_reply(mw, CMD_OK);
322 mw_putc(mw, mw->module_state);
323 mw_putc(mw, mw->flags);
324 mw_putc(mw, mw->channel_flags >> 8);
325 mw_putc(mw, mw->channel_flags);
326 end_reply(mw);
327 break;
328 default:
329 printf("Unhandled MegaWiFi command %s(%d) with length %X\n", cmd_names[command], command, size);
330 break;
331 }
332 } else if (mw->sock_fds[mw->transmit_channel - 1] >= 0 && mw->channel_state[mw->transmit_channel - 1] == 2) {
333 uint8_t channel = mw->transmit_channel - 1;
334 int sent = send(mw->sock_fds[channel], mw->transmit_buffer, mw->transmit_bytes, MSG_NOSIGNAL);
335 if (sent < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
336 close(mw->sock_fds[channel]);
337 mw->sock_fds[channel] = -1;
338 mw->channel_state[channel] = 0;
339 mw->channel_flags |= 1 << mw->transmit_channel;
340 } else if (sent < mw->transmit_bytes) {
341 //TODO: save this data somewhere so it can be sent in poll_socket
342 printf("Sent %d bytes on channel %d, but %d were requested\n", sent, mw->transmit_channel, mw->transmit_bytes);
343 }
344 } else {
345 printf("Unhandled receive of MegaWiFi data on channel %d\n", mw->transmit_channel);
346 } 741 }
347 mw->transmit_bytes = mw->expected_bytes = 0; 742 mw->transmit_bytes = mw->expected_bytes = 0;
348 } 743 }
349 744
350 void *megawifi_write_b(uint32_t address, void *context, uint8_t value) 745 void *megawifi_write_b(uint32_t address, void *context, uint8_t value)