-
Notifications
You must be signed in to change notification settings - Fork 0
/
stream.go
135 lines (113 loc) · 2.89 KB
/
stream.go
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package fquic
import (
"errors"
"net"
"time"
"github.com/lucas-clemente/quic-go"
)
// These errors are panicked by Stream methods that are called on
// incorrectly used unidirectional streams.
var (
ErrWriteOnly = errors.New("write-only stream")
ErrReadOnly = errors.New("read-only stream")
)
// A Stream is an open QUIC stream inside of a connection.
//
// A Stream can be bidirectional, read-only, or write-only. Calling
// read-related methods on a write-only stream and vice versa will
// result in a panic.
type Stream struct {
conn *Conn
s quic.SendStream
r quic.ReceiveStream
}
func newStream(conn *Conn, s quic.SendStream, r quic.ReceiveStream) *Stream {
return &Stream{
conn: conn,
s: s,
r: r,
}
}
// Conn returns the connection associated with the Stream.
func (s *Stream) Conn() *Conn {
return s.conn
}
// Stream returns the underlying bidirectional quic-go Stream. If the
// Stream is unidirectional in either direction, this returns nil.
func (s *Stream) Stream() quic.Stream {
qs, _ := s.s.(quic.Stream)
return qs
}
// ReceiveStream returns the underlying quic-go ReceiveStream, or nil
// if the stream is write-only.
func (s *Stream) ReceiveStream() quic.ReceiveStream {
return s.r
}
// SendStream returns the underlying quic-go SendStream, or nil if the
// stream is read-only.
func (s *Stream) SendStream() quic.SendStream {
return s.s
}
// CanRead returns true if the stream can be read from.
func (s *Stream) CanRead() bool {
return s.r != nil
}
// CanWrite returns true if the stream can be written to.
func (s *Stream) CanWrite() bool {
return s.s != nil
}
func (s *Stream) Read(buf []byte) (int, error) {
if s.r == nil {
panic(ErrWriteOnly)
}
return s.r.Read(buf)
}
func (s *Stream) Write(data []byte) (int, error) {
if s.s == nil {
panic(ErrReadOnly)
}
return s.s.Write(data)
}
// Close closes a writable stream. Unlike other direction-dependant
// methods methods, if this stream is read-only, this is a no-op.
func (s *Stream) Close() error {
if s.s == nil {
return nil
}
return s.s.Close()
}
func (s *Stream) LocalAddr() net.Addr {
return s.conn.LocalAddr()
}
func (s *Stream) RemoteAddr() net.Addr {
return s.conn.RemoteAddr()
}
// SetDeadline implements net.Conn's SetDeadline method. Note that
// this method only works on bidirectional streams.
//
// TODO: Make this use the available unidirectional method
// automatically if the stream is unidirectional?
func (s *Stream) SetDeadline(t time.Time) error {
if s.s == nil {
panic(ErrReadOnly)
}
if s.r == nil {
panic(ErrWriteOnly)
}
type deadliner interface {
SetDeadline(time.Time) error
}
return s.s.(deadliner).SetDeadline(t)
}
func (s *Stream) SetReadDeadline(t time.Time) error {
if s.r == nil {
panic(ErrWriteOnly)
}
return s.r.SetReadDeadline(t)
}
func (s *Stream) SetWriteDeadline(t time.Time) error {
if s.s == nil {
panic(ErrReadOnly)
}
return s.s.SetWriteDeadline(t)
}