diff --git a/config.go b/config.go index d014734..053b666 100644 --- a/config.go +++ b/config.go @@ -1,8 +1,9 @@ package main import ( - "gopkg.in/yaml.v2" "os" + + "gopkg.in/yaml.v2" ) type Config struct { @@ -10,10 +11,20 @@ type Config struct { StartCommand string `yaml:"start_command"` Port string `yaml:"port"` ConnectTimeout int `yaml:"connect_timeout"` //seconds + MCPort string `yaml:"mc_port"` +} + +var defaultConfig = Config{ + MCPort: "25565", + ConnectTimeout: 10, + Port: "4567", + Timeout: 1, } // this is a global constant since it's shared -var config Config +var config = Config{} + +const DEFAULT_VALUE_FMT_STR = "%s not found, default to %v" func LoadConfig(filePath string) error { data, err := os.ReadFile(filePath) @@ -26,5 +37,21 @@ func LoadConfig(filePath string) error { return err } GetLogger().Info("Configuration loaded successfully") + if config.MCPort == "" { + GetLogger().Warnf(DEFAULT_VALUE_FMT_STR, "MCPort", defaultConfig.MCPort) + config.MCPort = defaultConfig.MCPort + } + if config.ConnectTimeout == 0 { + GetLogger().Warnf(DEFAULT_VALUE_FMT_STR, "ConnectTimeout", defaultConfig.ConnectTimeout) + config.ConnectTimeout = defaultConfig.ConnectTimeout + } + if config.Port == "" { + GetLogger().Warnf(DEFAULT_VALUE_FMT_STR, "Port", defaultConfig.Port) + config.Port = defaultConfig.Port + } + if config.Timeout == 0 { + GetLogger().Warnf(DEFAULT_VALUE_FMT_STR, "Timeout", defaultConfig.Timeout) + config.Timeout = defaultConfig.Timeout + } return nil } diff --git a/conn.go b/conn.go index be716a3..471f237 100644 --- a/conn.go +++ b/conn.go @@ -40,7 +40,7 @@ func handleConn(clientOriginal net.Conn) { defer close(queryChan) QueryChanChan <- queryChan proceed := func() { - server, err := net.Dial("tcp", "127.0.0.1:25565") + server, err := net.Dial("tcp", "127.0.0.1:"+config.MCPort) if err != nil { GetLogger().Errorf("Failed to connect to MC server: %v", err) return @@ -66,21 +66,23 @@ func handleConn(clientOriginal net.Conn) { wg.Wait() GetLogger().Infof("Connection from %s closed", clientOriginal.RemoteAddr()) } - CntChan <- INCREASE - defer func() { CntChan <- DECREASE }() queryChan <- STOPPED st, _ := <-queryChan switch st { case RUNNING: + CntChan <- INCREASE + defer func() { CntChan <- DECREASE }() proceed() case STOPPED, WAITING: // client.Write([]byte("Server not ready!")) GetLogger().Infof("Connection queued, server currently at %s state", stateToStr[state]) + CntChan <- INCREASE + defer func() { CntChan <- DECREASE }() curChan := make(chan MCState) defer close(curChan) clientSignalChan.Add(curChan) - state, _ := <-curChan - if state == RUNNING { + st, _ := <-curChan + if st == RUNNING { proceed() } else { client.Write([]byte("You are too late, server dying!")) diff --git a/daemon.go b/daemon.go index fc695ab..ef56367 100644 --- a/daemon.go +++ b/daemon.go @@ -20,6 +20,7 @@ func Booting() { proc = exec.Command(arg[0], arg[1:]...) proc.Stdout = os.Stdout proc.Stderr = os.Stderr + proc.Stdin = os.Stdin proc.Start() DaemonChanRX <- struct{}{} GetLogger().Info("enter RUNNING state") diff --git a/ds.go b/ds.go index 53e3b99..3ff2a62 100644 --- a/ds.go +++ b/ds.go @@ -115,7 +115,7 @@ func NewDynamicMultiChan[T constraints.Ordered](reply bool, m int) *DynamicMulti modify: make(chan modify_t[T]), } mode := m - reload := make(chan struct{}) + reload := make([]chan struct{}, 0) used := make(map[int]bool) unused := make(map[int]bool) // delta := -1 @@ -129,8 +129,8 @@ func NewDynamicMultiChan[T constraints.Ordered](reply bool, m int) *DynamicMulti op := modification.op id := modification.id ch := modification.ch - for range viewCnt { - reload <- struct{}{} + for _, v := range reload { + v <- struct{}{} } switch op { case ADD: @@ -167,64 +167,67 @@ func NewDynamicMultiChan[T constraints.Ordered](reply bool, m int) *DynamicMulti } //deleted <- struct{}{} // <-reloadTX //extra communication } - for range viewCnt { - reload <- struct{}{} + for _, v := range reload { + v <- struct{}{} } } }() - go func() { + { + chanId := viewCnt viewCnt++ + reload = append(reload, make(chan struct{})) selectCases[0] = reflect.SelectCase{ Dir: reflect.SelectRecv, - Chan: reflect.ValueOf(reload), + Chan: reflect.ValueOf(reload[chanId]), } prevId := -1 - for { - id, recv, ok := reflect.Select(selectCases) - if prevId != -1 { - selectCases[prevId].Dir = reflect.SelectRecv - selectCases[prevId].Send = reflect.Value{} - prevId = -1 - } - if !ok { - // ret.used.Push(id) - // - // delete(used, id) - ret.modify <- modify_t[T]{DELETE, id - 1, nil} - <-reload - // reloadRX <- struct{}{} //I'm currently not dealing with other chan - <-reload //waiting for you finished - // reloadRX <- struct{}{} //I've read all deltas, you can release them - continue - } - if mode == 1 && id != 0 { - ret.RX <- To[T](recv) // possible for below to send to Chan? - if ret.reply { - msg, _ := <-ret.TX - selectCases[id].Dir = reflect.SelectSend - selectCases[id].Send = reflect.ValueOf(msg) - prevId = id - } - } else if id == 0 { - // reloadRX <- struct{}{} //I'm currently not dealing with other chan - <-reload //waiting for you finished - // reloadRX <- struct{}{} //I've read all deltas, you can release them - } - } - }() - if mode == 2 { go func() { - viewCnt++ - msgList := make([]T, 0) + for { + id, recv, ok := reflect.Select(selectCases) + if prevId != -1 { + selectCases[prevId].Dir = reflect.SelectRecv + selectCases[prevId].Send = reflect.Value{} + prevId = -1 + } + if !ok { + // ret.used.Push(id) + // + // delete(used, id) + ret.modify <- modify_t[T]{DELETE, id - 1, nil} + <-reload[chanId] + // reloadRX <- struct{}{} //I'm currently not dealing with other chan + <-reload[chanId] //waiting for you finished + // reloadRX <- struct{}{} //I've read all deltas, you can release them + continue + } + if mode == 1 && id != 0 { + ret.RX <- To[T](recv) // possible for below to send to Chan? + if ret.reply { + msg, _ := <-ret.TX + selectCases[id].Dir = reflect.SelectSend + selectCases[id].Send = reflect.ValueOf(msg) + prevId = id + } + } else if id == 0 { + // reloadRX <- struct{}{} //I'm currently not dealing with other chan + <-reload[chanId] //waiting for you finished + // reloadRX <- struct{}{} //I've read all deltas, you can release them + } + } + }() + } + if mode == 2 { + chanId := viewCnt + viewCnt++ + reload = append(reload, make(chan struct{})) + msgList := make([]T, 0) + go func() { for { select { - case <-reload: + case <-reload[chanId]: // reloadRX <- struct{}{} //I'm currently not dealing with other chan - <-reload //waiting for you finished - if addQue.Length() == 0 { - continue - } + <-reload[chanId] //waiting for you finished for !addQue.IsEmpty() { delta := addQue.Pop() for _, x := range msgList { diff --git a/fsm.go b/fsm.go index a70c3c1..1771cb5 100644 --- a/fsm.go +++ b/fsm.go @@ -12,6 +12,7 @@ const ( INCOMING globalConnEvent = iota EMPTY ) +const SERVER_STATE_INFO_FMTSTR = "Server is currently at %s state" // luckily I use int for them all var ( @@ -54,7 +55,7 @@ var waitChan chan struct{} // no we don't need cmdChan, we just make it work immediately func handleWaitingToRunning() { - GetLogger().Infof("Server is currently at %s state", stateToStr[RUNNING]) + GetLogger().Infof(SERVER_STATE_INFO_FMTSTR, stateToStr[RUNNING]) waitChan <- struct{}{} _, ok := <-waitChan if ok { @@ -62,7 +63,7 @@ func handleWaitingToRunning() { } //else it's too late } func handleRunningToWaiting() { - GetLogger().Infof("Server is currently at %s state", stateToStr[WAITING]) + GetLogger().Infof(SERVER_STATE_INFO_FMTSTR, stateToStr[WAITING]) waitChan = make(chan struct{}) go waitingThread() state = WAITING @@ -70,7 +71,7 @@ func handleRunningToWaiting() { // TODO: work with daemon func handleWaitingToStopping() { - GetLogger().Infof("Server is currently at %s state", stateToStr[STOPPING]) + GetLogger().Infof(SERVER_STATE_INFO_FMTSTR, stateToStr[STOPPING]) go stoppingThread() state = STOPPING } @@ -82,7 +83,7 @@ func stoppingThread() { handleStoppingToStopped() } func handleStoppingToStopped() { - GetLogger().Infof("Server is currently at %s state", stateToStr[STOPPED]) + GetLogger().Infof(SERVER_STATE_INFO_FMTSTR, stateToStr[STOPPED]) state = STOPPED } func bootingThread() { @@ -95,12 +96,12 @@ func bootingThread() { var runningChan chan struct{} func handleBootingToRunning() { - GetLogger().Infof("Server is currently at %s state", stateToStr[RUNNING]) + GetLogger().Infof(SERVER_STATE_INFO_FMTSTR, stateToStr[RUNNING]) state = RUNNING ConnSignalChan <- RUNNING } func handleStoppedToBooting() { - GetLogger().Infof("Server is currently at %s state", stateToStr[BOOTING]) + GetLogger().Infof(SERVER_STATE_INFO_FMTSTR, stateToStr[BOOTING]) state = BOOTING bootingThread() } diff --git a/logger.go b/logger.go index 9cc73ba..8729f6e 100644 --- a/logger.go +++ b/logger.go @@ -1,8 +1,9 @@ package main import ( - "github.com/sirupsen/logrus" "os" + + "github.com/sirupsen/logrus" ) var logger *logrus.Logger @@ -16,6 +17,7 @@ func InitLogger() { switch logLevel { case "debug": logger.SetLevel(logrus.DebugLevel) + logger.SetReportCaller(true) case "info": logger.SetLevel(logrus.InfoLevel) case "warn", "warning":