diff --git a/inc/lektor/net.h b/inc/lektor/net.h index 7c64ff183a45d927a655adcb5c723f47aa176551..7741dba464badfb3435ff3df8c2cb55a27460e81 100644 --- a/inc/lektor/net.h +++ b/inc/lektor/net.h @@ -11,6 +11,7 @@ struct lkt_command { char *name; char *args[LKT_MESSAGE_ARGS_MAX]; + long cont; }; /* Create and destruct a command structure. */ @@ -47,11 +48,11 @@ struct lkt_state { void lkt_state_send(struct lkt_state *srv, size_t c, struct lkt_message *msg); /* Get and set continuation state for a client. */ +size_t lkt_remaining_msg(struct lkt_state *srv, size_t c); + bool lkt_get_continuation(struct lkt_state *srv, size_t c); void lkt_set_continuation(struct lkt_state *srv, size_t c, int i); -size_t lkt_remaining_msg(struct lkt_state *srv, size_t c); - /* Get the mask to watch for events for a given client, to be used with the `idle` command. * Return a pointer to the client's mask */ enum mpd_idle_flag *lkt_client_get_mask(struct lkt_state *srv, size_t c); diff --git a/src/main/lkt.c b/src/main/lkt.c index da9ad84b8ba88ff284e33ab1145078b3e0ca8226..5b04b0011cd5f0d35a5aa4e6a25e6dc54e843a65 100644 --- a/src/main/lkt.c +++ b/src/main/lkt.c @@ -585,11 +585,7 @@ list__(struct lkt_cmd_args *args) FILE *sock = NULL; redo: sock = lkt_connect(); - write_socket_format(sock, "command_list_begin\n" - "continue %d\n" - "playlist %s\n" - "command_list_end\n", - continuation, args->argv[0]); + write_socket_format(sock, "%d playlist %s\n", continuation, args->argv[0]); for (;;) { memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char)); @@ -597,8 +593,10 @@ redo: if (! strncmp(buff, "continue:", strlen("continue:"))) { continuation = atoi(lkt_skip_key(buff)); - fclose(sock); - goto redo; + if (continuation > 0) { + fclose(sock); + goto redo; + } } if (! strncmp(buff, "OK", 2)) diff --git a/src/net/command.c b/src/net/command.c index b41d44194965b6409232df722eef73485342df5e..130adca4b1ce11387b85614f651ad4c896637c34 100644 --- a/src/net/command.c +++ b/src/net/command.c @@ -4,12 +4,39 @@ #include <stdlib.h> #include <string.h> +#include <errno.h> +#include <limits.h> struct lkt_command lkt_command_parse(char *raw) { - struct lkt_command res = { .name = raw, .args = {0} }; + errno = 0; + char *endptr; + struct lkt_command res = { .name = raw, .args = {0}, .cont = strtol(raw, &endptr, 0) }; + if ((errno == ERANGE && (res.cont == LONG_MAX || res.cont == LONG_MIN)) || (errno != 0 && res.cont == 0)) { + res.cont = 0; + goto skip_cont; + } + + if (endptr == raw) { + res.cont = 0; + goto skip_cont; + } + + if (*endptr == '\0') { + /* That thing is an error. */ + return res; + } + + /* Get the real command name. */ + raw = endptr + strcspn(raw, " "); + if (!*raw) + return res; + res.name = raw; + + /* Get the args. */ +skip_cont: raw += strcspn(raw, " "); if (!*raw) return res; diff --git a/src/net/listen.c b/src/net/listen.c index f4bbf1524725049cc26846bb4608e678806b4e99..51bb903157ac693f8a1a1021f9dad150a5bdd65d 100644 --- a/src/net/listen.c +++ b/src/net/listen.c @@ -192,13 +192,6 @@ handle_simple_command(struct lkt_state *srv, size_t c, struct lkt_command cmd) err = !lkt_close_client(srv, c); else if (!strcmp(cmd.name, "ping")) err = 0; - else if (!strcmp(cmd.name, "continue")) { - continuation = atoi(cmd.args[0]); - lkt_set_continuation(srv, c, continuation); - fprintf(stderr, " * Client is continuing from %d\n", continuation); - err = 0; - goto skip_continue; - } else if (!strcmp(cmd.name, "next")) err = !command_next(srv->db, &srv->win, &srv->mpd_idle_events); @@ -308,7 +301,6 @@ handle_simple_command(struct lkt_state *srv, size_t c, struct lkt_command cmd) fprintf(stderr, " * Client should continue from %d\n", continuation); send_continue(srv, c, continuation); } -skip_continue: send_status(srv, c, err, cmd.name); end_no_send_status: return err; @@ -362,10 +354,13 @@ static int handle_incoming_data(struct lkt_state *srv, size_t i) { struct lkt_client *cli = &srv->clients[i - 1]; + int n; for (;;) { - int n = recv(srv->fds[i].fd, cli->buffer_in + cli->buffer_in_len, - LKT_MESSAGE_MAX - cli->buffer_in_len, 0); + /* Recieve some data. */ +recv: + n = recv(srv->fds[i].fd, cli->buffer_in + cli->buffer_in_len, + LKT_MESSAGE_MAX - cli->buffer_in_len, 0); if (n < 0) { if (errno == EWOULDBLOCK || errno == EAGAIN) return 0; @@ -375,11 +370,12 @@ handle_incoming_data(struct lkt_state *srv, size_t i) return -1; cli->buffer_in_len += n; + /* Handle the data. */ char *buf = cli->buffer_in; for (;;) { size_t line_len = strcspn(buf, "\n"); if (line_len >= cli->buffer_in_len) - break; + goto recv; buf[line_len] = 0; struct lkt_command cmd = lkt_command_parse(buf); @@ -390,7 +386,7 @@ handle_incoming_data(struct lkt_state *srv, size_t i) } if (cli->buffer_in < buf) - memcpy(cli->buffer_in, buf, cli->buffer_in_len); + memmove(cli->buffer_in, buf, cli->buffer_in_len); else if (cli->buffer_in_len == LKT_MESSAGE_MAX) return -1; }