diff --git a/CHANGELOG.md b/CHANGELOG.md index ce45067..e87ce57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 3.8.0 + - Added support for transparent framing / octet-counting. See [RFC 6587 section 3.4.1](https://www.ietf.org/rfc/rfc6587.txt) + ## 3.7.1 - Fix issue where the priority field was not being set correctly when grok failed [#76](https://github.com/logstash-plugins/logstash-input-syslog/pull/78) diff --git a/docs/index.asciidoc b/docs/index.asciidoc index 49423a9..5cb7a35 100644 --- a/docs/index.asciidoc +++ b/docs/index.asciidoc @@ -33,8 +33,9 @@ supports `RFC3164` syslog with some small modifications. However, some non-standard syslog formats can be read and parsed if a functional `grok_pattern` is provided. The date format is still only allowed to be `RFC3164` style or `ISO8601`. +This input supports UDP and TCP. Both TCP transparent and non-transparent framming are supported. -For more information see the http://www.ietf.org/rfc/rfc3164.txt[RFC3164 page]. +For more information on syslog see the http://www.ietf.org/rfc/rfc3164.txt[RFC3164 page] and for more information on TCP framing see the https://www.ietf.org/rfc/rfc6587.txt[RFC 6587 page]. Note: This input will start listeners on both TCP and UDP. diff --git a/lib/logstash/inputs/syslog.rb b/lib/logstash/inputs/syslog.rb index 1256dc1..081ebb6 100644 --- a/lib/logstash/inputs/syslog.rb +++ b/lib/logstash/inputs/syslog.rb @@ -227,16 +227,40 @@ def tcp_read_lines(socket) buffer = String.new loop do begin - buffer << socket.read_nonblock(1024) - while (newline = buffer.index("\n")) - yield buffer.slice!(0..newline) - end + buffer << socket.read_nonblock(1) + break if buffer.length >= 1 rescue IO::WaitReadable IO.select([socket], nil) retry end end - end + if buffer[0].match?(/\d/) #Check if the first char is a digit + loop do + begin + buffer << socket.read_nonblock(16) + first_space = buffer.index(" ") + log_len = Integer(buffer.slice!(0..first_space)) + buffer << socket.read_nonblock(log_len-buffer.length) + yield buffer.slice!(0..log_len) + rescue IO::WaitReadable + IO.select([socket], nil) + retry + end + end + else + loop do + begin + buffer << socket.read_nonblock(1024) + while (newline = buffer.index("\n")) + yield buffer.slice!(0..newline) + end + rescue IO::WaitReadable + IO.select([socket], nil) + retry + end + end + end + end # tcp_receiver is executed in a thread, any uncatched exception will be bubbled up to the # tcp server thread and all tcp connections will be closed and the listener restarted. diff --git a/version b/version index a76ccff..1981190 100644 --- a/version +++ b/version @@ -1 +1 @@ -3.7.1 +3.8.0