/** * This file is part of Graylog. * * Graylog is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Graylog 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Graylog. If not, see <http://www.gnu.org/licenses/>. */ package org.graylog2.inputs.syslog.tcp; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.handler.codec.embedder.CodecEmbedderException; import org.jboss.netty.handler.codec.embedder.DecoderEmbedder; import org.junit.Before; import org.junit.Test; import java.nio.charset.StandardCharsets; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; public class SyslogOctetCountFrameDecoderTest { private DecoderEmbedder<ChannelBuffer> embedder; @Before public void setUp() throws Exception { embedder = new DecoderEmbedder<ChannelBuffer>(new SyslogOctetCountFrameDecoder()); } @Test public void testDecode() throws Exception { final ChannelBuffer buf1 = ChannelBuffers.copiedBuffer("123 <45>1 2014-10-21T10:21:09+00:00 c4dc57ba1ebb syslog-ng 7120 - [meta sequenceId=\"1\"] syslog-ng starting up; version='3.5.3'\n", StandardCharsets.UTF_8); final ChannelBuffer buf2 = ChannelBuffers.copiedBuffer("186 <45>1 2014-10-21T10:21:09+00:00 c4dc57ba1ebb syslog-ng 7120 - [meta sequenceId=\"2\"] Syslog connection established; fd='9', server='AF_INET(172.17.42.1:6666)', local='AF_INET(0.0.0.0:0)'\n", StandardCharsets.UTF_8); final ChannelBuffer buf3 = ChannelBuffers.wrappedBuffer(buf1, buf2, buf1); assertTrue(embedder.offer(buf1)); assertTrue(embedder.offer(buf2)); assertTrue(embedder.offer(buf3)); assertEquals(embedder.poll().toString(StandardCharsets.UTF_8), "<45>1 2014-10-21T10:21:09+00:00 c4dc57ba1ebb syslog-ng 7120 - [meta sequenceId=\"1\"] syslog-ng starting up; version='3.5.3'\n"); assertEquals(embedder.poll().toString(StandardCharsets.UTF_8), "<45>1 2014-10-21T10:21:09+00:00 c4dc57ba1ebb syslog-ng 7120 - [meta sequenceId=\"2\"] Syslog connection established; fd='9', server='AF_INET(172.17.42.1:6666)', local='AF_INET(0.0.0.0:0)'\n"); assertEquals(embedder.poll().toString(StandardCharsets.UTF_8), "<45>1 2014-10-21T10:21:09+00:00 c4dc57ba1ebb syslog-ng 7120 - [meta sequenceId=\"1\"] syslog-ng starting up; version='3.5.3'\n"); assertEquals(embedder.poll().toString(StandardCharsets.UTF_8), "<45>1 2014-10-21T10:21:09+00:00 c4dc57ba1ebb syslog-ng 7120 - [meta sequenceId=\"2\"] Syslog connection established; fd='9', server='AF_INET(172.17.42.1:6666)', local='AF_INET(0.0.0.0:0)'\n"); assertEquals(embedder.poll().toString(StandardCharsets.UTF_8), "<45>1 2014-10-21T10:21:09+00:00 c4dc57ba1ebb syslog-ng 7120 - [meta sequenceId=\"1\"] syslog-ng starting up; version='3.5.3'\n"); assertNull(embedder.poll()); } @Test public void testIncompleteFrameLengthValue() throws Exception { final ChannelBuffer buf1 = ChannelBuffers.copiedBuffer("12", StandardCharsets.UTF_8); final ChannelBuffer buf2 = ChannelBuffers.copiedBuffer("3 <45>1 2014-10-21T10:21:09+00:00 c4dc57ba1ebb syslog-ng 7120 - [meta sequenceId=\"1\"] syslog-ng starting up; version='3.5.3'\n", StandardCharsets.UTF_8); assertFalse(embedder.offer(buf1)); assertNull(embedder.poll()); assertTrue(embedder.offer(buf2)); assertEquals(embedder.poll().toString(StandardCharsets.UTF_8), "<45>1 2014-10-21T10:21:09+00:00 c4dc57ba1ebb syslog-ng 7120 - [meta sequenceId=\"1\"] syslog-ng starting up; version='3.5.3'\n"); } @Test public void testIncompleteFrames() throws Exception { final ChannelBuffer buf1 = ChannelBuffers.copiedBuffer("123 <45>1 2014-10-21T10:21:09+00:00 c4dc57ba1ebb syslog-ng 7120 - ", StandardCharsets.UTF_8); final ChannelBuffer buf2 = ChannelBuffers.copiedBuffer("[meta sequenceId=\"1\"] syslog-ng starting up; version='3.5.3'\n", StandardCharsets.UTF_8); assertFalse(embedder.offer(buf1)); assertNull(embedder.poll()); assertTrue(embedder.offer(buf2)); assertEquals(embedder.poll().toString(StandardCharsets.UTF_8), "<45>1 2014-10-21T10:21:09+00:00 c4dc57ba1ebb syslog-ng 7120 - [meta sequenceId=\"1\"] syslog-ng starting up; version='3.5.3'\n"); } @Test public void testIncompleteFramesAndSmallBuffer() throws Exception { /* * This test has been added to reproduce this issue: https://github.com/Graylog2/graylog2-server/issues/1105 * * It triggers an edge case where the buffer is missing <frame size value length + 1> bytes. * The SyslogOctetCountFrameDecoder was handling this wrong in previous versions and tried to read more from * the buffer than there was available after the frame size value bytes have been skipped. */ final byte[] bytes = "123 <45>1 2014-10-21T10:21:09+00:00 c4dc57ba1ebb syslog-ng 7120 - [meta sequenceId=\"1\"] syslog-ng starting up; version='3.5.".getBytes(StandardCharsets.UTF_8); final ChannelBuffer buf = ChannelBuffers.dynamicBuffer(bytes.length); buf.writeBytes(bytes); assertFalse(embedder.offer(buf)); assertNull(embedder.poll()); buf.writeBytes("3'\n".getBytes(StandardCharsets.UTF_8)); assertTrue(embedder.offer(buf)); assertEquals(embedder.poll().toString(StandardCharsets.UTF_8), "<45>1 2014-10-21T10:21:09+00:00 c4dc57ba1ebb syslog-ng 7120 - [meta sequenceId=\"1\"] syslog-ng starting up; version='3.5.3'\n"); } @Test(expected = CodecEmbedderException.class) public void testBrokenFrames() throws Exception { final ChannelBuffer buf1 = ChannelBuffers.copiedBuffer("1 2014-10-21T10:21:09+00:00 c4dc57ba1ebb syslog-ng 7120 - ", StandardCharsets.UTF_8); embedder.offer(buf1); } @Test public void testDecodeSupportsMessagesLongerThan1024Bytes() throws Exception { // All transport receiver // implementations SHOULD be able to accept messages of up to and // including 2048 octets in length. Transport receivers MAY receive // messages larger than 2048 octets in length. // -- https://tools.ietf.org/html/rfc5424#section-6.1 final byte[] bytes = new byte[2048]; for (int i = 0; i < bytes.length; i++) { bytes[i] = (byte) ('A' + (i % 26)); } final String longString = new String(bytes, StandardCharsets.UTF_8); final ChannelBuffer buffer = ChannelBuffers.copiedBuffer("2111 <45>1 2014-10-21T10:21:09+00:00 c4dc57ba1ebb syslog-ng 7120 - " + longString + "\n", StandardCharsets.UTF_8); assertTrue(embedder.offer(buffer)); embedder.finish(); assertEquals(embedder.poll().toString(StandardCharsets.UTF_8), "<45>1 2014-10-21T10:21:09+00:00 c4dc57ba1ebb syslog-ng 7120 - " + longString + "\n"); assertNull(embedder.poll()); } }