aboutsummaryrefslogtreecommitdiffstats
path: root/src/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/client.c')
-rw-r--r--src/client.c89
1 files changed, 41 insertions, 48 deletions
diff --git a/src/client.c b/src/client.c
index bea35b848..65dc858f3 100644
--- a/src/client.c
+++ b/src/client.c
@@ -18,6 +18,7 @@
*/
#include "client.h"
+#include "fifo_buffer.h"
#include "command.h"
#include "conf.h"
#include "listen.h"
@@ -71,13 +72,12 @@ struct deferred_buffer {
};
struct client {
- char buffer[4096];
- size_t bufferLength;
- size_t bufferPos;
-
GIOChannel *channel;
guint source_id;
+ /** the buffer for reading lines from the #channel */
+ struct fifo_buffer *input;
+
unsigned permission;
/** the uid of the client process, or -1 if unknown */
@@ -176,8 +176,6 @@ static void client_init(struct client *client, int fd)
client->cmd_list_size = 0;
client->cmd_list_OK = -1;
- client->bufferLength = 0;
- client->bufferPos = 0;
#ifndef G_OS_WIN32
client->channel = g_io_channel_unix_new(fd);
@@ -197,6 +195,8 @@ static void client_init(struct client *client, int fd)
G_IO_IN|G_IO_ERR|G_IO_HUP,
client_in_event, client);
+ client->input = fifo_buffer_new(4096);
+
client->lastTime = time(NULL);
client->cmd_list = NULL;
client->deferred_send = g_queue_new();
@@ -370,54 +370,45 @@ static int client_process_line(struct client *client, char *line)
return ret;
}
+static char *
+client_read_line(struct client *client)
+{
+ const char *p, *newline;
+ size_t length;
+ char *line;
+
+ p = fifo_buffer_read(client->input, &length);
+ if (p == NULL)
+ return NULL;
+
+ newline = memchr(p, '\n', length);
+ if (newline == NULL)
+ return NULL;
+
+ line = g_strndup(p, newline - p);
+ fifo_buffer_consume(client->input, newline - p + 1);
+
+ return g_strchomp(line);
+}
+
static int client_input_received(struct client *client, size_t bytesRead)
{
- char *start = client->buffer + client->bufferPos, *end;
- char *newline, *next;
+ char *line;
int ret;
- assert(client->bufferPos <= client->bufferLength);
- assert(client->bufferLength + bytesRead <= sizeof(client->buffer));
-
- client->bufferLength += bytesRead;
- end = client->buffer + client->bufferLength;
+ fifo_buffer_append(client->input, bytesRead);
/* process all lines */
- while ((newline = memchr(start, '\n', end - start)) != NULL) {
- next = newline + 1;
- if (newline > start && newline[-1] == '\r')
- --newline;
- *newline = 0;
+ while ((line = client_read_line(client)) != NULL) {
+ ret = client_process_line(client, line);
+ g_free(line);
- ret = client_process_line(client, start);
if (ret == COMMAND_RETURN_KILL ||
ret == COMMAND_RETURN_CLOSE)
return ret;
if (client_is_expired(client))
return COMMAND_RETURN_CLOSE;
-
- start = next;
- }
-
- /* 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) {
- g_warning("[%u] buffer overflow",
- client->num);
- return COMMAND_RETURN_CLOSE;
- }
- 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;
@@ -425,18 +416,20 @@ static int client_input_received(struct client *client, size_t bytesRead)
static int client_read(struct client *client)
{
+ char *p;
+ size_t max_length;
GError *error = NULL;
GIOStatus status;
gsize bytes_read;
- assert(client->bufferPos <= client->bufferLength);
- assert(client->bufferLength < sizeof(client->buffer));
+ p = fifo_buffer_write(client->input, &max_length);
+ if (p == NULL) {
+ g_warning("[%u] buffer overflow", client->num);
+ return COMMAND_RETURN_CLOSE;
+ }
- status = g_io_channel_read_chars
- (client->channel,
- client->buffer + client->bufferLength,
- sizeof(client->buffer) - client->bufferLength,
- &bytes_read, &error);
+ status = g_io_channel_read_chars(client->channel, p, max_length,
+ &bytes_read, &error);
switch (status) {
case G_IO_STATUS_NORMAL:
return client_input_received(client, bytes_read);