-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
479 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package rfc3164 | ||
|
||
import "errors" | ||
|
||
var ( | ||
ErrInvalidPRI = errors.New("invalid PRI") | ||
ErrInvalidTimestamp = errors.New("invalid timestamp") | ||
ErrInvalidHostname = errors.New("invalid hostname") | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package rfc3164 | ||
|
||
import ( | ||
"time" | ||
) | ||
|
||
type Message struct { | ||
PRI PRI | ||
Timestamp time.Time | ||
Hostname string | ||
Tag string | ||
Content string | ||
} | ||
|
||
// PRI represents the Priority value of a syslog message. | ||
// The PRI is a single byte that encodes the facility and severity of the message. | ||
type PRI struct { | ||
value byte | ||
} | ||
|
||
func NewPRI(value byte) (PRI, error) { | ||
if value > 191 { | ||
return PRI{}, ErrInvalidPRI | ||
} | ||
return PRI{value: value}, nil | ||
} | ||
|
||
// Facility returns the facility value of the PRI. | ||
func (p PRI) Facility() byte { | ||
return p.value & 0xF8 >> 3 | ||
} | ||
|
||
// Severity returns the severity value of the PRI. | ||
func (p PRI) Severity() byte { | ||
return p.value & 0x07 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package rfc3164 | ||
|
||
import ( | ||
"io" | ||
"strings" | ||
"time" | ||
) | ||
|
||
type Parser struct{} | ||
|
||
// NewParser creates a new Parser. | ||
func NewParser() Parser { | ||
return Parser{} | ||
} | ||
|
||
func (p Parser) Parse(input io.ByteScanner) (Message, error) { | ||
var m Message | ||
|
||
pri, err := parsePRI(input) | ||
if err != nil { | ||
return m, err | ||
} | ||
|
||
timestamp, err := parseTimestamp(input) | ||
if err != nil { | ||
return m, err | ||
} | ||
|
||
hostname, err := parseHostname(input) | ||
if err != nil { | ||
return m, err | ||
} | ||
|
||
tag, content := parseMessage(input) | ||
|
||
return Message{ | ||
PRI: PRI{pri}, | ||
Timestamp: timestamp, | ||
Hostname: hostname, | ||
Tag: tag, | ||
Content: content, | ||
}, nil | ||
} | ||
|
||
// parsePRI parses the PRI part of a syslog message. | ||
func parsePRI(input io.ByteScanner) (byte, error) { | ||
b, err := input.ReadByte() | ||
if err != nil || b != '<' { | ||
return 0, ErrInvalidPRI | ||
} | ||
|
||
PRI := byte(0) | ||
for i := 0; i < 4; i++ { | ||
b, err = input.ReadByte() | ||
if err != nil { | ||
return 0, ErrInvalidPRI | ||
} | ||
if b == '>' { | ||
if PRI > 191 { | ||
return 0, ErrInvalidPRI | ||
} | ||
return PRI, nil | ||
} | ||
if b < '0' || b > '9' { | ||
return 0, ErrInvalidPRI | ||
} | ||
PRI = PRI*10 + (b - '0') | ||
} | ||
|
||
return 0, ErrInvalidPRI | ||
} | ||
|
||
func parseTimestamp(input io.ByteScanner) (time.Time, error) { | ||
b, err := input.ReadByte() | ||
if err != nil { | ||
return time.Time{}, ErrInvalidTimestamp | ||
} | ||
if b == ' ' { | ||
return time.Time{}, nil | ||
} | ||
|
||
builder := strings.Builder{} | ||
builder.WriteByte(b) | ||
for i := 0; i < 14; i++ { | ||
b, err := input.ReadByte() | ||
if err != nil { | ||
return time.Time{}, ErrInvalidTimestamp | ||
} | ||
builder.WriteByte(b) | ||
} | ||
|
||
space, err := input.ReadByte() | ||
if err != nil || space != ' ' { | ||
return time.Time{}, ErrInvalidTimestamp | ||
} | ||
|
||
timestamp, err := time.Parse(time.Stamp, builder.String()) | ||
if err != nil { | ||
return time.Time{}, ErrInvalidTimestamp | ||
} | ||
return timestamp, nil | ||
} | ||
|
||
func parseHostname(input io.ByteScanner) (string, error) { | ||
builder := strings.Builder{} | ||
for { | ||
b, err := input.ReadByte() | ||
if err != nil { | ||
return "", ErrInvalidHostname | ||
} | ||
if b == ' ' { | ||
break | ||
} | ||
builder.WriteByte(b) | ||
} | ||
return builder.String(), nil | ||
} | ||
|
||
func parseMessage(input io.ByteScanner) (tag string, content string) { | ||
builder := strings.Builder{} | ||
tagFound := false | ||
for { | ||
b, err := input.ReadByte() | ||
if err != nil { | ||
break | ||
} | ||
if (b == '[' || b == ']' || b == ':') && !tagFound { | ||
tagFound = true | ||
tag = builder.String() | ||
builder.Reset() | ||
} | ||
builder.WriteByte(b) | ||
} | ||
content = builder.String() | ||
return | ||
} |
Oops, something went wrong.