mirror of
https://github.com/nadoo/glider.git
synced 2026-04-24 21:20:12 +08:00
89 lines
1.6 KiB
Go
89 lines
1.6 KiB
Go
package session
|
|
|
|
import (
|
|
"io"
|
|
"net"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// Stream implements net.Conn over a multiplexed session.
|
|
type Stream struct {
|
|
id uint32
|
|
sess *Session
|
|
|
|
pr *io.PipeReader
|
|
pw *io.PipeWriter
|
|
|
|
dieOnce sync.Once
|
|
dieErr error
|
|
CloseFunc func() error // overridable close hook
|
|
}
|
|
|
|
func newStream(id uint32, sess *Session) *Stream {
|
|
pr, pw := io.Pipe()
|
|
return &Stream{
|
|
id: id,
|
|
sess: sess,
|
|
pr: pr,
|
|
pw: pw,
|
|
}
|
|
}
|
|
|
|
func (s *Stream) Read(b []byte) (int, error) {
|
|
return s.pr.Read(b)
|
|
}
|
|
|
|
func (s *Stream) Write(b []byte) (int, error) {
|
|
if s.dieErr != nil {
|
|
return 0, s.dieErr
|
|
}
|
|
return s.sess.writeDataFrame(s.id, b)
|
|
}
|
|
|
|
func (s *Stream) Close() error {
|
|
if s.CloseFunc != nil {
|
|
return s.CloseFunc()
|
|
}
|
|
return s.CloseRemote()
|
|
}
|
|
|
|
func (s *Stream) CloseRemote() error {
|
|
var once bool
|
|
s.dieOnce.Do(func() {
|
|
s.dieErr = io.ErrClosedPipe
|
|
s.pr.Close()
|
|
once = true
|
|
})
|
|
if once {
|
|
return s.sess.streamClosed(s.id)
|
|
}
|
|
return s.dieErr
|
|
}
|
|
|
|
// closeLocally closes the stream without notifying the remote peer.
|
|
func (s *Stream) closeLocally() {
|
|
s.dieOnce.Do(func() {
|
|
s.dieErr = net.ErrClosed
|
|
s.pr.Close()
|
|
})
|
|
}
|
|
|
|
func (s *Stream) LocalAddr() net.Addr {
|
|
if ts, ok := s.sess.conn.(interface{ LocalAddr() net.Addr }); ok {
|
|
return ts.LocalAddr()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Stream) RemoteAddr() net.Addr {
|
|
if ts, ok := s.sess.conn.(interface{ RemoteAddr() net.Addr }); ok {
|
|
return ts.RemoteAddr()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Stream) SetDeadline(t time.Time) error { return nil }
|
|
func (s *Stream) SetReadDeadline(t time.Time) error { return nil }
|
|
func (s *Stream) SetWriteDeadline(t time.Time) error { return nil }
|