| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- package web
- import (
- "crypto/ecdsa"
- "crypto/elliptic"
- "crypto/rand"
- "crypto/x509"
- "crypto/x509/pkix"
- "encoding/pem"
- "fmt"
- "math/big"
- "net"
- "path/filepath"
- "strings"
- "testing"
- "time"
- "github.com/mhsanaei/3x-ui/v3/internal/database"
- "github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
- "github.com/mhsanaei/3x-ui/v3/internal/database/model"
- "github.com/mhsanaei/3x-ui/v3/internal/tuic"
- "github.com/mhsanaei/3x-ui/v3/internal/web/job"
- "github.com/mhsanaei/3x-ui/v3/internal/xray"
- )
- func TestGracefulShutdownPersistsFinalTuicTraffic(t *testing.T) {
- dbDir := t.TempDir()
- t.Setenv("XUI_DB_FOLDER", dbDir)
- dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
- privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- if err != nil {
- t.Fatalf("generate certificate key: %v", err)
- }
- template := x509.Certificate{
- SerialNumber: big.NewInt(1),
- Subject: pkix.Name{CommonName: "localhost"},
- NotBefore: time.Now().Add(-time.Hour),
- NotAfter: time.Now().Add(time.Hour),
- IPAddresses: []net.IP{net.ParseIP("127.0.0.1")},
- }
- der, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey)
- if err != nil {
- t.Fatalf("create certificate: %v", err)
- }
- certificate := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: der})
- keyDER, err := x509.MarshalECPrivateKey(privateKey)
- if err != nil {
- t.Fatalf("marshal certificate key: %v", err)
- }
- privatePEM := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: keyDER})
- const (
- inboundID = 18002
- email = "shutdown-tuic@x"
- )
- inbound := &model.Inbound{
- Id: inboundID, Tag: "tuic-shutdown-traffic", Protocol: model.TUIC,
- Enable: true, Listen: "127.0.0.1", Port: 0,
- Settings: fmt.Sprintf(`{"certificate":%q,"private_key":%q,"clients":[{"uuid":"a0000000-0000-0000-0000-000000000022","password":"p","email":%q,"enable":true}]}`, certificate, privatePEM, email),
- }
- if err := database.GetDB().Create(inbound).Error; err != nil {
- t.Fatalf("create TUIC inbound: %v", err)
- }
- if err := database.GetDB().Create(&xray.ClientTraffic{InboundId: inboundID, Email: email, Enable: true}).Error; err != nil {
- t.Fatalf("create client traffic: %v", err)
- }
- manager := tuic.GetManager()
- manager.StopAll()
- manager.CollectAllTraffic()
- t.Cleanup(manager.StopAll)
- job.NewTuicJob().Run()
- if !manager.AddTestTraffic(inboundID, email, 100, 200) {
- t.Fatal("TUIC listener did not start")
- }
- if err := NewServer().Stop(); err != nil && !strings.Contains(err.Error(), "xray is not running") {
- t.Fatalf("graceful server shutdown: %v", err)
- }
- var got xray.ClientTraffic
- if err := database.GetDB().Where("email = ?", email).First(&got).Error; err != nil {
- t.Fatalf("load persisted client traffic: %v", err)
- }
- if got.Up != 100 || got.Down != 200 {
- t.Fatalf("shutdown persisted traffic (%d,%d), want (100,200)", got.Up, got.Down)
- }
- _, pending := manager.CollectAllTraffic()
- if len(pending) != 0 {
- t.Fatalf("final TUIC traffic remains only in manager memory: %+v", pending)
- }
- }
|