You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

154 lines
3.2 KiB

package main
import (
"context"
"errors"
"log"
"net"
"sync"
"time"
"github.com/cacggghp/vk-turn-proxy/internal/dcmux"
)
func runTelemostDataChannelVLESSMode(ctx context.Context, inviteLink, listenAddr string) error {
return runDataChannelVLESSMode(ctx, "Telemost", connectTelemostDataChannelPeer, inviteLink, listenAddr)
}
func runJazzDataChannelVLESSMode(ctx context.Context, room, listenAddr string) error {
return runDataChannelVLESSMode(ctx, "SaluteJazz", connectJazzDataChannelPeer, room, listenAddr)
}
func runDataChannelVLESSMode(ctx context.Context, providerName string, connectPeer dataChannelConnectFunc, room, listenAddr string) error {
var (
connMu sync.Mutex
conns = make(map[uint16]net.Conn)
)
closeAll := func() {
connMu.Lock()
defer connMu.Unlock()
for sid, conn := range conns {
_ = conn.Close()
delete(conns, sid)
}
}
var peer dataChannelPeer
clientID := uint32(time.Now().UnixNano())
mux := dcmux.New(clientID, func(frame []byte) error {
return peer.Send(frame)
})
peer, err := connectPeer(ctx, room, mux.HandleFrame, func() {
log.Printf("%s DataChannel VLESS: peer reconnected, closing active TCP streams", providerName)
closeAll()
mux.Reset()
})
if err != nil {
return err
}
defer func(peer dataChannelPeer) {
err := peer.Close()
if err != nil {
log.Println(err)
}
}(peer)
listener, err := net.Listen("tcp", listenAddr)
if err != nil {
return err
}
defer func(listener net.Listener) {
err := listener.Close()
if err != nil {
log.Println(err)
}
}(listener)
closeOnContextDone(ctx, listener)
log.Printf("%s DataChannel VLESS mode: listening on %s", providerName, listenAddr)
for {
conn, err := listener.Accept()
if err != nil {
if ctx.Err() != nil || errors.Is(err, net.ErrClosed) {
closeAll()
return nil
}
log.Printf("%s DataChannel VLESS accept error: %v", providerName, err)
continue
}
sid := mux.OpenStream()
connMu.Lock()
conns[sid] = conn
connMu.Unlock()
go func(streamID uint16, tcpConn net.Conn) {
defer func() {
connMu.Lock()
delete(conns, streamID)
connMu.Unlock()
if err := mux.CloseStream(streamID); err != nil {
log.Printf("%s DataChannel VLESS: failed to close mux stream %d: %v", providerName, streamID, err)
}
_ = tcpConn.Close()
mux.CleanupStream(streamID)
}()
done := make(chan struct{})
streamClosed := make(chan struct{})
go func() {
defer close(done)
buf := make([]byte, 32768)
for {
n, readErr := tcpConn.Read(buf)
if readErr != nil {
return
}
if sendErr := mux.SendData(streamID, buf[:n]); sendErr != nil {
return
}
}
}()
go func() {
defer close(streamClosed)
for {
dataReady := mux.WaitForData(streamID)
select {
case <-ctx.Done():
return
case <-done:
return
case _, ok := <-dataReady:
if !ok {
return
}
}
for {
data := mux.ReadStream(streamID)
if len(data) == 0 {
break
}
if _, writeErr := tcpConn.Write(data); writeErr != nil {
return
}
}
if mux.StreamClosed(streamID) {
return
}
}
}()
select {
case <-ctx.Done():
case <-done:
case <-streamClosed:
}
}(sid, conn)
}
}