client: optimized client_input_received()
Use memchr() instead of manually traversing the input buffer. Update the client's properties after all commands have been processed. Check for buffer overflow once.
This commit is contained in:
parent
0031eaaff5
commit
6eb62e4761
82
src/client.c
82
src/client.c
@ -341,10 +341,9 @@ void client_new(int fd, const struct sockaddr *addr)
|
|||||||
sockaddr_to_tmp_string(addr));
|
sockaddr_to_tmp_string(addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int client_process_line(struct client *client)
|
static int client_process_line(struct client *client, char *line)
|
||||||
{
|
{
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
char *line = client->buffer + client->bufferPos;
|
|
||||||
|
|
||||||
if (client->cmd_list_OK >= 0) {
|
if (client->cmd_list_OK >= 0) {
|
||||||
if (strcmp(line, CLIENT_LIST_MODE_END) == 0) {
|
if (strcmp(line, CLIENT_LIST_MODE_END) == 0) {
|
||||||
@ -414,49 +413,56 @@ static int client_process_line(struct client *client)
|
|||||||
|
|
||||||
static int client_input_received(struct client *client, int bytesRead)
|
static int client_input_received(struct client *client, int bytesRead)
|
||||||
{
|
{
|
||||||
|
char *start = client->buffer + client->bufferLength;
|
||||||
|
char *end = start + bytesRead;
|
||||||
|
char *newline, *next;
|
||||||
int ret;
|
int ret;
|
||||||
char *buf_tail = &(client->buffer[client->bufferLength - 1]);
|
|
||||||
|
|
||||||
/* any input from the client makes it leave "idle" mode */
|
/* any input from the client makes it leave "idle" mode */
|
||||||
client->idle_waiting = false;
|
client->idle_waiting = false;
|
||||||
|
|
||||||
while (bytesRead > 0) {
|
client->bufferLength += bytesRead;
|
||||||
client->bufferLength++;
|
|
||||||
bytesRead--;
|
|
||||||
buf_tail++;
|
|
||||||
if (*buf_tail == '\n') {
|
|
||||||
*buf_tail = '\0';
|
|
||||||
if (client->bufferLength > client->bufferPos) {
|
|
||||||
if (*(buf_tail - 1) == '\r')
|
|
||||||
*(buf_tail - 1) = '\0';
|
|
||||||
}
|
|
||||||
ret = client_process_line(client);
|
|
||||||
if (ret == COMMAND_RETURN_KILL ||
|
|
||||||
ret == COMMAND_RETURN_CLOSE)
|
|
||||||
return ret;
|
|
||||||
if (client_is_expired(client))
|
|
||||||
return COMMAND_RETURN_CLOSE;
|
|
||||||
|
|
||||||
client->bufferPos = client->bufferLength;
|
/* process all lines */
|
||||||
}
|
while ((newline = memchr(start, '\n', end - start)) != NULL) {
|
||||||
if (client->bufferLength == CLIENT_MAX_BUFFER_LENGTH) {
|
next = newline + 1;
|
||||||
if (client->bufferPos == 0) {
|
|
||||||
ERROR("client %i: buffer overflow\n",
|
if (newline > start && newline[-1] == '\r')
|
||||||
client->num);
|
--newline;
|
||||||
return COMMAND_RETURN_CLOSE;
|
*newline = 0;
|
||||||
}
|
|
||||||
if (client->cmd_list_OK >= 0 &&
|
ret = client_process_line(client, start);
|
||||||
client->cmd_list &&
|
if (ret == COMMAND_RETURN_KILL ||
|
||||||
!client->cmd_list_dup)
|
ret == COMMAND_RETURN_CLOSE)
|
||||||
cmd_list_clone(client);
|
return ret;
|
||||||
assert(client->bufferLength >= client->bufferPos
|
if (client_is_expired(client))
|
||||||
&& "bufferLength >= bufferPos");
|
return COMMAND_RETURN_CLOSE;
|
||||||
client->bufferLength -= client->bufferPos;
|
|
||||||
memmove(client->buffer,
|
start = next;
|
||||||
client->buffer + client->bufferPos,
|
}
|
||||||
client->bufferLength);
|
|
||||||
client->bufferPos = 0;
|
/* mark consumed lines */
|
||||||
|
client->bufferPos = start - client->buffer;
|
||||||
|
|
||||||
|
/* if we're have reached the buffer's end, close the gab at
|
||||||
|
the beginning */
|
||||||
|
if (client->bufferLength == sizeof(client->buffer)) {
|
||||||
|
if (client->bufferPos == 0) {
|
||||||
|
ERROR("client %i: buffer overflow\n",
|
||||||
|
client->num);
|
||||||
|
return COMMAND_RETURN_CLOSE;
|
||||||
}
|
}
|
||||||
|
if (client->cmd_list_OK >= 0 &&
|
||||||
|
client->cmd_list &&
|
||||||
|
!client->cmd_list_dup)
|
||||||
|
cmd_list_clone(client);
|
||||||
|
assert(client->bufferLength >= client->bufferPos
|
||||||
|
&& "bufferLength >= bufferPos");
|
||||||
|
client->bufferLength -= client->bufferPos;
|
||||||
|
memmove(client->buffer,
|
||||||
|
client->buffer + client->bufferPos,
|
||||||
|
client->bufferLength);
|
||||||
|
client->bufferPos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user