mirror of
https://github.com/coredns/coredns.git
synced 2025-10-28 08:44:17 -04:00
93 lines
1.8 KiB
Go
93 lines
1.8 KiB
Go
|
|
package dnstapio
|
||
|
|
|
||
|
|
import (
|
||
|
|
"encoding/binary"
|
||
|
|
"fmt"
|
||
|
|
"io"
|
||
|
|
|
||
|
|
tap "github.com/dnstap/golang-dnstap"
|
||
|
|
fs "github.com/farsightsec/golang-framestream"
|
||
|
|
"github.com/golang/protobuf/proto"
|
||
|
|
)
|
||
|
|
|
||
|
|
const (
|
||
|
|
frameLenSize = 4
|
||
|
|
protobufSize = 1024 * 1024
|
||
|
|
)
|
||
|
|
|
||
|
|
type dnstapEncoder struct {
|
||
|
|
fse *fs.Encoder
|
||
|
|
opts *fs.EncoderOptions
|
||
|
|
writer io.Writer
|
||
|
|
buffer *proto.Buffer
|
||
|
|
}
|
||
|
|
|
||
|
|
func newDnstapEncoder(o *fs.EncoderOptions) *dnstapEncoder {
|
||
|
|
return &dnstapEncoder{
|
||
|
|
opts: o,
|
||
|
|
buffer: proto.NewBuffer(make([]byte, 0, protobufSize)),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (enc *dnstapEncoder) resetWriter(w io.Writer) error {
|
||
|
|
fse, err := fs.NewEncoder(w, enc.opts)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if err = fse.Flush(); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
enc.fse = fse
|
||
|
|
enc.writer = w
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (enc *dnstapEncoder) writeMsg(msg *tap.Dnstap) error {
|
||
|
|
if len(enc.buffer.Bytes()) >= protobufSize {
|
||
|
|
if err := enc.flushBuffer(); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
}
|
||
|
|
bufLen := len(enc.buffer.Bytes())
|
||
|
|
// add placeholder for frame length
|
||
|
|
if err := enc.buffer.EncodeFixed32(0); err != nil {
|
||
|
|
enc.buffer.SetBuf(enc.buffer.Bytes()[:bufLen])
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if err := enc.buffer.Marshal(msg); err != nil {
|
||
|
|
enc.buffer.SetBuf(enc.buffer.Bytes()[:bufLen])
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
enc.encodeFrameLen(enc.buffer.Bytes()[bufLen:])
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (enc *dnstapEncoder) flushBuffer() error {
|
||
|
|
if enc.fse == nil || enc.writer == nil {
|
||
|
|
return fmt.Errorf("no writer")
|
||
|
|
}
|
||
|
|
|
||
|
|
buf := enc.buffer.Bytes()
|
||
|
|
written := 0
|
||
|
|
for written < len(buf) {
|
||
|
|
n, err := enc.writer.Write(buf[written:])
|
||
|
|
written += n
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
}
|
||
|
|
enc.buffer.Reset()
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (enc *dnstapEncoder) encodeFrameLen(buf []byte) {
|
||
|
|
binary.BigEndian.PutUint32(buf, uint32(len(buf)-4))
|
||
|
|
}
|
||
|
|
|
||
|
|
func (enc *dnstapEncoder) close() error {
|
||
|
|
if enc.fse != nil {
|
||
|
|
return enc.fse.Close()
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|