mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
SquashSRS4: Update srs-bench.
This commit is contained in:
parent
25145b945d
commit
b7b474deba
10 changed files with 590 additions and 516 deletions
199
trunk/3rdparty/srs-bench/vnet/udpproxy.go
vendored
199
trunk/3rdparty/srs-bench/vnet/udpproxy.go
vendored
|
@ -1,34 +1,13 @@
|
|||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2021 Winlin
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
package vnet
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pion/transport/vnet"
|
||||
)
|
||||
|
||||
// A UDP proxy between real server(net.UDPConn) and vnet.UDPConn.
|
||||
// UDPProxy is a proxy between real server(net.UDPConn) and vnet.UDPConn.
|
||||
//
|
||||
// High level design:
|
||||
// ..............................................
|
||||
|
@ -44,32 +23,9 @@ import (
|
|||
// : | | ............................:
|
||||
// : +--------+ :
|
||||
// ...............................................
|
||||
//
|
||||
// The whole big picture:
|
||||
// ......................................
|
||||
// : Virtual Network (vnet) :
|
||||
// : :
|
||||
// +-------+ * 1 +----+ +--------+ :
|
||||
// | :App |------------>|:Net|--o<-----|:Router | .............................
|
||||
// +-------+ +----+ | | : UDPProxy :
|
||||
// +-----------+ * 1 +----+ | | +----+ +---------+ +---------+ +--------+
|
||||
// |:STUNServer|-------->|:Net|--o<-----| |--->o--|:Net|-->o-| vnet. |-->o-| net. |--->-| :Real |
|
||||
// +-----------+ +----+ | | +----+ | UDPConn | | UDPConn | | Server |
|
||||
// +-----------+ * 1 +----+ | | : +---------+ +---------+ +--------+
|
||||
// |:TURNServer|-------->|:Net|--o<-----| | ............................:
|
||||
// +-----------+ +----+ [1] | | :
|
||||
// : 1 | | 1 <<has>> :
|
||||
// : +---<>| |<>----+ [2] :
|
||||
// : | +--------+ | :
|
||||
// To form | *| v 0..1 :
|
||||
// a subnet tree | o [3] +-----+ :
|
||||
// : | ^ |:NAT | :
|
||||
// : | | +-----+ :
|
||||
// : +-------+ :
|
||||
// ......................................
|
||||
type UDPProxy struct {
|
||||
// The router bind to.
|
||||
router *vnet.Router
|
||||
router *Router
|
||||
|
||||
// Each vnet source, bind to a real socket to server.
|
||||
// key is real server addr, which is net.Addr
|
||||
|
@ -88,19 +44,22 @@ type UDPProxy struct {
|
|||
// NewProxy create a proxy, the router for this proxy belongs/bind to. If need to proxy for
|
||||
// please create a new proxy for each router. For all addresses we proxy, we will create a
|
||||
// vnet.Net in this router and proxy all packets.
|
||||
func NewProxy(router *vnet.Router) (*UDPProxy, error) {
|
||||
func NewProxy(router *Router) (*UDPProxy, error) {
|
||||
v := &UDPProxy{router: router, timeout: 2 * time.Minute}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// Close the proxy, stop all workers.
|
||||
func (v *UDPProxy) Close() error {
|
||||
// nolint:godox // TODO: FIXME: Do cleanup.
|
||||
v.workers.Range(func(key, value interface{}) bool {
|
||||
_ = value.(*aUDPProxyWorker).Close()
|
||||
return true
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Proxy starts a worker for server, ignore if already started.
|
||||
func (v *UDPProxy) Proxy(client *vnet.Net, server *net.UDPAddr) error {
|
||||
func (v *UDPProxy) Proxy(client *Net, server *net.UDPAddr) error {
|
||||
// Note that even if the worker exists, it's also ok to create a same worker,
|
||||
// because the router will use the last one, and the real server will see a address
|
||||
// change event after we switch to the next worker.
|
||||
|
@ -113,25 +72,44 @@ func (v *UDPProxy) Proxy(client *vnet.Net, server *net.UDPAddr) error {
|
|||
worker := &aUDPProxyWorker{
|
||||
router: v.router, mockRealServerAddr: v.mockRealServerAddr,
|
||||
}
|
||||
|
||||
// Create context for cleanup.
|
||||
var ctx context.Context
|
||||
ctx, worker.ctxDisposeCancel = context.WithCancel(context.Background())
|
||||
|
||||
v.workers.Store(server.String(), worker)
|
||||
|
||||
return worker.Proxy(client, server)
|
||||
return worker.Proxy(ctx, client, server)
|
||||
}
|
||||
|
||||
// A proxy worker for a specified proxy server.
|
||||
type aUDPProxyWorker struct {
|
||||
router *vnet.Router
|
||||
router *Router
|
||||
mockRealServerAddr *net.UDPAddr
|
||||
|
||||
// Each vnet source, bind to a real socket to server.
|
||||
// key is vnet client addr, which is net.Addr
|
||||
// value is *net.UDPConn
|
||||
endpoints sync.Map
|
||||
|
||||
// For cleanup.
|
||||
ctxDisposeCancel context.CancelFunc
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
func (v *aUDPProxyWorker) Proxy(client *vnet.Net, serverAddr *net.UDPAddr) error { // nolint:gocognit
|
||||
func (v *aUDPProxyWorker) Close() error {
|
||||
// Notify all goroutines to dispose.
|
||||
v.ctxDisposeCancel()
|
||||
|
||||
// Wait for all goroutines quit.
|
||||
v.wg.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *aUDPProxyWorker) Proxy(ctx context.Context, client *Net, serverAddr *net.UDPAddr) error { // nolint:gocognit
|
||||
// Create vnet for real server by serverAddr.
|
||||
nw := vnet.NewNet(&vnet.NetConfig{
|
||||
nw := NewNet(&NetConfig{
|
||||
StaticIP: serverAddr.IP.String(),
|
||||
})
|
||||
if err := v.router.AddNet(nw); err != nil {
|
||||
|
@ -145,10 +123,71 @@ func (v *aUDPProxyWorker) Proxy(client *vnet.Net, serverAddr *net.UDPAddr) error
|
|||
return err
|
||||
}
|
||||
|
||||
// Start a proxy goroutine.
|
||||
var findEndpointBy func(addr net.Addr) (*net.UDPConn, error)
|
||||
// nolint:godox // TODO: FIXME: Do cleanup.
|
||||
// User stop proxy, we should close the socket.
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
_ = vnetSocket.Close()
|
||||
}()
|
||||
|
||||
// Got new vnet client, start a new endpoint.
|
||||
findEndpointBy := func(addr net.Addr) (*net.UDPConn, error) {
|
||||
// Exists binding.
|
||||
if value, ok := v.endpoints.Load(addr.String()); ok {
|
||||
// Exists endpoint, reuse it.
|
||||
return value.(*net.UDPConn), nil
|
||||
}
|
||||
|
||||
// The real server we proxy to, for utest to mock it.
|
||||
realAddr := serverAddr
|
||||
if v.mockRealServerAddr != nil {
|
||||
realAddr = v.mockRealServerAddr
|
||||
}
|
||||
|
||||
// Got new vnet client, create new endpoint.
|
||||
realSocket, err := net.DialUDP("udp4", nil, realAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// User stop proxy, we should close the socket.
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
_ = realSocket.Close()
|
||||
}()
|
||||
|
||||
// Bind address.
|
||||
v.endpoints.Store(addr.String(), realSocket)
|
||||
|
||||
// Got packet from real serverAddr, we should proxy it to vnet.
|
||||
v.wg.Add(1)
|
||||
go func(vnetClientAddr net.Addr) {
|
||||
defer v.wg.Done()
|
||||
|
||||
buf := make([]byte, 1500)
|
||||
for {
|
||||
n, _, err := realSocket.ReadFrom(buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if n <= 0 {
|
||||
continue // Drop packet
|
||||
}
|
||||
|
||||
if _, err := vnetSocket.WriteTo(buf[:n], vnetClientAddr); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}(addr)
|
||||
|
||||
return realSocket, nil
|
||||
}
|
||||
|
||||
// Start a proxy goroutine.
|
||||
v.wg.Add(1)
|
||||
go func() {
|
||||
defer v.wg.Done()
|
||||
|
||||
buf := make([]byte, 1500)
|
||||
|
||||
for {
|
||||
|
@ -172,51 +211,5 @@ func (v *aUDPProxyWorker) Proxy(client *vnet.Net, serverAddr *net.UDPAddr) error
|
|||
}
|
||||
}()
|
||||
|
||||
// Got new vnet client, start a new endpoint.
|
||||
findEndpointBy = func(addr net.Addr) (*net.UDPConn, error) {
|
||||
// Exists binding.
|
||||
if value, ok := v.endpoints.Load(addr.String()); ok {
|
||||
// Exists endpoint, reuse it.
|
||||
return value.(*net.UDPConn), nil
|
||||
}
|
||||
|
||||
// The real server we proxy to, for utest to mock it.
|
||||
realAddr := serverAddr
|
||||
if v.mockRealServerAddr != nil {
|
||||
realAddr = v.mockRealServerAddr
|
||||
}
|
||||
|
||||
// Got new vnet client, create new endpoint.
|
||||
realSocket, err := net.DialUDP("udp4", nil, realAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Bind address.
|
||||
v.endpoints.Store(addr.String(), realSocket)
|
||||
|
||||
// Got packet from real serverAddr, we should proxy it to vnet.
|
||||
// nolint:godox // TODO: FIXME: Do cleanup.
|
||||
go func(vnetClientAddr net.Addr) {
|
||||
buf := make([]byte, 1500)
|
||||
for {
|
||||
n, _, err := realSocket.ReadFrom(buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if n <= 0 {
|
||||
continue // Drop packet
|
||||
}
|
||||
|
||||
if _, err := vnetSocket.WriteTo(buf[:n], vnetClientAddr); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}(addr)
|
||||
|
||||
return realSocket, nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue