Browse Source

fix(parselog): recover panic from parsing OpenVPN log

When parsing OpenVPN log if the logfile is corrupt and not parsable
instead of crashing now we are recovering the thrown panic and allowing
OpenVPN some time to write it properly.

Fixes #70
Mustafa Arici 7 years ago
parent
commit
9f97850442
4 changed files with 41 additions and 0 deletions
  1. 3 0
      go.mod
  2. 6 0
      go.sum
  3. 9 0
      parselog.go
  4. 23 0
      parselog_test.go

+ 3 - 0
go.mod

@@ -5,6 +5,7 @@ require (
 	github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
 	github.com/asaskevich/govalidator v0.0.0-20171111151018-521b25f4b05f
 	github.com/coreos/go-iptables v0.2.0
+	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e
 	github.com/go-openapi/analysis v0.0.0-20180418034448-863ac7f90e00 // indirect
 	github.com/go-openapi/errors v0.0.0-20171226161601-7bcb96a367ba // indirect
@@ -26,7 +27,9 @@ require (
 	github.com/mattn/go-sqlite3 v1.6.0 // indirect
 	github.com/mitchellh/mapstructure v0.0.0-20180511142126-bb74f1db0675 // indirect
 	github.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84
+	github.com/pmezard/go-difflib v1.0.0 // indirect
 	github.com/sirupsen/logrus v1.0.5
+	github.com/stretchr/testify v1.2.2
 	github.com/urfave/cli v1.20.0
 	golang.org/x/crypto v0.0.0-20180513064651-94e3fad7f1b4 // indirect
 	golang.org/x/net v0.0.0-20180511174649-2491c5de3490

+ 6 - 0
go.sum

@@ -6,6 +6,8 @@ github.com/asaskevich/govalidator v0.0.0-20171111151018-521b25f4b05f h1:xHxhygLk
 github.com/asaskevich/govalidator v0.0.0-20171111151018-521b25f4b05f/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
 github.com/coreos/go-iptables v0.2.0 h1:RmVRALeVCicZcF3rF05e0ooU9x9TmalN0HcT4hkhG5s=
 github.com/coreos/go-iptables v0.2.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e h1:Fw7ZmgiklsLh5EQWyHh1sumKSCG1+yjEctIpGKib87s=
 github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 github.com/go-openapi/analysis v0.0.0-20180418034448-863ac7f90e00 h1:b76E8vAKRC8E+tl1suDCKnc8Q50m2j/SW4PVR/uTlKU=
@@ -48,8 +50,12 @@ github.com/mitchellh/mapstructure v0.0.0-20180511142126-bb74f1db0675 h1:/rdJjIiK
 github.com/mitchellh/mapstructure v0.0.0-20180511142126-bb74f1db0675/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
 github.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84 h1:fiKJgB4JDUd43CApkmCeTSQlWjtTtABrU2qsgbuP0BI=
 github.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/sirupsen/logrus v1.0.5 h1:8c8b5uO0zS4X6RPl/sd1ENwSkIc0/H2PaHxE3udaE8I=
 github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
+github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
 github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
 golang.org/x/crypto v0.0.0-20180513064651-94e3fad7f1b4 h1:WTMZrvoRWzf+3YKGwBvVgUuvEWwzIQ65nA9x6mdIq8Y=

+ 9 - 0
parselog.go

@@ -6,6 +6,8 @@ import (
 	"strconv"
 	"strings"
 	"time"
+
+	"github.com/sirupsen/logrus"
 )
 
 // clEntry reprsents a parsed entry that is present on OpenVPN
@@ -30,6 +32,13 @@ type rtEntry struct {
 // parseStatusLog parses the received OpenVPN status log file.
 // And then returns the parsed client information.
 func parseStatusLog(f io.Reader) ([]clEntry, []rtEntry) {
+	// Recover any panics
+	defer func() {
+		if r := recover(); r != nil {
+			logrus.WithField("panic", r).Error("OpenVPN log file is corrupt")
+		}
+	}()
+
 	// Parsing stages.
 	const stageCL int = 0
 	const stageRT int = 1

+ 23 - 0
parselog_test.go

@@ -5,6 +5,8 @@ import (
 	"io"
 	"reflect"
 	"testing"
+
+	"github.com/stretchr/testify/assert"
 )
 
 func Test_parseStatusLog(t *testing.T) {
@@ -80,3 +82,24 @@ func Test_parseStatusLog(t *testing.T) {
 		})
 	}
 }
+
+func Test_parseStatusLog_CorruptStatusLog(t *testing.T) {
+	const exampleLogFile = `OpenVPN CLIENT LIST
+	Updated,Mon Mar 26 13:26:10 2018
+	Common Name,Real Address,Bytes Received,Bytes Sent,Connected Since
+	google.DNS,8.8.8.8Name,Real Addressdfs,Last Ref
+	10.20.30.6,google.DNS,8.8.8.8:33974,Mon Mar 26 13:26:04 2018
+	10.20.30.5,google1.DNS,8..4.4:53246,Mon Mar 26 13:25:57 2018
+	GLOBAL STATS
+	Max bcast/mcast queue length,4
+	END
+	`
+
+	// Mock the status log file.
+	f := bytes.NewBufferString(exampleLogFile)
+
+	cl, rt := parseStatusLog(f)
+
+	assert.Empty(t, cl)
+	assert.Empty(t, rt)
+}