mirror of
				https://github.com/ossrs/srs.git
				synced 2025-03-09 15:49:59 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			184 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			184 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// 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"
 | 
						|
	"fmt"
 | 
						|
	"github.com/pion/logging"
 | 
						|
	"github.com/pion/transport/vnet"
 | 
						|
	"net"
 | 
						|
	"sync"
 | 
						|
	"testing"
 | 
						|
	"time"
 | 
						|
)
 | 
						|
 | 
						|
// vnet client:
 | 
						|
//		10.0.0.11:5787
 | 
						|
// proxy to real server:
 | 
						|
//		192.168.1.10:8000
 | 
						|
func TestUDPProxyDirectDeliver(t *testing.T) {
 | 
						|
	ctx, cancel := context.WithCancel(context.Background())
 | 
						|
 | 
						|
	var r0, r1, r2 error
 | 
						|
	defer func() {
 | 
						|
		if r0 != nil || r1 != nil || r2 != nil {
 | 
						|
			t.Errorf("fail for ctx=%v, r0=%v, r1=%v, r2=%v", ctx.Err(), r0, r1, r2)
 | 
						|
		}
 | 
						|
	}()
 | 
						|
 | 
						|
	var wg sync.WaitGroup
 | 
						|
	defer wg.Wait()
 | 
						|
 | 
						|
	// Timeout, fail
 | 
						|
	wg.Add(1)
 | 
						|
	go func() {
 | 
						|
		defer wg.Done()
 | 
						|
		defer cancel()
 | 
						|
 | 
						|
		select {
 | 
						|
		case <-ctx.Done():
 | 
						|
		case <-time.After(time.Duration(*testTimeout) * time.Millisecond):
 | 
						|
			r2 = fmt.Errorf("timeout")
 | 
						|
		}
 | 
						|
	}()
 | 
						|
 | 
						|
	// For utest, we always proxy vnet packets to the random port we listen to.
 | 
						|
	mockServer := NewMockUDPEchoServer()
 | 
						|
	wg.Add(1)
 | 
						|
	go func() {
 | 
						|
		defer wg.Done()
 | 
						|
		defer cancel()
 | 
						|
		if err := mockServer.doMockUDPServer(ctx); err != nil {
 | 
						|
			r0 = err
 | 
						|
		}
 | 
						|
	}()
 | 
						|
 | 
						|
	// Create a vent and proxy.
 | 
						|
	wg.Add(1)
 | 
						|
	go func() {
 | 
						|
		defer wg.Done()
 | 
						|
		defer cancel()
 | 
						|
 | 
						|
		// When real server is ready, start the vnet test.
 | 
						|
		select {
 | 
						|
		case <-ctx.Done():
 | 
						|
			return
 | 
						|
		case <-mockServer.realServerReady.Done():
 | 
						|
		}
 | 
						|
 | 
						|
		doVnetProxy := func() error {
 | 
						|
			router, err := vnet.NewRouter(&vnet.RouterConfig{
 | 
						|
				CIDR:          "0.0.0.0/0",
 | 
						|
				LoggerFactory: logging.NewDefaultLoggerFactory(),
 | 
						|
			})
 | 
						|
			if err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
 | 
						|
			clientNetwork := vnet.NewNet(&vnet.NetConfig{
 | 
						|
				StaticIP: "10.0.0.11",
 | 
						|
			})
 | 
						|
			if err = router.AddNet(clientNetwork); err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
 | 
						|
			if err := router.Start(); err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
			defer router.Stop()
 | 
						|
 | 
						|
			proxy, err := NewProxy(router)
 | 
						|
			if err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
			defer proxy.Close()
 | 
						|
 | 
						|
			// For utest, mock the target real server.
 | 
						|
			proxy.mockRealServerAddr = mockServer.realServerAddr
 | 
						|
 | 
						|
			// The real server address to proxy to.
 | 
						|
			// Note that for utest, we will proxy to a local address.
 | 
						|
			serverAddr, err := net.ResolveUDPAddr("udp4", "192.168.1.10:8000")
 | 
						|
			if err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
 | 
						|
			if err := proxy.Proxy(clientNetwork, serverAddr); err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
 | 
						|
			// Now, all packets from client, will be proxy to real server, vice versa.
 | 
						|
			client, err := clientNetwork.ListenPacket("udp4", "10.0.0.11:5787")
 | 
						|
			if err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
 | 
						|
			// When system quit, interrupt client.
 | 
						|
			selfKill, selfKillCancel := context.WithCancel(context.Background())
 | 
						|
			go func() {
 | 
						|
				<-ctx.Done()
 | 
						|
				selfKillCancel()
 | 
						|
				client.Close()
 | 
						|
			}()
 | 
						|
 | 
						|
			// Write by vnet client.
 | 
						|
			if _, err := client.WriteTo([]byte("Hello"), serverAddr); err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
 | 
						|
			buf := make([]byte, 1500)
 | 
						|
			if n, addr, err := client.ReadFrom(buf); err != nil {
 | 
						|
				if selfKill.Err() == context.Canceled {
 | 
						|
					return nil
 | 
						|
				}
 | 
						|
				return err
 | 
						|
			} else if n != 5 || addr == nil {
 | 
						|
				return fmt.Errorf("n=%v, addr=%v", n, addr)
 | 
						|
			} else if string(buf[:n]) != "Hello" {
 | 
						|
				return fmt.Errorf("data %v", buf[:n])
 | 
						|
			}
 | 
						|
 | 
						|
			// Directly write, simulate the ARQ packet.
 | 
						|
			// We should got the echo packet also.
 | 
						|
			if _, err := proxy.Deliver(client.LocalAddr(), serverAddr, []byte("Hello")); err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
 | 
						|
			if n, addr, err := client.ReadFrom(buf); err != nil {
 | 
						|
				if selfKill.Err() == context.Canceled {
 | 
						|
					return nil
 | 
						|
				}
 | 
						|
				return err
 | 
						|
			} else if n != 5 || addr == nil {
 | 
						|
				return fmt.Errorf("n=%v, addr=%v", n, addr)
 | 
						|
			} else if string(buf[:n]) != "Hello" {
 | 
						|
				return fmt.Errorf("data %v", buf[:n])
 | 
						|
			}
 | 
						|
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		if err := doVnetProxy(); err != nil {
 | 
						|
			r1 = err
 | 
						|
		}
 | 
						|
	}()
 | 
						|
}
 |