Files
sing-box-extended/transport/openvpn/mux.go

93 lines
1.6 KiB
Go

package openvpn
import (
"context"
"net"
"sync"
)
type PacketMux struct {
io PacketIO
control chan []byte
data chan []byte
done chan struct{}
once sync.Once
}
func NewPacketMux(io PacketIO) *PacketMux {
return &PacketMux{
io: io,
control: make(chan []byte, 64),
data: make(chan []byte, 256),
done: make(chan struct{}),
}
}
func (m *PacketMux) Run(ctx context.Context) {
defer m.Close()
for ctx.Err() == nil {
packet, err := m.io.ReadPacket(ctx)
if err != nil {
return
}
if len(packet) == 0 {
continue
}
opcode, _ := parseOpcodeKeyID(packet[0])
ch := m.data
if opcode.IsControl() {
ch = m.control
}
select {
case ch <- packet:
case <-ctx.Done():
return
case <-m.done:
return
}
}
}
func (m *PacketMux) ReadPacket(ctx context.Context) ([]byte, error) {
select {
case packet := <-m.control:
return packet, nil
case <-ctx.Done():
return nil, ctx.Err()
case <-m.done:
return nil, net.ErrClosed
}
}
func (m *PacketMux) ReadDataPacket(ctx context.Context) ([]byte, error) {
select {
case packet := <-m.data:
return packet, nil
case <-ctx.Done():
return nil, ctx.Err()
case <-m.done:
return nil, net.ErrClosed
}
}
func (m *PacketMux) WritePacket(ctx context.Context, packet []byte) error {
return m.io.WritePacket(ctx, packet)
}
func (m *PacketMux) Close() error {
m.once.Do(func() {
close(m.done)
_ = m.io.Close()
})
return nil
}
func (m *PacketMux) LocalAddr() net.Addr {
return m.io.LocalAddr()
}
func (m *PacketMux) RemoteAddr() net.Addr {
return m.io.RemoteAddr()
}