6
6
"errors"
7
7
"io"
8
8
"net"
9
+ "time"
9
10
)
10
11
11
12
type SessionStatus = byte
@@ -37,7 +38,6 @@ type Mux struct {
37
38
id [2 ]byte
38
39
length [2 ]byte
39
40
status [2 ]byte
40
- otb []byte
41
41
remain int
42
42
}
43
43
@@ -104,14 +104,8 @@ func (m *Mux) Read(b []byte) (int, error) {
104
104
}
105
105
106
106
func (m * Mux ) Write (b []byte ) (int , error ) {
107
- if m .otb != nil {
108
- // create a sub connection
109
- if _ , err := m .Conn .Write (m .otb ); err != nil {
110
- return 0 , err
111
- }
112
- m .otb = nil
113
- }
114
- m .buf .Reset ()
107
+ defer m .buf .Reset () // reset must after write (keep the data fill in NewMux can be sent)
108
+
115
109
binary .Write (& m .buf , binary .BigEndian , uint16 (4 ))
116
110
m .buf .Write (m .id [:])
117
111
m .buf .WriteByte (SessionStatusKeep )
@@ -123,15 +117,26 @@ func (m *Mux) Write(b []byte) (int, error) {
123
117
}
124
118
125
119
func (m * Mux ) Close () error {
126
- _ , err := m .Conn .Write ([]byte {0x0 , 0x4 , m .id [0 ], m .id [1 ], SessionStatusEnd , OptionNone })
127
- if err != nil {
128
- return err
120
+ errChan := make (chan error , 1 )
121
+ t := time .AfterFunc (time .Second , func () { // maybe conn write too slowly, force close underlay conn after one second
122
+ errChan <- m .Conn .Close ()
123
+ })
124
+ _ , _ = m .Conn .Write ([]byte {0x0 , 0x4 , m .id [0 ], m .id [1 ], SessionStatusEnd , OptionNone }) // ignore session end frame write error
125
+ if ! t .Stop () {
126
+ // Stop does not wait for f to complete before returning, so we used a chan to know whether f is completed
127
+ return <- errChan
129
128
}
130
129
return m .Conn .Close ()
131
130
}
132
131
133
132
func NewMux (conn net.Conn , option MuxOption ) * Mux {
134
- buf := & bytes.Buffer {}
133
+ mux := & Mux {
134
+ Conn : conn ,
135
+ id : option .ID ,
136
+ }
137
+
138
+ // create a sub connection (in buf)
139
+ buf := & mux .buf
135
140
136
141
// fill empty length
137
142
buf .Write ([]byte {0x0 , 0x0 })
@@ -165,9 +170,5 @@ func NewMux(conn net.Conn, option MuxOption) *Mux {
165
170
metadata := buf .Bytes ()
166
171
binary .BigEndian .PutUint16 (metadata [:2 ], uint16 (len (metadata )- 2 ))
167
172
168
- return & Mux {
169
- Conn : conn ,
170
- id : option .ID ,
171
- otb : metadata ,
172
- }
173
+ return mux
173
174
}
0 commit comments