package main import ( "io" "minimcd/protocol" "net" "sync" "time" ) type timeoutConn struct { conn net.Conn } func (c timeoutConn) Read(buf []byte) (int, error) { c.conn.SetDeadline(time.Now().Add(time.Duration(config.ConnectTimeout) * time.Second)) return c.conn.Read(buf) } func (c timeoutConn) Write(buf []byte) (int, error) { c.conn.SetDeadline(time.Now().Add(time.Duration(config.ConnectTimeout) * time.Second)) return c.conn.Write(buf) } type signalChan chan MCState var signalChanChan = make(chan signalChan) // 单条管道->多条管道派发器 goroutine only var clientSignalChan = NewDynamicMultiChan[MCState](false, 2) func bridge() { for { msg, _ := <-ConnSignalChan clientSignalChan.TX <- msg clientSignalChan = NewDynamicMultiChan[MCState](false, 2) } } const ENABLE_LOGIN_FILTER = true func handleConn(clientOriginal net.Conn) { client := timeoutConn{clientOriginal} defer clientOriginal.Close() const DENIED_FMT_STR = "%s refused, it's not login connection" check := func() protocol.Packet { l := protocol.StreamedFromVarNoException[int](clientOriginal) if l == 0 { return nil } pid := protocol.StreamedFromVarNoException[int](clientOriginal) if pid != 0x0 { return nil } ver, addr, port, nxtst := protocol.StreamedFromHandshakePacketDataNoException(clientOriginal) if nxtst != 2 { return nil } return protocol.ToHandshakePacket(ver, addr, port, nxtst) } var firstPacket protocol.Packet if ENABLE_LOGIN_FILTER { if firstPacket = check(); firstPacket == nil { GetLogger().Infof(DENIED_FMT_STR, clientOriginal.RemoteAddr()) return } } queryChan := make(QueryChan) defer close(queryChan) QueryChanChan <- queryChan queryChan <- STOPPED st, _ := <-queryChan proceed := func() { 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 } defer server.Close() if ENABLE_LOGIN_FILTER { server.Write(firstPacket) } var wg sync.WaitGroup wg.Add(2) go func() { defer wg.Done() if _, err := io.Copy(server, client); err != nil { GetLogger().Errorf("Error forwarding client to server: %v", err) } }() // 从服务器到客户端 go func() { defer wg.Done() if _, err := io.Copy(client, server); err != nil { GetLogger().Errorf("Error forwarding server to client: %v", err) } }() wg.Wait() GetLogger().Infof("Connection from %s closed", clientOriginal.RemoteAddr()) } 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) st, _ := <-curChan if st == RUNNING { proceed() } else { client.Write([]byte("You are too late, server dying!")) GetLogger().Warnf("Connection refused, server currently at %s state", stateToStr[state]) } default: client.Write([]byte("Server not ready!")) GetLogger().Warnf("Connection refused, server currently at %s state", stateToStr[state]) } } func Listen() { go bridge() listener, _ := net.Listen("tcp", "0.0.0.0:"+config.Port) defer listener.Close() GetLogger().Infof("Listening on %s", config.Port) for { conn, err := listener.Accept() if err != nil { GetLogger().Errorf("ection error: %v", err) continue } //conn.SetReadDeadline(time.Now().Add(time.Duration(config.ConnectTimeout) * time.Second)) GetLogger().Infof("New connection from %s", conn.RemoteAddr()) conn.SetDeadline(time.Now().Add(time.Duration(config.ConnectTimeout) * time.Second)) go handleConn(conn) } }