# HG changeset patch # User doragasu # Date 1588534708 25200 # Node ID 6d99bdbf1e3e860dc18413f78eedfbaa9216ffba # Parent 9c01945b5d20d1b8d451a65be0992f2d8f20cc2a megawifi: refactor and update commands diff -r 9c01945b5d20 -r 6d99bdbf1e3e megawifi.c --- a/megawifi.c Sat May 02 17:33:23 2020 -0700 +++ b/megawifi.c Sun May 03 12:38:28 2020 -0700 @@ -25,7 +25,7 @@ }; #define STX 0x7E #define ETX 0x7E -#define MAX_RECV_SIZE 1440 +#define MAX_RECV_SIZE 1460 #define E(N) N enum { @@ -51,6 +51,14 @@ STATE_TRANSPARENT }; +enum { + SOCKST_NONE = 0, + SOCKST_TCP_LISTEN, + SOCKST_TCP_EST, + SOCKST_UDP_READY +}; + + #define FLAG_ONLINE typedef struct { @@ -112,22 +120,27 @@ mw->receive_bytes += count; } -static void mw_puts(megawifi *mw, char *s) +static void mw_putraw(megawifi *mw, const char *data, size_t len) { - uint32_t len = strlen(s); if ((mw->receive_bytes + len) > sizeof(mw->receive_buffer)) { return; } - memcpy(mw->receive_buffer + mw->receive_bytes, s, len); + memcpy(mw->receive_buffer + mw->receive_bytes, data, len); mw->receive_bytes += len; } +static void mw_puts(megawifi *mw, const char *s) +{ + size_t len = strlen(s); + mw_putraw(mw, s, len); +} + static void poll_socket(megawifi *mw, uint8_t channel) { if (mw->sock_fds[channel] < 0) { return; } - if (mw->channel_state[channel] == 1) { + if (mw->channel_state[channel] == SOCKST_TCP_LISTEN) { int res = accept(mw->sock_fds[channel], NULL, NULL); if (res >= 0) { close(mw->sock_fds[channel]); @@ -136,14 +149,14 @@ fcntl(res, F_SETFL, O_NONBLOCK); #endif mw->sock_fds[channel] = res; - mw->channel_state[channel] = 2; + mw->channel_state[channel] = SOCKST_TCP_EST; mw->channel_flags |= 1 << (channel + 1); } else if (errno != EAGAIN && errno != EWOULDBLOCK) { close(mw->sock_fds[channel]); - mw->channel_state[channel] = 0; + mw->channel_state[channel] = SOCKST_NONE; mw->channel_flags |= 1 << (channel + 1); } - } else if (mw->channel_state[channel] == 2 && mw->receive_bytes < sizeof(mw->receive_buffer) - 4) { + } else if (mw->channel_state[channel] == SOCKST_TCP_EST && mw->receive_bytes < sizeof(mw->receive_buffer) - 4) { size_t max = sizeof(mw->receive_buffer) - 4 - mw->receive_bytes; if (max > MAX_RECV_SIZE) { max = MAX_RECV_SIZE; @@ -158,7 +171,7 @@ //should this set the channel flag? } else if (bytes < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { close(mw->sock_fds[channel]); - mw->channel_state[channel] = 0; + mw->channel_state[channel] = SOCKST_NONE; mw->channel_flags |= 1 << (channel + 1); } } @@ -197,152 +210,163 @@ mw_putc(mw, ETX); } -static void process_packet(megawifi *mw) +static void process_command(megawifi *mw) { - if (mw->transmit_channel == 0) { - uint32_t command = mw->transmit_buffer[0] << 8 | mw->transmit_buffer[1]; - uint32_t size = mw->transmit_buffer[2] << 8 | mw->transmit_buffer[3]; - if (size > mw->transmit_bytes - 4) { - size = mw->transmit_bytes - 4; + uint32_t command = mw->transmit_buffer[0] << 8 | mw->transmit_buffer[1]; + uint32_t size = mw->transmit_buffer[2] << 8 | mw->transmit_buffer[3]; + if (size > mw->transmit_bytes - 4) { + size = mw->transmit_bytes - 4; + } + int orig_receive_bytes = mw->receive_bytes; + switch (command) + { + case CMD_VERSION: + start_reply(mw, CMD_OK); + mw_putc(mw, 1); + mw_putc(mw, 3); + mw_putc(mw, 0); + mw_puts(mw, "blastem"); + end_reply(mw); + break; + case CMD_ECHO: + mw->receive_bytes = mw->transmit_bytes; + memcpy(mw->receive_buffer, mw->transmit_buffer, mw->transmit_bytes); + break; + case CMD_IP_CURRENT: { + iface_info i; + if (get_host_address(&i)) { + start_reply(mw, CMD_OK); + //config number and reserved bytes + mw_set(mw, 0, 4); + //ip + mw_copy(mw, i.ip, sizeof(i.ip)); + //net mask + mw_copy(mw, i.net_mask, sizeof(i.net_mask)); + //gateway guess + mw_putc(mw, i.ip[0] & i.net_mask[0]); + mw_putc(mw, i.ip[1] & i.net_mask[1]); + mw_putc(mw, i.ip[2] & i.net_mask[2]); + mw_putc(mw, (i.ip[3] & i.net_mask[3]) + 1); + //dns + static const uint8_t localhost[] = {127,0,0,1}; + mw_copy(mw, localhost, sizeof(localhost)); + mw_copy(mw, localhost, sizeof(localhost)); + + } else { + start_reply(mw, CMD_ERROR); } - int orig_receive_bytes = mw->receive_bytes; - switch (command) - { - case CMD_VERSION: - start_reply(mw, CMD_OK); - mw_putc(mw, 1); - mw_putc(mw, 0); - mw_puts(mw, "blastem"); + end_reply(mw); + break; + } + case CMD_AP_JOIN: + mw->module_state = STATE_READY; + start_reply(mw, CMD_OK); + end_reply(mw); + break; + case CMD_TCP_BIND:{ + if (size < 7){ + start_reply(mw, CMD_ERROR); end_reply(mw); break; - case CMD_ECHO: - mw->receive_bytes = mw->transmit_bytes; - memcpy(mw->receive_buffer, mw->transmit_buffer, mw->transmit_bytes); + } + uint8_t channel = mw->transmit_buffer[10]; + if (!channel || channel > 15) { + start_reply(mw, CMD_ERROR); + end_reply(mw); break; - case CMD_IP_CURRENT: { - iface_info i; - if (get_host_address(&i)) { - start_reply(mw, CMD_OK); - //config number and reserved bytes - mw_set(mw, 0, 4); - //ip - mw_copy(mw, i.ip, sizeof(i.ip)); - //net mask - mw_copy(mw, i.net_mask, sizeof(i.net_mask)); - //gateway guess - mw_putc(mw, i.ip[0] & i.net_mask[0]); - mw_putc(mw, i.ip[1] & i.net_mask[1]); - mw_putc(mw, i.ip[2] & i.net_mask[2]); - mw_putc(mw, (i.ip[3] & i.net_mask[3]) + 1); - //dns - static const uint8_t localhost[] = {127,0,0,1}; - mw_copy(mw, localhost, sizeof(localhost)); - mw_copy(mw, localhost, sizeof(localhost)); - - } else { - start_reply(mw, CMD_ERROR); - } + } + channel--; + if (mw->sock_fds[channel] >= 0) { + close(mw->sock_fds[channel]); + } + mw->sock_fds[channel] = socket(AF_INET, SOCK_STREAM, 0); + if (mw->sock_fds[channel] < 0) { + start_reply(mw, CMD_ERROR); end_reply(mw); break; } - case CMD_AP_JOIN: - mw->module_state = STATE_READY; - start_reply(mw, CMD_OK); + int value = 1; + setsockopt(mw->sock_fds[channel], SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)); + struct sockaddr_in bind_addr; + memset(&bind_addr, 0, sizeof(bind_addr)); + bind_addr.sin_family = AF_INET; + bind_addr.sin_port = htons(mw->transmit_buffer[8] << 8 | mw->transmit_buffer[9]); + if (bind(mw->sock_fds[channel], (struct sockaddr *)&bind_addr, sizeof(bind_addr)) != 0) { + close(mw->sock_fds[channel]); + mw->sock_fds[channel] = -1; + start_reply(mw, CMD_ERROR); end_reply(mw); break; - case CMD_TCP_BIND:{ - if (size < 7){ - start_reply(mw, CMD_ERROR); - end_reply(mw); - break; - } - uint8_t channel = mw->transmit_buffer[10]; - if (!channel || channel > 15) { - start_reply(mw, CMD_ERROR); - end_reply(mw); - break; - } - channel--; - if (mw->sock_fds[channel] >= 0) { - close(mw->sock_fds[channel]); - } - mw->sock_fds[channel] = socket(AF_INET, SOCK_STREAM, 0); - if (mw->sock_fds[channel] < 0) { - start_reply(mw, CMD_ERROR); - end_reply(mw); - break; - } - int value = 1; - setsockopt(mw->sock_fds[channel], SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)); - struct sockaddr_in bind_addr; - memset(&bind_addr, 0, sizeof(bind_addr)); - bind_addr.sin_family = AF_INET; - bind_addr.sin_port = htons(mw->transmit_buffer[8] << 8 | mw->transmit_buffer[9]); - if (bind(mw->sock_fds[channel], (struct sockaddr *)&bind_addr, sizeof(bind_addr)) != 0) { - close(mw->sock_fds[channel]); - mw->sock_fds[channel] = -1; - start_reply(mw, CMD_ERROR); - end_reply(mw); - break; - } - int res = listen(mw->sock_fds[channel], 2); - start_reply(mw, res ? CMD_ERROR : CMD_OK); - if (res) { - close(mw->sock_fds[channel]); - mw->sock_fds[channel] = -1; - } else { - mw->channel_flags |= 1 << (channel + 1); - mw->channel_state[channel] = 1; + } + int res = listen(mw->sock_fds[channel], 2); + start_reply(mw, res ? CMD_ERROR : CMD_OK); + if (res) { + close(mw->sock_fds[channel]); + mw->sock_fds[channel] = -1; + } else { + mw->channel_flags |= 1 << (channel + 1); + mw->channel_state[channel] = SOCKST_TCP_LISTEN; #ifndef _WIN32 //FIXME: Set nonblocking on Windows too - fcntl(mw->sock_fds[channel], F_SETFL, O_NONBLOCK); + fcntl(mw->sock_fds[channel], F_SETFL, O_NONBLOCK); #endif - } + } + end_reply(mw); + break; + } + case CMD_SOCK_STAT: { + uint8_t channel = mw->transmit_buffer[4]; + if (!channel || channel > 15) { + start_reply(mw, CMD_ERROR); end_reply(mw); break; } - case CMD_SOCK_STAT: { - uint8_t channel = mw->transmit_buffer[4]; - if (!channel || channel > 15) { - start_reply(mw, CMD_ERROR); - end_reply(mw); - break; + mw->channel_flags &= ~(1 << channel); + channel--; + poll_socket(mw, channel); + start_reply(mw, CMD_OK); + mw_putc(mw, mw->channel_state[channel]); + end_reply(mw); + break; + } + case CMD_SYS_STAT: + poll_all_sockets(mw); + start_reply(mw, CMD_OK); + mw_putc(mw, mw->module_state); + mw_putc(mw, mw->flags); + mw_putc(mw, mw->channel_flags >> 8); + mw_putc(mw, mw->channel_flags); + end_reply(mw); + break; + default: + printf("Unhandled MegaWiFi command %s(%d) with length %X\n", cmd_names[command], command, size); + break; + } +} + +static void process_packet(megawifi *mw) +{ + if (mw->transmit_channel == 0) { + process_command(mw); + } else { + uint8_t channel = mw->transmit_channel - 1; + int channel_state = mw->channel_state[channel]; + int sock_fd = mw->sock_fds[channel]; + // TODO Handle UDP type sockets + if (sock_fd >= 0 && channel_state == SOCKST_TCP_EST) { + int sent = send(sock_fd, mw->transmit_buffer, mw->transmit_bytes, MSG_NOSIGNAL); + if (sent < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { + close(sock_fd); + mw->sock_fds[channel] = -1; + mw->channel_state[channel] = SOCKST_NONE; + mw->channel_flags |= 1 << mw->transmit_channel; + } else if (sent < mw->transmit_bytes) { + //TODO: save this data somewhere so it can be sent in poll_socket + printf("Sent %d bytes on channel %d, but %d were requested\n", sent, mw->transmit_channel, mw->transmit_bytes); } - mw->channel_flags &= ~(1 << channel); - channel--; - poll_socket(mw, channel); - start_reply(mw, CMD_OK); - mw_putc(mw, mw->channel_state[channel]); - end_reply(mw); - break; + } else { + printf("Unhandled receive of MegaWiFi data on channel %d\n", mw->transmit_channel); } - case CMD_SYS_STAT: - poll_all_sockets(mw); - start_reply(mw, CMD_OK); - mw_putc(mw, mw->module_state); - mw_putc(mw, mw->flags); - mw_putc(mw, mw->channel_flags >> 8); - mw_putc(mw, mw->channel_flags); - end_reply(mw); - break; - default: - printf("Unhandled MegaWiFi command %s(%d) with length %X\n", cmd_names[command], command, size); - break; - } - } else if (mw->sock_fds[mw->transmit_channel - 1] >= 0 && mw->channel_state[mw->transmit_channel - 1] == 2) { - uint8_t channel = mw->transmit_channel - 1; - int sent = send(mw->sock_fds[channel], mw->transmit_buffer, mw->transmit_bytes, MSG_NOSIGNAL); - if (sent < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { - close(mw->sock_fds[channel]); - mw->sock_fds[channel] = -1; - mw->channel_state[channel] = 0; - mw->channel_flags |= 1 << mw->transmit_channel; - } else if (sent < mw->transmit_bytes) { - //TODO: save this data somewhere so it can be sent in poll_socket - printf("Sent %d bytes on channel %d, but %d were requested\n", sent, mw->transmit_channel, mw->transmit_bytes); - } - } else { - printf("Unhandled receive of MegaWiFi data on channel %d\n", mw->transmit_channel); } mw->transmit_bytes = mw->expected_bytes = 0; } diff -r 9c01945b5d20 -r 6d99bdbf1e3e mw_commands.c --- a/mw_commands.c Sat May 02 17:33:23 2020 -0700 +++ b/mw_commands.c Sun May 03 12:38:28 2020 -0700 @@ -5,7 +5,7 @@ E(CMD_AP_CFG), E(CMD_AP_CFG_GET), E(CMD_IP_CURRENT), - E(CMD_RESERVED), + E(CMD_RESERVED_7), E(CMD_IP_CFG), E(CMD_IP_CFG_GET), E(CMD_DEF_AP_CFG), @@ -14,10 +14,10 @@ E(CMD_AP_LEAVE), E(CMD_TCP_CON), E(CMD_TCP_BIND), - E(CMD_TCP_ACCEPT), - E(CMD_TCP_DISC), + E(CMD_RESERVED_16), + E(CMD_CLOSE), E(CMD_UDP_SET), - E(CMD_UDP_CLR), + E(CMD_RESERVED_19), E(CMD_SOCK_STAT), E(CMD_PING), E(CMD_SNTP_CFG), @@ -30,4 +30,27 @@ E(CMD_FLASH_ID), E(CMD_SYS_STAT), E(CMD_DEF_CFG_SET), - E(CMD_HRNG_GET), \ No newline at end of file + E(CMD_HRNG_GET), + E(CMD_BSSID_GET), + E(CMD_GAMERTAG_SET), + E(CMD_GAMERTAG_GET), + E(CMD_LOG), + E(CMD_FACTORY_RESET), + E(CMD_SLEEP), + E(CMD_HTTP_URL_SET), + E(CMD_HTTP_METHOD_SET), + E(CMD_HTTP_CERT_QUERY), + E(CMD_HTTP_CERT_SET), + E(CMD_HTTP_HDR_ADD), + E(CMD_HTTP_HDR_DEL), + E(CMD_HTTP_OPEN), + E(CMD_HTTP_FINISH), + E(CMD_HTTP_CLEANUP), + E(CMD_RESERVED_48), + E(CMD_SERVER_URL_GET), + E(CMD_SERVER_URL_SET), + E(CMD_WIFI_ADV_GET), + E(CMD_WIFI_ADV_SET), + E(CMD_NV_CFG_SAVE), + E(CMD_UPGRADE_LIST), + E(CMD_UPGRADE_PERFORM),