mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-10-24 23:05:01 +03:00
d2a0216e01
The panel started answering requests before the share-link generator was registered, so an "all links", client sub-links or Telegram link request that arrived during start-up got "sub link provider not registered". NewServer now takes the provider and installs it before anything listens, and the provider registry is guarded by a lock, since start-up writes it while requests read it.
93 lines
2.9 KiB
Go
93 lines
2.9 KiB
Go
package web
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"crypto/x509"
|
|
"crypto/x509/pkix"
|
|
"encoding/pem"
|
|
"fmt"
|
|
"math/big"
|
|
"net"
|
|
"path/filepath"
|
|
"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(nil).Stop(); err != nil {
|
|
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)
|
|
}
|
|
}
|