File: Decoder.go

package info (click to toggle)
golang-github-farsightsec-golang-framestream 0.3.0%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 116 kB
  • sloc: makefile: 4
file content (90 lines) | stat: -rw-r--r-- 2,880 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*
 * Copyright (c) 2014 by Farsight Security, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package framestream

import (
	"io"
	"time"
)

// DecoderOptions specifies configuration for a framestream Decoder.
type DecoderOptions struct {
	// MaxPayloadSize is the largest frame size accepted by the Decoder.
	//
	// If the Frame Streams Writer sends a frame in excess of this size,
	// Decode() will return the error ErrDataFrameTooLarge. The Decoder
	// attempts to recover from this error, so calls to Decode() after
	// receiving this error may succeed.
	MaxPayloadSize uint32
	// The ContentType expected by the Decoder. May be left unset for no
	// content negotiation. If the Writer requests a different content type,
	// NewDecoder() will return ErrContentTypeMismatch.
	ContentType []byte
	// If Bidirectional is true, the underlying io.Reader must be an
	// io.ReadWriter, and the Decoder will engage in a bidirectional
	// handshake with its peer to establish content type and communicate
	// shutdown.
	Bidirectional bool
	// Timeout gives the timeout for reading the initial handshake messages
	// from the peer and writing response messages if Bidirectional. It is
	// only effective for underlying Readers satisfying net.Conn.
	Timeout time.Duration
}

// A Decoder decodes Frame Streams frames read from an underlying io.Reader.
//
// It is provided for compatibility. Use Reader instead.
type Decoder struct {
	buf []byte
	r   *Reader
}

// NewDecoder returns a Decoder using the given io.Reader and options.
func NewDecoder(r io.Reader, opt *DecoderOptions) (*Decoder, error) {
	if opt == nil {
		opt = &DecoderOptions{}
	}
	if opt.MaxPayloadSize == 0 {
		opt.MaxPayloadSize = DEFAULT_MAX_PAYLOAD_SIZE
	}
	ropt := &ReaderOptions{
		Bidirectional: opt.Bidirectional,
		Timeout:       opt.Timeout,
	}
	if opt.ContentType != nil {
		ropt.ContentTypes = append(ropt.ContentTypes, opt.ContentType)
	}
	dr, err := NewReader(r, ropt)
	if err != nil {
		return nil, err
	}
	dec := &Decoder{
		buf: make([]byte, opt.MaxPayloadSize),
		r:   dr,
	}
	return dec, nil
}

// Decode returns the data from a Frame Streams data frame. The slice returned
// is valid until the next call to Decode.
func (dec *Decoder) Decode() (frameData []byte, err error) {
	n, err := dec.r.ReadFrame(dec.buf)
	if err != nil {
		return nil, err
	}
	return dec.buf[:n], nil
}