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
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)
|
|
}
|
|
}
|
|
|