[syslog-ng] [PATCH (3.4) 1/5] logproto: Introduce an indented multiline server class
Gergely Nagy
algernon at balabit.hu
Sat Oct 13 17:20:17 CEST 2012
The indented multiline class is derived from LogProtoTextServer, the
main difference is in determining what constitutes a full line: while
the text server considers a newline as a terminator, the indented
multiline server has stricter requirements: the newline must be
followed by another line that does not start with whitespace.
Signed-off-by: Gergely Nagy <algernon at balabit.hu>
---
lib/Makefile.am | 2 +
lib/logproto-builtins.c | 3 +
lib/logproto-indented-multiline-server.c | 90 ++++++++++++++++++++++++++++++
lib/logproto-indented-multiline-server.h | 44 +++++++++++++++
lib/logproto-text-server.c | 37 +++++++-----
lib/logproto-text-server.h | 8 +++
tests/unit/test_logproto.c | 45 +++++++++++++++
7 files changed, 216 insertions(+), 13 deletions(-)
create mode 100644 lib/logproto-indented-multiline-server.c
create mode 100644 lib/logproto-indented-multiline-server.h
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 65de69a..406cbd3 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -54,6 +54,7 @@ pkginclude_HEADERS = \
logproto-framed-server.h \
logproto-text-client.h \
logproto-text-server.h \
+ logproto-indented-multiline-server.h \
logproto-record-server.h \
logproto-builtins.h \
logproto.h \
@@ -137,6 +138,7 @@ libsyslog_ng_la_SOURCES = \
logproto-framed-server.c \
logproto-text-client.c \
logproto-text-server.c \
+ logproto-indented-multiline-server.c \
logproto-record-server.c \
logproto-builtins.c \
logqueue.c \
diff --git a/lib/logproto-builtins.c b/lib/logproto-builtins.c
index bbe23ce..c1d674c 100644
--- a/lib/logproto-builtins.c
+++ b/lib/logproto-builtins.c
@@ -24,6 +24,7 @@
#include "logproto-dgram-server.h"
#include "logproto-text-client.h"
#include "logproto-text-server.h"
+#include "logproto-indented-multiline-server.h"
#include "logproto-framed-client.h"
#include "logproto-framed-server.h"
#include "plugin.h"
@@ -35,6 +36,7 @@
DEFINE_LOG_PROTO_SERVER(log_proto_dgram);
DEFINE_LOG_PROTO_CLIENT(log_proto_text);
DEFINE_LOG_PROTO_SERVER(log_proto_text);
+DEFINE_LOG_PROTO_SERVER(log_proto_indented_multiline);
DEFINE_LOG_PROTO_CLIENT(log_proto_framed);
DEFINE_LOG_PROTO_SERVER(log_proto_framed);
@@ -43,6 +45,7 @@ static Plugin framed_server_plugins[] =
LOG_PROTO_SERVER_PLUGIN(log_proto_dgram, "dgram"),
LOG_PROTO_CLIENT_PLUGIN(log_proto_text, "text"),
LOG_PROTO_SERVER_PLUGIN(log_proto_text, "text"),
+ LOG_PROTO_SERVER_PLUGIN(log_proto_indented_multiline, "indented-multiline"),
LOG_PROTO_CLIENT_PLUGIN(log_proto_framed, "framed"),
LOG_PROTO_SERVER_PLUGIN(log_proto_framed, "framed"),
};
diff --git a/lib/logproto-indented-multiline-server.c b/lib/logproto-indented-multiline-server.c
new file mode 100644
index 0000000..e3b52d3
--- /dev/null
+++ b/lib/logproto-indented-multiline-server.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2012 BalaBit IT Ltd, Budapest, Hungary
+ * Copyright (c) 2012 Gergely Nagy <algernon at balabit.hu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "logproto-indented-multiline-server.h"
+#include "messages.h"
+
+#include <stdio.h>
+
+static gboolean
+log_proto_indented_multiline_server_line_is_complete(LogProtoTextServer *self,
+ LogProtoBufferedServerState *state,
+ const guchar **eol)
+{
+ gsize pos;
+
+ if (!*eol)
+ return FALSE;
+
+ /* If we have eol, find more eols until we get one where the next
+ char is non-whitespace. */
+
+ pos = *eol - self->super.buffer;
+
+ while (pos < state->pending_buffer_end - 1)
+ {
+ if (self->super.buffer[pos] == '\n')
+ *eol = self->super.buffer + pos;
+ else
+ {
+ pos++;
+ continue;
+ }
+
+ if (self->super.buffer[pos + 1] != ' ' &&
+ self->super.buffer[pos + 1] != '\t')
+ return TRUE;
+
+ pos++;
+ }
+
+ return FALSE;
+}
+
+static void
+log_proto_indented_multiline_server_line_flush (LogProtoTextServer *self,
+ LogProtoBufferedServerState *state,
+ const guchar **msg, gsize *msg_len,
+ const guchar *buffer_start, gsize buffer_bytes)
+{
+ *msg = buffer_start;
+ *msg_len = buffer_bytes;
+ if ((*msg)[buffer_bytes - 1] == '\n')
+ (*msg_len)--;
+
+ state->pending_buffer_pos = state->pending_buffer_end;
+}
+
+void
+log_proto_indented_multiline_server_init(LogProtoIMultiLineServer *self,
+ LogTransport *transport,
+ const LogProtoServerOptions *options)
+{
+ log_proto_text_server_init(&self->super, transport, options);
+ self->super.is_line_complete = log_proto_indented_multiline_server_line_is_complete;
+ self->super.line_flush = log_proto_indented_multiline_server_line_flush;
+}
+
+LogProtoServer *
+log_proto_indented_multiline_server_new(LogTransport *transport, const LogProtoServerOptions *options)
+{
+ LogProtoIMultiLineServer *self = g_new0(LogProtoIMultiLineServer, 1);
+
+ log_proto_indented_multiline_server_init(self, transport, options);
+ return &self->super.super.super;
+}
diff --git a/lib/logproto-indented-multiline-server.h b/lib/logproto-indented-multiline-server.h
new file mode 100644
index 0000000..260d9b1
--- /dev/null
+++ b/lib/logproto-indented-multiline-server.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2012 BalaBit IT Ltd, Budapest, Hungary
+ * Copyright (c) 2012 Gergely Nagy <algernon at balabit.hu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+#ifndef LOGPROTO_INDENTED_MULTILINE_SERVER_INCLUDED
+#define LOGPROTO_INDENTED_MULTILINE_SERVER_INCLUDED
+
+#include "logproto-text-server.h"
+
+typedef struct _LogProtoIMultiLineServer LogProtoIMultiLineServer;
+struct _LogProtoIMultiLineServer
+{
+ LogProtoTextServer super;
+};
+
+/* LogProtoIMultiLineServer
+ *
+ * This class processes indented multiline text files/streams. Each
+ * record consists of one line that starts with non-whitespace, with
+ * zero or more lines starting with whitespace. A record is terminated
+ * when we reach a line that starts with non-whitespace, or EOF.
+ */
+LogProtoServer *log_proto_indented_multiline_server_new(LogTransport *transport,
+ const LogProtoServerOptions *options);
+void log_proto_indented_multiline_server_init(LogProtoIMultiLineServer *self,
+ LogTransport *transport,
+ const LogProtoServerOptions *options);
+
+#endif
diff --git a/lib/logproto-text-server.c b/lib/logproto-text-server.c
index ed1ed90..600c06d 100644
--- a/lib/logproto-text-server.c
+++ b/lib/logproto-text-server.c
@@ -185,16 +185,25 @@ log_proto_text_server_get_raw_size_of_buffer(LogProtoTextServer *self, const guc
}
}
+static gboolean
+log_proto_text_server_line_is_complete(LogProtoTextServer *self,
+ LogProtoBufferedServerState *state,
+ const guchar **eol)
+{
+ return !!(*eol);
+}
+
+static void
+log_proto_text_server_line_flush (LogProtoTextServer *self,
+ LogProtoBufferedServerState *state,
+ const guchar **msg, gsize *msg_len,
+ const guchar *buffer_start, gsize buffer_bytes)
+{
+ *msg = buffer_start;
+ *msg_len = buffer_bytes;
+ state->pending_buffer_pos = state->pending_buffer_end;
+}
-/**
- * log_proto_text_server_fetch_from_buf:
- * @self: LogReader instance
- * @saddr: socket address to be assigned to new messages (consumed!)
- * @flush: whether to flush the input buffer
- * @msg_counter: the number of messages processed in the current poll iteration
- *
- * Returns TRUE if a message was found in the buffer, FALSE if we need to read again.
- **/
static gboolean
log_proto_text_server_fetch_from_buf(LogProtoBufferedServer *s, const guchar *buffer_start, gsize buffer_bytes, const guchar **msg, gsize *msg_len, gboolean flush_the_rest)
{
@@ -209,9 +218,7 @@ log_proto_text_server_fetch_from_buf(LogProtoBufferedServer *s, const guchar *bu
* we are set to packet terminating mode or the connection is to
* be teared down and we have partial data in our buffer.
*/
- *msg = buffer_start;
- *msg_len = buffer_bytes;
- state->pending_buffer_pos = state->pending_buffer_end;
+ self->line_flush (self, state, msg, msg_len, buffer_start, buffer_bytes);
goto success;
}
@@ -235,7 +242,7 @@ log_proto_text_server_fetch_from_buf(LogProtoBufferedServer *s, const guchar *bu
*msg = buffer_start;
goto success;
}
- else if (!eol)
+ else if (!self->is_line_complete(self, state, &eol))
{
gsize raw_split_size;
@@ -328,6 +335,10 @@ log_proto_text_server_init(LogProtoTextServer *self, LogTransport *transport, co
self->super.super.prepare = log_proto_text_server_prepare;
self->super.super.free_fn = log_proto_text_server_free;
self->super.fetch_from_buf = log_proto_text_server_fetch_from_buf;
+
+ self->is_line_complete = log_proto_text_server_line_is_complete;
+ self->line_flush = log_proto_text_server_line_flush;
+
self->super.stream_based = TRUE;
self->reverse_convert = (GIConv) -1;
}
diff --git a/lib/logproto-text-server.h b/lib/logproto-text-server.h
index 720d2a6..012db89 100644
--- a/lib/logproto-text-server.h
+++ b/lib/logproto-text-server.h
@@ -34,6 +34,14 @@ struct _LogProtoTextServer
gchar *reverse_buffer;
gsize reverse_buffer_len;
gint convert_scale;
+
+ gboolean (*is_line_complete)(LogProtoTextServer *self,
+ LogProtoBufferedServerState *state,
+ const guchar **eol);
+ void (*line_flush)(LogProtoTextServer *self,
+ LogProtoBufferedServerState *state,
+ const guchar **msg, gsize *msg_len,
+ const guchar *buffer_start, gsize buffer_bytes);
};
/* LogProtoTextServer
diff --git a/tests/unit/test_logproto.c b/tests/unit/test_logproto.c
index 2feec3d..51063f5 100644
--- a/tests/unit/test_logproto.c
+++ b/tests/unit/test_logproto.c
@@ -4,6 +4,7 @@
#include "logproto-text-server.h"
#include "logproto-framed-server.h"
#include "logproto-dgram-server.h"
+#include "logproto-indented-multiline-server.h"
#include "logproto-record-server.h"
#include "apphook.h"
@@ -507,6 +508,49 @@ test_log_proto_text_server(void)
}
/****************************************************************************************
+ * LogProtoIMultiLineServer
+ ****************************************************************************************/
+static void
+test_log_proto_indented_multiline_server_base(gboolean input_is_stream)
+{
+ LogProtoServer *proto;
+
+ log_proto_testcase_begin("test_log_proto_indented_multiline_server_base");
+ proto_server_options.max_msg_size = 32;
+
+ proto = log_proto_indented_multiline_server_new(
+ /* 32 bytes max line length */
+ (input_is_stream ? log_transport_mock_stream_new : log_transport_mock_records_new)(
+ "01234567\n"
+ /* line too long */
+ //"0123456789ABCDEF0123456789ABCDEF01234567\n", -1,
+ /* multi-line */
+ "0\n 1=2\n 3=4\nEND\n", -1,
+
+ LTM_EOF),
+ get_inited_proto_server_options());
+
+ assert_proto_server_fetch(proto, "01234567", -1);
+
+ /* input split due to an oversized input line */
+ //assert_proto_server_fetch(proto, "0123456789ABCDEF0123456789ABCDEF", -1);
+ //assert_proto_server_fetch(proto, "01234567", -1);
+
+ assert_proto_server_fetch(proto, "0\n 1=2\n 3=4", -1);
+ assert_proto_server_fetch(proto, "END", -1);
+
+ log_proto_server_free(proto);
+ log_proto_testcase_end();
+}
+
+static void
+test_log_proto_indented_multiline_server(void)
+{
+ test_log_proto_indented_multiline_server_base(FALSE);
+ test_log_proto_indented_multiline_server_base(TRUE);
+}
+
+/****************************************************************************************
* LogProtoDGramServer
****************************************************************************************/
@@ -883,6 +927,7 @@ test_log_proto(void)
test_log_proto_base();
test_log_proto_record_server();
test_log_proto_text_server();
+ test_log_proto_indented_multiline_server();
test_log_proto_dgram_server();
test_log_proto_framed_server();
}
--
1.7.10.4
More information about the syslog-ng
mailing list