github.com/metaworking/channeld@v0.7.3/pkg/channeld/settings.go (about)

     1  package channeld
     2  
     3  import (
     4  	"encoding/json"
     5  	"flag"
     6  	"fmt"
     7  	"os"
     8  	"strconv"
     9  	"strings"
    10  
    11  	"github.com/metaworking/channeld/pkg/channeldpb"
    12  	"github.com/metaworking/channeld/pkg/common"
    13  	"github.com/pkg/profile"
    14  )
    15  
    16  type GlobalSettingsType struct {
    17  	Development   bool
    18  	LogLevel      *NullableInt // zapcore.Level
    19  	LogFile       *NullableString
    20  	ProfileOption func(*profile.Profile)
    21  	ProfilePath   string
    22  
    23  	ServerNetwork         string
    24  	ServerAddress         string
    25  	ServerReadBufferSize  int
    26  	ServerWriteBufferSize int
    27  	ServerFSM             string
    28  	ServerBypassAuth      bool
    29  
    30  	ClientNetworkWaitMasterServer bool
    31  	ClientNetwork                 string
    32  	ClientAddress                 string
    33  	ClientReadBufferSize          int
    34  	ClientWriteBufferSize         int
    35  	ClientFSM                     string
    36  
    37  	CompressionType channeldpb.CompressionType
    38  
    39  	MaxConnectionIdBits uint8
    40  
    41  	ConnectionAuthTimeoutMs int64
    42  	MaxFailedAuthAttempts   int
    43  	MaxFsmDisallowed        int
    44  
    45  	SpatialControllerConfig NullableString
    46  	SpatialChannelIdStart   common.ChannelId
    47  	EntityChannelIdStart    common.ChannelId
    48  
    49  	ChannelSettings map[channeldpb.ChannelType]ChannelSettingsType
    50  
    51  	EnableRecordPacket bool
    52  
    53  	ReplaySessionPersistenceDir string
    54  }
    55  
    56  type ACLSettingsType struct {
    57  	Sub    ChannelAccessLevel
    58  	Unsub  ChannelAccessLevel
    59  	Remove ChannelAccessLevel
    60  }
    61  
    62  type ChannelSettingsType struct {
    63  	TickIntervalMs                 uint
    64  	DefaultFanOutIntervalMs        uint32
    65  	DefaultFanOutDelayMs           int32
    66  	RemoveChannelAfterOwnerRemoved bool
    67  	ACLSettings                    ACLSettingsType
    68  	// Optinal. The full name of the Protobuf message type for the channel data (including the package name)
    69  	DataMsgFullName string
    70  }
    71  
    72  var GlobalSettings = GlobalSettingsType{
    73  	LogLevel:              &NullableInt{},
    74  	LogFile:               &NullableString{},
    75  	ServerReadBufferSize:  0x0001ffff,
    76  	ServerWriteBufferSize: 256,
    77  	ServerFSM:             "config/server_authoratative_fsm.json",
    78  	ClientReadBufferSize:  0x0001ffff,
    79  	ClientWriteBufferSize: 512,
    80  	ClientFSM:             "config/client_non_authoratative_fsm.json",
    81  	CompressionType:       channeldpb.CompressionType_NO_COMPRESSION,
    82  	// Mirror uses int32 as the connId
    83  	MaxConnectionIdBits:     31,
    84  	ConnectionAuthTimeoutMs: 5000,
    85  	MaxFailedAuthAttempts:   5,
    86  	MaxFsmDisallowed:        10,
    87  	SpatialChannelIdStart:   0x00010000,
    88  	EntityChannelIdStart:    0x00080000,
    89  	ChannelSettings: map[channeldpb.ChannelType]ChannelSettingsType{
    90  		channeldpb.ChannelType_GLOBAL: {
    91  			TickIntervalMs:                 10,
    92  			DefaultFanOutIntervalMs:        20,
    93  			DefaultFanOutDelayMs:           0,
    94  			RemoveChannelAfterOwnerRemoved: false,
    95  		},
    96  	},
    97  }
    98  
    99  type NullableInt struct {
   100  	Value    int
   101  	HasValue bool
   102  }
   103  
   104  func (i NullableInt) String() string {
   105  	if i.HasValue {
   106  		return strconv.Itoa(i.Value)
   107  	} else {
   108  		return ""
   109  	}
   110  }
   111  
   112  func (i *NullableInt) Set(s string) error {
   113  	val, err := strconv.Atoi(s)
   114  	if err == nil {
   115  		i.Value = val
   116  		i.HasValue = true
   117  	}
   118  	return err
   119  }
   120  
   121  type NullableString struct {
   122  	Value    string
   123  	HasValue bool
   124  }
   125  
   126  func (ns NullableString) String() string {
   127  	return ns.Value
   128  }
   129  
   130  func (ns *NullableString) Set(s string) error {
   131  	ns.Value = s
   132  	ns.HasValue = true
   133  	return nil
   134  }
   135  
   136  func (s *GlobalSettingsType) ParseFlag() error {
   137  	flag.BoolVar(&s.Development, "dev", false, "run in development mode?")
   138  	flag.Var(s.LogLevel, "loglevel", "the log level, -1 = Debug, 0 = Info, 1= Warn, 2 = Error, 3 = Panic")
   139  	//flag.Var(stringPtrFlag{s.LogFile, fmt.Sprintf("logs/%s.log", time.Now().Format("20060102150405"))}, "logfile", "file path to store the log")
   140  	flag.Var(s.LogFile, "logfile", "file path to store the log")
   141  	flag.Func("profile", "available options: cpu, mem, goroutine", func(str string) error {
   142  		switch strings.ToLower(str) {
   143  		case "cpu":
   144  			s.ProfileOption = profile.CPUProfile
   145  		case "mem":
   146  			s.ProfileOption = profile.MemProfile
   147  		case "goroutine":
   148  			s.ProfileOption = profile.GoroutineProfile
   149  		default:
   150  			return fmt.Errorf("invalid profile type: %s", str)
   151  		}
   152  		return nil
   153  	})
   154  	flag.StringVar(&s.ProfilePath, "profilepath", "profiles", "the path to store the profile output files")
   155  
   156  	flag.StringVar(&s.ServerNetwork, "sn", "tcp", "the network type for the server connections")
   157  	flag.StringVar(&s.ServerAddress, "sa", ":11288", "the network address for the server connections")
   158  	flag.IntVar(&s.ServerReadBufferSize, "srb", s.ServerReadBufferSize, "the read buffer size for the server connections")
   159  	flag.IntVar(&s.ServerWriteBufferSize, "swb", s.ServerWriteBufferSize, "the write buffer size for the server connections")
   160  	flag.StringVar(&s.ServerFSM, "sfsm", s.ServerFSM, "the path to the server FSM config")
   161  	flag.BoolVar(&s.ServerBypassAuth, "sba", true, "should server bypasses the authentication?")
   162  
   163  	flag.BoolVar(&s.ClientNetworkWaitMasterServer, "cwm", true, "should the client network starts listening after the Global channel being possessed by the Master Server?")
   164  	flag.StringVar(&s.ClientNetwork, "cn", "tcp", "the network type for the client connections")
   165  	flag.StringVar(&s.ClientAddress, "ca", ":12108", "the network address for the client connections")
   166  	flag.IntVar(&s.ClientReadBufferSize, "crb", s.ClientReadBufferSize, "the read buffer size for the client connections")
   167  	flag.IntVar(&s.ClientWriteBufferSize, "cwb", s.ClientWriteBufferSize, "the write buffer size for the client connections")
   168  	flag.StringVar(&s.ClientFSM, "cfsm", s.ClientFSM, "the path to the client FSM config")
   169  
   170  	flag.BoolVar(&s.EnableRecordPacket, "erp", false, "enable record message packets send from clients")
   171  	flag.StringVar(&s.ReplaySessionPersistenceDir, "rspd", "", "the path to write packet recording")
   172  
   173  	// Use flag.Uint instead of flag.UintVar to avoid the default value being overwritten by the flag value
   174  	ct := flag.Uint("ct", 0, "the compression type, 0 = No, 1 = Snappy")
   175  	flag.Var(&s.SpatialControllerConfig, "scc", "the path to the spatial controller config file")
   176  	scs := flag.Uint("scs", uint(s.SpatialChannelIdStart), "start ChannelId of spatial channels. Default is 0x00010000.")
   177  	ecs := flag.Uint("ecs", uint(s.EntityChannelIdStart), "start ChannelId of entity channels. Default is 0x00080000.")
   178  	mcb := flag.Uint("mcb", uint(s.MaxConnectionIdBits), "max bits of ConnectionId (e.g. 16 means max ConnectionId = 1<<16 - 1). Up to 32.")
   179  	cat := flag.Uint("cat", uint(s.ConnectionAuthTimeoutMs), "the duration to allow a connection stay unauthenticated before closing it. Default is 5000. (0 = no limit)")
   180  	mfaa := flag.Int("mfaa", s.MaxFailedAuthAttempts, "the max number of failed authentication attempts before closing the connection. Default is 5. (0 = no limit)")
   181  	mfd := flag.Int("mfd", s.MaxFsmDisallowed, "the max number of disallowed FSM transitions before closing the connection. Default is 10. (0 = no limit)")
   182  
   183  	chs := flag.String("chs", "config/channel_settings_hifi.json", "the path to the channel settings file")
   184  
   185  	flag.Parse()
   186  
   187  	if ct != nil {
   188  		s.CompressionType = channeldpb.CompressionType(*ct)
   189  	}
   190  
   191  	if scs != nil {
   192  		s.SpatialChannelIdStart = common.ChannelId(*scs)
   193  	}
   194  
   195  	if ecs != nil {
   196  		s.EntityChannelIdStart = common.ChannelId(*ecs)
   197  	}
   198  
   199  	if mcb != nil {
   200  		s.MaxConnectionIdBits = uint8(*mcb)
   201  	}
   202  
   203  	if cat != nil {
   204  		s.ConnectionAuthTimeoutMs = int64(*cat)
   205  	}
   206  
   207  	if mfaa != nil {
   208  		s.MaxFailedAuthAttempts = int(*mfaa)
   209  	}
   210  
   211  	if mfd != nil {
   212  		s.MaxFsmDisallowed = int(*mfd)
   213  	}
   214  
   215  	chsData, err := os.ReadFile(*chs)
   216  	if err == nil {
   217  		if err := json.Unmarshal(chsData, &GlobalSettings.ChannelSettings); err != nil {
   218  			return fmt.Errorf("failed to unmarshall channel settings: %v", err)
   219  		}
   220  	} else {
   221  		return fmt.Errorf("failed to read channel settings: %v", err)
   222  	}
   223  
   224  	return nil
   225  }
   226  
   227  func (s GlobalSettingsType) GetChannelSettings(t channeldpb.ChannelType) ChannelSettingsType {
   228  	settings, exists := s.ChannelSettings[t]
   229  	if !exists {
   230  		settings = s.ChannelSettings[channeldpb.ChannelType_GLOBAL]
   231  	}
   232  	return settings
   233  }