syn.go 2.34 KB
Newer Older
Jeromy's avatar
Jeromy committed
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package frame

import (
	"fmt"
	"io"
)

const (
	maxSynBodySize  = 8
	maxSynFrameSize = headerSize + maxSynBodySize
)

type RStreamSyn struct {
	Header
	body           [maxSynBodySize]byte
	streamPriority StreamPriority
	streamType     StreamType
}

// StreamType returns the stream's defined type as specified by
// the remote endpoint
func (f *RStreamSyn) StreamType() StreamType {
	return f.streamType
}

// StreamPriority returns the stream priority set on this frame
func (f *RStreamSyn) StreamPriority() StreamPriority {
	return f.streamPriority
}

func (f *RStreamSyn) parseFields() error {
	var length uint16 = 0
	flags := f.Flags()

	if flags.IsSet(flagStreamPriority) {
		f.streamPriority = StreamPriority(order.Uint32(f.body[length : length+4]))
		length += 4
	} else {
		f.streamPriority = 0
	}

	if flags.IsSet(flagStreamType) {
		f.streamType = StreamType(order.Uint32(f.body[length : length+4]))
		length += 4
	} else {
		f.streamType = 0
	}

	if length != f.Length() {
		return fmt.Errorf("Expected length %d for flags %v, but got %v", length, flags, f.Length())
	}

	return nil
}

func (f *RStreamSyn) readFrom(d deserializer) (err error) {
	if _, err = io.ReadFull(d, f.body[:f.Length()]); err != nil {
		return
	}

	if err = f.parseFields(); err != nil {
		return
	}

	return
}

type WStreamSyn struct {
	Header
	data   [maxSynFrameSize]byte
	length int
}

func (f *WStreamSyn) writeTo(s serializer) (err error) {
	_, err = s.Write(f.data[:headerSize+f.Length()])
	return
}

func (f *WStreamSyn) Set(streamId StreamId, streamPriority StreamPriority, streamType StreamType, fin bool) (err error) {
	var (
		flags  flagsType
		length int = 0
	)

	// set fin bit
	if fin {
		flags.Set(flagFin)
	}

	if streamPriority != 0 {
		if streamPriority > priorityMask {
			err = protoError("Priority %d is out of range", streamPriority)
			return
		}

		flags.Set(flagStreamPriority)
		start := headerSize + length
		order.PutUint32(f.data[start:start+4], uint32(streamPriority))
		length += 4
	}

	if streamType != 0 {
		flags.Set(flagStreamType)
		start := headerSize + length
		order.PutUint32(f.data[start:start+4], uint32(streamType))
		length += 4
	}

	// make the frame
	if err = f.Header.SetAll(TypeStreamSyn, length, streamId, flags); err != nil {
		return
	}
	return
}

func NewWStreamSyn() (f *WStreamSyn) {
	f = new(WStreamSyn)
	f.Header = Header(f.data[:headerSize])
	return
}