diff options
Diffstat (limited to 'main/tcp_server.c')
-rw-r--r-- | main/tcp_server.c | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/main/tcp_server.c b/main/tcp_server.c index f50dc21..7bfaa61 100644 --- a/main/tcp_server.c +++ b/main/tcp_server.c @@ -1,8 +1,226 @@ +#include <ctype.h> + #include "tcp_server.h" +#include "sockbuf.h" #include "lwip/sockets.h" #include "station.h" +static int strcmp_(const char* s1, const char* s2) +{ + if (!s1) { + return !s2; + } + + if (!s2) { + return !s1; + } + + return strcmp(s1, s2); +} + +static char* read_token(sockbuf_t* sockbuf, char* into, size_t sz) +{ + int cur = 0; + + int ch = get_char(sockbuf); + + while (ch >= 0 && isspace(ch)) { + ch = get_char(sockbuf); + } + + while (ch >= 0 && !isspace(ch)) { + if (sz > 1) { + into[cur++] = (char) ch; + sz --; + } + ch = get_char(sockbuf); + } + + if (ch < 0) { + return NULL; + } + + if (sz >= 1) { + into[cur] = 0; + } + return into; +} + +static void handle_int_option( + const char* attr, + sockbuf_t* sockbuf, + int* ptr) +{ + char op_[8]; + char buf_[32]; + + char* op = read_token(sockbuf, op_, sizeof(op_)); + char* value = read_token(sockbuf, buf_, sizeof(buf_)); + + int curval = *ptr; + int ivalue = atoi(value); + if (!strcmp_(op, "+=")) { + curval += ivalue; + } else if (!strcmp_(op, "-=")) { + curval -= ivalue; + } else if (!strcmp_(op, "=")) { + curval = ivalue; + } else { + sockbuf_write(sockbuf, "Unknown operation: '"); + sockbuf_write(sockbuf, op); + sockbuf_write(sockbuf, "'\n"); + return; + } + + snprintf(buf_, sizeof(buf_), "%s = %d\n", attr, curval); + *ptr = curval; + sockbuf_write(sockbuf, buf_); +} + +static void handle_uint8_option( + const char* attr, + sockbuf_t* sockbuf, + uint8_t* ptr) +{ + int tmp = *ptr; + handle_int_option(attr, sockbuf, &tmp); + *ptr = tmp; +} + +static void handle_uint32_option( + const char* attr, + sockbuf_t* sockbuf, + uint32_t* ptr) +{ + int tmp = *ptr; + handle_int_option(attr, sockbuf, &tmp); + *ptr = tmp; +} + +static void handle_bool_option( + const char* attr, + sockbuf_t* sockbuf, + bool* ptr) +{ + char buf_[32]; + char* op = read_token(sockbuf, buf_, sizeof(buf_)); + + bool curval = *ptr; + if (!strcmp(op, "on")) { + curval = 1; + } else if (!strcmp(op, "off")) { + curval = 0; + } else if (!strcmp(op, "toggle")) { + curval = !curval; + } else { + sockbuf_write(sockbuf, "Invalid value: '"); + sockbuf_write(sockbuf, op); + sockbuf_write(sockbuf, "'\n"); + return; + } + + *ptr = curval; + snprintf(buf_, sizeof(buf_), "%s = %s\n", attr, curval ? "on" : "off"); + sockbuf_write(sockbuf, buf_); +} + +#define HANDLE_UINT8_OPTION(attr) \ + else if (!strcmp_(key, #attr)) { \ + handle_uint8_option(#attr, sockbuf, &ws_params->state. attr); \ + } + +#define HANDLE_INT_OPTION(attr) \ + else if (!strcmp_(key, #attr)) { \ + handle_int_option(#attr, sockbuf, &ws_params->state. attr); \ + } + +#define HANDLE_UINT32_OPTION(attr) \ + else if (!strcmp_(key, #attr)) { \ + handle_uint32_option(#attr, sockbuf, &ws_params->state. attr); \ + } + +#define HANDLE_BOOL_OPTION(attr) \ + else if (!strcmp_(key, #attr)) { \ + handle_bool_option(#attr, sockbuf, &ws_params->state. attr); \ + } + +static void handle_set_cmd( + sockbuf_t* sockbuf, ws_params_t* ws_params, const char* key) +{ + if (false) {} + + HANDLE_UINT8_OPTION(brightness) + HANDLE_UINT8_OPTION(n_snow) + HANDLE_UINT8_OPTION(n_red) + + HANDLE_INT_OPTION(timetick) + HANDLE_UINT32_OPTION(time) + + HANDLE_BOOL_OPTION(sleep) + HANDLE_BOOL_OPTION(power) + HANDLE_BOOL_OPTION(cool) + + else { + sockbuf_write(sockbuf, "Unknown attribute: '"); + sockbuf_write(sockbuf, key); + sockbuf_write(sockbuf, "'\n"); + } +} + +#define PRINT_INT(attr) \ + snprintf(buf, sizeof(buf), #attr ": %d\n", (int) ws_params->state. attr); \ + sockbuf_write(sockbuf, buf) +#define PRINT_BOOL(attr) \ + snprintf(buf, sizeof(buf), #attr ": %s\n", \ + ws_params->state. attr ? "on" : "off"); \ + sockbuf_write(sockbuf, buf) +static void handle_print_cmd(sockbuf_t* sockbuf, ws_params_t* ws_params) +{ + char buf[128]; + + PRINT_INT(time); + PRINT_INT(timetick); + PRINT_INT(brightness); + PRINT_INT(off); + PRINT_INT(n_snow); + PRINT_INT(n_red); + + PRINT_BOOL(sleep); + PRINT_BOOL(power); + PRINT_BOOL(cool); +} + +static void run_sockbuf(sockbuf_t* sockbuf, ws_params_t* ws_params) +{ + char buf[128]; + + while (true) { + char* cmd = read_token(sockbuf, buf, sizeof(buf)); + + if (!cmd) { + break; + } + + if (!strcmp_(cmd, "set")) { + char* key = read_token(sockbuf, buf, sizeof(buf)); + + if (key) { + handle_set_cmd(sockbuf, ws_params, key); + } + } else if (!strcmp_(cmd, "print")) { + handle_print_cmd(sockbuf, ws_params); + } else if (!strcmp_(cmd, "end")) { + close(sockbuf->socket); + return; + } else { + sockbuf_write(sockbuf, "Unknown command: '"); + sockbuf_write(sockbuf, cmd); + sockbuf_write(sockbuf, "'\n"); + } + } +} + portTASK_FUNCTION(tcp_server, params) { ws_params_t* ws_params = (ws_params_t*) params; @@ -32,6 +250,10 @@ portTASK_FUNCTION(tcp_server, params) int sock = accept(s, (struct sockaddr*)&client_addr, &size); printf("Accepted connection\n"); + sockbuf_t sockbuf; + init_sockbuf(&sockbuf, sock); + run_sockbuf(&sockbuf, ws_params); + ssize_t len; char buf[128]; @@ -40,6 +262,14 @@ portTASK_FUNCTION(tcp_server, params) buf[len] = 0; printf("Read %s\n", buf); + if (!strcmp_(buf, "off\n")) { + ws_params->state.power = 0; + } + + if (!strcmp_(buf, "on\n")) { + ws_params->state.power = 1; + } + for (int i = 0; i < len; ++ i) { switch (buf[i]) { case '+': |