66 "errors"
77 "io"
88 "net"
9+ "time"
910)
1011
1112type SessionStatus = byte
@@ -37,7 +38,6 @@ type Mux struct {
3738 id [2 ]byte
3839 length [2 ]byte
3940 status [2 ]byte
40- otb []byte
4141 remain int
4242}
4343
@@ -104,14 +104,8 @@ func (m *Mux) Read(b []byte) (int, error) {
104104}
105105
106106func (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+
115109 binary .Write (& m .buf , binary .BigEndian , uint16 (4 ))
116110 m .buf .Write (m .id [:])
117111 m .buf .WriteByte (SessionStatusKeep )
@@ -123,15 +117,26 @@ func (m *Mux) Write(b []byte) (int, error) {
123117}
124118
125119func (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
129128 }
130129 return m .Conn .Close ()
131130}
132131
133132func 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
135140
136141 // fill empty length
137142 buf .Write ([]byte {0x0 , 0x0 })
@@ -165,9 +170,5 @@ func NewMux(conn net.Conn, option MuxOption) *Mux {
165170 metadata := buf .Bytes ()
166171 binary .BigEndian .PutUint16 (metadata [:2 ], uint16 (len (metadata )- 2 ))
167172
168- return & Mux {
169- Conn : conn ,
170- id : option .ID ,
171- otb : metadata ,
172- }
173+ return mux
173174}
0 commit comments