package loadsim import ( "errors" "flag" "fmt" "strings" "time" ) type Protocol string const ( ProtocolGB32960 Protocol = "gb32960" ProtocolJT808 Protocol = "jt808" ProtocolYutongMQTT Protocol = "yutong-mqtt" DefaultJT808PhoneBase int64 = 139000000000 maxJT808Phone int64 = 999999999999 ) type Config struct { Protocol Protocol Addr string Connections int ConnectRatePerSecond int SendInterval time.Duration Duration time.Duration Template string SendFrames bool JT808PhoneBase int64 DrainResponses bool } type FlagConfig struct { protocol string addr string connections int connectRate int sendInterval time.Duration duration time.Duration template string sendFrames bool jt808PhoneBase int64 drainResponses bool } func RegisterFlags(fs *flag.FlagSet) *FlagConfig { cfg := &FlagConfig{} fs.StringVar(&cfg.protocol, "protocol", string(ProtocolJT808), "protocol: jt808, gb32960, yutong-mqtt") fs.StringVar(&cfg.addr, "addr", "", "target host:port") fs.IntVar(&cfg.connections, "connections", 1, "target concurrent connections") fs.IntVar(&cfg.connectRate, "connect-rate", 100, "new connections per second") fs.DurationVar(&cfg.sendInterval, "send-interval", 10*time.Second, "frame send interval per connection") fs.DurationVar(&cfg.duration, "duration", 10*time.Minute, "load test duration") fs.StringVar(&cfg.template, "template", "", "frame template name") fs.BoolVar(&cfg.sendFrames, "send", true, "send protocol frames while connections are open") fs.Int64Var(&cfg.jt808PhoneBase, "jt808-phone-base", DefaultJT808PhoneBase, "first synthetic JT808 phone; one consecutive phone is assigned per connection") fs.BoolVar(&cfg.drainResponses, "drain-responses", true, "continuously read protocol responses while frames are being sent") return cfg } func (c *FlagConfig) Build() (Config, error) { protocol := Protocol(strings.ToLower(strings.TrimSpace(c.protocol))) switch protocol { case ProtocolGB32960, ProtocolJT808, ProtocolYutongMQTT: default: return Config{}, fmt.Errorf("unsupported protocol %q", c.protocol) } if strings.TrimSpace(c.addr) == "" { return Config{}, errors.New("addr is required") } if c.connections <= 0 { return Config{}, errors.New("connections must be positive") } if c.connectRate <= 0 { return Config{}, errors.New("connect-rate must be positive") } if c.sendInterval <= 0 { return Config{}, errors.New("send-interval must be positive") } if c.duration <= 0 { return Config{}, errors.New("duration must be positive") } if protocol == ProtocolJT808 { if c.jt808PhoneBase <= 0 || c.jt808PhoneBase > maxJT808Phone { return Config{}, errors.New("jt808-phone-base must be a positive 12-digit-or-shorter number") } if int64(c.connections-1) > maxJT808Phone-c.jt808PhoneBase { return Config{}, errors.New("jt808 synthetic phone range exceeds 12 digits") } } return Config{ Protocol: protocol, Addr: strings.TrimSpace(c.addr), Connections: c.connections, ConnectRatePerSecond: c.connectRate, SendInterval: c.sendInterval, Duration: c.duration, Template: strings.TrimSpace(c.template), SendFrames: c.sendFrames, JT808PhoneBase: c.jt808PhoneBase, DrainResponses: c.drainResponses, }, nil }