glider/proxy/anytls/session/stream.go
2026-04-09 18:49:23 +08:00

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 }