diff options
Diffstat (limited to 'fw/esp32/components/eos/sock.c')
-rw-r--r-- | fw/esp32/components/eos/sock.c | 344 |
1 files changed, 285 insertions, 59 deletions
diff --git a/fw/esp32/components/eos/sock.c b/fw/esp32/components/eos/sock.c index 08d95d5..b6ed3e9 100644 --- a/fw/esp32/components/eos/sock.c +++ b/fw/esp32/components/eos/sock.c @@ -1,6 +1,7 @@ #include <stdlib.h> #include <stdint.h> #include <string.h> +#include <sys/select.h> #include <freertos/FreeRTOS.h> #include <freertos/semphr.h> @@ -9,6 +10,9 @@ #include <esp_system.h> #include <esp_log.h> #include <esp_err.h> +#include <esp_vfs.h> +#include <esp_vfs_dev.h> +#include <esp_vfs_eventfd.h> #include <lwip/sockets.h> #include <lwip/err.h> @@ -23,8 +27,14 @@ static const char *TAG = "EOS SOCK"; static SemaphoreHandle_t mutex; +static int cmd_fd, rep_fd; static int _socks[EOS_SOCK_MAX_SOCK]; +#define CMD_OPEN 1 +#define CMD_CLOSE 2 +#define CMD_SEND 3 +#define CMD_REOPEN 4 + static int t_open_dgram(void) { struct sockaddr_in _myaddr; int sock; @@ -74,83 +84,246 @@ static ssize_t t_recvfrom(int sock, void *msg, size_t msg_size, EOSNetAddr *addr return recvlen; } +static void populate_fds(fd_set *fds, int *max_fd) { + int i; + + *max_fd = cmd_fd; + + FD_ZERO(fds); + FD_SET(cmd_fd, fds); + for (i=0; i<EOS_SOCK_MAX_SOCK; i++) { + if (_socks[i]) { + FD_SET(_socks[i], fds); + if (_socks[i] > *max_fd) { + *max_fd = _socks[i]; + } + } + } +} + static void udp_rcvr_task(void *pvParameters) { - uint8_t sock_i = (uint8_t)pvParameters; - int sock = _socks[sock_i-1]; - - do { - EOSNetAddr addr; - unsigned char *buf, *_buf; - ssize_t rv; - - buf = eos_net_alloc(); - rv = t_recvfrom(sock, buf + EOS_SOCK_SIZE_UDP_HDR, EOS_NET_SIZE_BUF - EOS_SOCK_SIZE_UDP_HDR, &addr); - if (rv < 0) { - eos_net_free(buf); - ESP_LOGE(TAG, "UDP RECV ERR:%d", rv); - break; + EOSNetAddr addr; + unsigned char *buffer; + uint16_t buf_len; + fd_set all_fds, read_fds; + uint8_t sock_i; + uint8_t cmd[8]; + ssize_t _rv; + int sock, max_fd, i; + int rv; + + assert(sizeof(buffer) == 4); + + populate_fds(&all_fds, &max_fd); + while (1) { + memcpy(&read_fds, &all_fds, sizeof(fd_set)); + rv = select(max_fd + 1, &read_fds, NULL, NULL, NULL); + if (rv <= 0) { + ESP_LOGE(TAG, "SELECT ERR:%d", rv); + continue; } - _buf = buf; - _buf[0] = EOS_SOCK_MTYPE_PKT; - _buf[1] = sock_i; - _buf += 2; - memcpy(_buf, addr.host, sizeof(addr.host)); - _buf += sizeof(addr.host); - _buf[0] = addr.port >> 8; - _buf[1] = addr.port; - _buf += sizeof(addr.port); - eos_net_send(EOS_NET_MTYPE_SOCK, buf, rv + EOS_SOCK_SIZE_UDP_HDR); - } while (1); - xSemaphoreTake(mutex, portMAX_DELAY); - _socks[sock_i-1] = 0; - xSemaphoreGive(mutex); + for (i=0; i<EOS_SOCK_MAX_SOCK; i++) { + sock = _socks[i]; + if (sock && FD_ISSET(sock, &read_fds)) { + unsigned char *_buf; + + buffer = eos_net_alloc(); + _rv = t_recvfrom(sock, buffer + EOS_SOCK_SIZE_UDP_HDR, EOS_NET_SIZE_BUF - EOS_SOCK_SIZE_UDP_HDR, &addr); + if (_rv < 0) { + eos_net_free(buffer); + ESP_LOGE(TAG, "RECV ERR:%d", _rv); + } + _buf = buffer; + _buf[0] = EOS_SOCK_MTYPE_PKT; + _buf[1] = i + 1; + _buf += 2; + memcpy(_buf, addr.host, sizeof(addr.host)); + _buf += sizeof(addr.host); + _buf[0] = addr.port >> 8; + _buf[1] = addr.port; + _buf += sizeof(addr.port); + rv = eos_net_send(EOS_NET_MTYPE_SOCK, buffer, _rv + EOS_SOCK_SIZE_UDP_HDR); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); + } + } + if (FD_ISSET(cmd_fd, &read_fds)) { + rv = read(cmd_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + switch (cmd[0]) { + case CMD_OPEN: { + sock = t_open_dgram(); + sock_i = 0; + if (sock > 0) { + for (i=0; i<EOS_SOCK_MAX_SOCK; i++) { + if (_socks[i] == 0) { + sock_i = i + 1; + _socks[i] = sock; + break; + } + } + if (sock_i) { + populate_fds(&all_fds, &max_fd); + } + } + memset(cmd, 0, sizeof(cmd)); + cmd[1] = sock_i; + + rv = write(rep_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + break; + } + + case CMD_CLOSE: { + sock_i = cmd[1] - 1; + sock = _socks[sock_i]; + if (sock) { + t_close(sock); + _socks[sock_i] = 0; + populate_fds(&all_fds, &max_fd); + } + + rv = write(rep_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + break; + } + + case CMD_SEND: { + sock_i = cmd[1] - 1; + buf_len = (uint16_t)cmd[2] << 8; + buf_len |= (uint16_t)cmd[3]; + memcpy(&buffer, cmd + 4, sizeof(buffer)); + + sock = _socks[sock_i]; + memcpy(addr.host, buffer, sizeof(addr.host)); + buffer += sizeof(addr.host); + buf_len -= sizeof(addr.host); + addr.port = (uint16_t)buffer[0] << 8; + addr.port |= (uint16_t)buffer[1]; + buffer += sizeof(addr.port); + buf_len -= sizeof(addr.port); + _rv = t_sendto(sock, buffer, buf_len, &addr); + + memset(cmd, 0, sizeof(cmd)); + + rv = write(rep_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + break; + } + + case CMD_REOPEN: { + buffer = NULL; + buf_len = 0; + + for (i=0; i<EOS_SOCK_MAX_SOCK; i++) { + sock = _socks[i]; + if (sock) { + t_close(sock); + _socks[i] = -1; + } + } + for (i=0; i<EOS_SOCK_MAX_SOCK; i++) { + sock = _socks[i]; + if (sock) { + sock = t_open_dgram(); + if (sock > 0) { + _socks[i] = sock; + } else { + _socks[i] = 0; + if (buffer) { + buffer[buf_len] = i + 1; + buf_len++; + } else { + buffer = eos_net_alloc(); + buffer[0] = EOS_SOCK_MTYPE_CLOSE; + buffer[1] = i + 1; + buf_len = 2; + } + } + } + } + if (buffer) { + rv = eos_net_send(EOS_NET_MTYPE_SOCK, buffer, buf_len); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); + } + + rv = write(rep_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + break; + } + + default: + ESP_LOGE(TAG, "BAD CMD:%d", cmd[0]); + break; + } + + } + } + vTaskDelete(NULL); } static void sock_handler(unsigned char _mtype, unsigned char *buffer, uint16_t buf_len) { unsigned char mtype; uint8_t sock_i; - int sock, i; + uint8_t cmd[8]; + int rv; if (buf_len < 1) return; + memset(cmd, 0, sizeof(cmd)); + mtype = buffer[0]; switch (mtype) { case EOS_SOCK_MTYPE_PKT: { - EOSNetAddr addr; + unsigned char *_buf = buffer; if (buf_len < EOS_SOCK_SIZE_UDP_HDR) return; - sock_i = buffer[1]-1; - if (sock_i >= EOS_SOCK_MAX_SOCK) return; - - sock = _socks[sock_i]; - buffer += 2; - memcpy(addr.host, buffer, sizeof(addr.host)); - buffer += sizeof(addr.host); - addr.port = (uint16_t)buffer[0] << 8; - addr.port |= (uint16_t)buffer[1]; - buffer += sizeof(addr.port); - t_sendto(sock, buffer, buf_len - EOS_SOCK_SIZE_UDP_HDR, &addr); + sock_i = buffer[1]; + if ((sock_i == 0) || (sock_i > EOS_SOCK_MAX_SOCK)) return; + + _buf += 2; + cmd[0] = CMD_SEND; + cmd[1] = sock_i; + cmd[2] = buf_len >> 8; + cmd[3] = buf_len; + memcpy(cmd + 4, &_buf, sizeof(_buf)); + + xSemaphoreTake(mutex, portMAX_DELAY); + + rv = write(cmd_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + rv = read(rep_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + xSemaphoreGive(mutex); + + assert(cmd[0] == CMD_SEND); break; } case EOS_SOCK_MTYPE_OPEN_DGRAM: { - sock = t_open_dgram(); - sock_i = 0; - if (sock > 0) { - xSemaphoreTake(mutex, portMAX_DELAY); - for (i=0; i<EOS_SOCK_MAX_SOCK; i++) { - if (_socks[i] == 0) { - sock_i = i+1; - _socks[i] = sock; - break; - } - } - xSemaphoreGive(mutex); - } - if (sock_i) xTaskCreate(&udp_rcvr_task, "udp_rcvr", EOS_TASK_SSIZE_UDP_RCVR, (void *)sock_i, EOS_TASK_PRIORITY_UDP_RCVR, NULL); + cmd[0] = CMD_OPEN; + + xSemaphoreTake(mutex, portMAX_DELAY); + + rv = write(cmd_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + rv = read(rep_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + xSemaphoreGive(mutex); + + assert(cmd[0] == CMD_OPEN); + sock_i = cmd[1]; buffer[0] = EOS_SOCK_MTYPE_OPEN_DGRAM; buffer[1] = sock_i; eos_net_reply(EOS_NET_MTYPE_SOCK, buffer, 2); @@ -160,19 +333,72 @@ static void sock_handler(unsigned char _mtype, unsigned char *buffer, uint16_t b case EOS_SOCK_MTYPE_CLOSE: { if (buf_len < 2) return; - sock_i = buffer[1]-1; - if (sock_i >= EOS_SOCK_MAX_SOCK) return; + sock_i = buffer[1]; + if ((sock_i == 0) || (sock_i > EOS_SOCK_MAX_SOCK)) return; + + cmd[0] = CMD_CLOSE; + cmd[1] = sock_i; + + xSemaphoreTake(mutex, portMAX_DELAY); - sock = _socks[sock_i]; - t_close(sock); + rv = write(cmd_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + rv = read(rep_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + xSemaphoreGive(mutex); + + assert(cmd[0] == CMD_CLOSE); break; } } } void eos_sock_init(void) { + esp_vfs_eventfd_config_t config = ESP_VFS_EVENTD_CONFIG_DEFAULT(); + esp_err_t ret; + + ret = esp_vfs_eventfd_register(&config); + assert(ret == ESP_OK); + + cmd_fd = eventfd(0, 0); + assert(cmd_fd > 0); + + rep_fd = eventfd(0, 0); + assert(rep_fd > 0); + mutex = xSemaphoreCreateBinary(); + assert(mutex != NULL); xSemaphoreGive(mutex); + eos_net_set_handler(EOS_NET_MTYPE_SOCK, sock_handler); + ESP_LOGI(TAG, "INIT"); } + +void eos_sock_run(void) { + BaseType_t rv; + + rv = xTaskCreate(&udp_rcvr_task, "udp_rcvr", EOS_TASK_SSIZE_SOCK, NULL, EOS_TASK_PRIORITY_SOCK, NULL); + assert(rv == pdPASS); + + ESP_LOGI(TAG, "RUN"); +} + +void eos_sock_reopen(void) { + uint8_t cmd[8]; + int rv; + + cmd[0] = CMD_REOPEN; + xSemaphoreTake(mutex, portMAX_DELAY); + + rv = write(cmd_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + rv = read(rep_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + xSemaphoreGive(mutex); + assert(cmd[0] == CMD_REOPEN); +} |