func ServerSocket() { addr, err := net.ResolveTCPAddr("tcp", config.Listen_addr) if err != nil { log.Fatalf("error parse address %s: %s", config.Listen_addr, err.Error()) } s, err := net.ListenTCP("tcp", addr) if err != nil { log.Fatalf("error listening on %s: %s", config.Listen_addr, err.Error()) } log.Infof("Server listened on %s", config.Listen_addr) for { conn, err := s.AcceptTCP() if err != nil { log.Warnf("listen_socket: error when accepting: %s", err.Error()) continue } go func(conn *WrapedSocket) { event := new(PostAcceptEvent) event.RemoteAddr = conn.RemoteAddr().(*net.TCPAddr) event.connID = conn.Id() PostAccept(event) if event.Rejected() { conn.Warnf("connection rejected.") conn.Close() return } log.Infof("connection accepted.") ClientSocket(conn, event) }(WrapClientSocket(conn)) } }
func ConfReload() { // Do not panic! defer func() { if r := recover(); r != nil { log.Errorf("paniced when reloading config %s, recovered.", config_file) log.Errorf("panic: %s", r) } }() log.Warn("Reloading config") content, err := ioutil.ReadFile(config_file) if err != nil { log.Errorf("unable to reload config %s: %s", config_file, err.Error()) return } prev_listen := config.Listen_addr config_lock.Lock() err = yaml.Unmarshal(content, &config) if err != nil { log.Errorf("error when parsing config file %s: %s", config_file, err.Error()) return } validateConfig() config_lock.Unlock() log.Info("config reloaded.") if config.Listen_addr != prev_listen { log.Warnf("config reload will not reopen server socket, thus no effect on listen address") } log.Infof("%d upstream server(s) found", len(config.Upstream)) }
func Run() { PreLoadConfig() confInit() PostLoadConfig() runtime.GOMAXPROCS(runtime.NumCPU()) log.Infof("MineGate %s started.", version_full) go ServerSocket() sig := make(chan os.Signal, 1) signal.Notify(sig, syscall.SIGHUP, syscall.SIGUSR1) for { cur := <-sig switch cur { case syscall.SIGHUP: log.Warn("SIGHUP caught, reloading config...") PreLoadConfig() ConfReload() PostLoadConfig() case syscall.SIGUSR1: log.Warn("SIGUSR1 caught, rotating log...") log.Rotate() default: log.Errorf("Trapped unexpected signal: %s", cur.String()) continue } } }
func PipeIt(reader *WrapedSocket, writer *WrapedSocket) { // TODO: Use configurable buffer size. raddr := reader.RemoteAddr().String() waddr := writer.RemoteAddr().String() log.Infof("%s ==PIPE==> %s", raddr, waddr) defer writer.Close() buffer := make([]byte, 4096) for { reader.SetTimeout(15 * time.Second) n, err := reader.Read(buffer) if err != nil { if err == io.EOF { reader.Warnf("EOF, closing connection.") } else { reader.Errorf("read error: %s", err.Error()) } reader.Close() if n > 0 { writer.SetWriteTimeout(15 * time.Second) writer.Write(buffer[:n]) } return } writer.SetWriteTimeout(15 * time.Second) n, err = writer.Write(buffer[:n]) if err != nil { writer.Errorf("write error: %s", err.Error()) return } // log.Debugf("%s == %d bytes => %s", raddr, n, waddr) } }
func (upstream *Upstream) Validate() (valid bool) { var host, port string host, port, err := net.SplitHostPort(upstream.Server) if err != nil { server := upstream.Server + ":25565" if host, port, err = net.SplitHostPort(server); err != nil { log.Error("Invalid upstream server: " + upstream.Server) return false } log.Infof("no port information found in %s, assume 25565", upstream.Server) upstream.Server = server } p, err := strconv.ParseUint(port, 10, 16) if err != nil { log.Errorf("Invalid port %s: %s", port, err.Error()) return false } host = strings.ToLower(host) if !CheckHost(host) { log.Error("Invalid upstream host: " + host) return false } upstream.Server = net.JoinHostPort(host, fmt.Sprintf("%d", p)) upstream.Pattern = strings.ToLower(upstream.Pattern) if !CheckPattern(upstream.Pattern) { log.Error("Invalid pattern: " + upstream.Pattern) return false } if upstream.ErrorMsg.Text == "" { log.Warnf("Empty error text for %s, use default string", upstream.Server) upstream.ErrorMsg.Text = "Connection failed to " + upstream.Server } upstream.ChatMsg = ToChatMsg(&upstream.ErrorMsg) return true }
func Run() { PreLoadConfig() confInit() PostLoadConfig() runtime.GOMAXPROCS(runtime.NumCPU()) log.Infof("MineGate %s started.", version_full) ServerSocket() }
func heartBeatTicker() { for { time.Sleep(time.Second * time.Duration(delta)) if limit == 0 { continue } ctlock.Lock() log.Infof("[conntrack] Reducing connection count...") for track := range conn_track { if conn_track[track] <= limit { delete(conn_track, track) log.Debugf("[conntrack] Removing IP %s.", track) } else { conn_track[track] -= limit } } log.Infof("[conntrack] Done. IPs currently in record: %d", len(conn_track)) ctlock.Unlock() } }
func loadConfig() { new_brust, err := minegate.GetExtraConf("conntrack.brust") if err != nil { log.Info("[conntrack] Using default brust: 5") brust = 5 } else { nb := minegate.ToUint(new_brust) log.Infof("[conntrack] Using brust: %d", nb) brust = nb } new_limit, err := minegate.GetExtraConf("conntrack.limit") if err != nil { log.Info("[conntrack] Using default limit: 5") limit = 5 } else { nl := minegate.ToUint(new_limit) if nl != 0 { log.Infof("[conntrack] Using limit: %d", nl) limit = nl } else { log.Info("[conntrack] Limit = 0, disabling conntrack.") limit = 0 } } new_delta, err := minegate.GetExtraConf("conntrack.interval") if err != nil { log.Info("[conntrack] Using default delta: 60") delta = 60 } else { nd := minegate.ToUint(new_delta) if nd < 15 { log.Warn("[conntrack] Minimal interval is 15.") nd = 15 } log.Infof("[conntrack] Using interval %d", nd) delta = nd } }
func GetUpstream(hostname string) (upstream *Upstream, err *mcchat.ChatMsg) { config_lock.Lock() defer config_lock.Unlock() log.Debugf("hostname=%s", hostname) for _, u := range config.Upstream { log.Debugf("pattern=%s", u.Pattern) if matched, _ := path.Match(u.Pattern, hostname); matched { log.Infof("matched server: %s", u.Server) return u, nil } } log.Warnf("no match for %s", hostname) return nil, config.chatNotFound }
func OnLoginRequest(handle LoginRequestFunc, priority int) (err error) { if priority < 0 || priority > 39 { log.Errorf("Invalid priority %d: not in range [0, 39]", priority) return fmt.Errorf("priority check failure: %d not in range [0, 39]", priority) } if handle == nil { log.Error("Attempt to register nil handler") return errors.New("Nil handler!") } if loginRequestHandlers[priority] == nil { loginRequestHandlers[priority] = make(loginRequestHandler, 0, 16) } loginRequestHandlers[priority] = append(loginRequestHandlers[priority], handle) log.Infof("Registered pingRequest handler at priority %d", priority) return nil }
func OnDisconnect(handle DisconnectFunc, priority int) (err error) { if priority < 0 || priority > 39 { log.Errorf("Invalid priority %d: not in range [0, 39]", priority) return fmt.Errorf("priority check failure: %d not in range [0, 39]", priority) } if handle == nil { log.Error("Attempt to register nil handler") return errors.New("Nil handler!") } if disconnectHandlers[priority] == nil { disconnectHandlers[priority] = make(disconnectHandler, 0, 16) } disconnectHandlers[priority] = append(disconnectHandlers[priority], handle) log.Infof("Registered disconnect handler at priority %d", priority) return nil }
func OnPreStatusResponse(handle PreStatusResponseFunc, priority int) (err error) { if priority < 0 || priority > 39 { log.Errorf("Invalid priority %d: not in range [0, 39]", priority) return fmt.Errorf("priority check failure: %d not in range [0, 39]", priority) } if handle == nil { log.Error("Attempt to register nil handler") return errors.New("Nil handler!") } if preStatusResponseHandlers[priority] == nil { preStatusResponseHandlers[priority] = make(preStatusResponseHandler, 0, 16) } preStatusResponseHandlers[priority] = append(preStatusResponseHandlers[priority], handle) log.Infof("Registered preStatusResponse handler at priority %d", priority) return nil }
func OnStartProxy(handle StartProxyFunc, priority int) (err error) { if priority < 0 || priority > 39 { log.Errorf("Invalid priority %d: not in range [0, 39]", priority) return fmt.Errorf("priority check failure: %d not in range [0, 39]", priority) } if handle == nil { log.Error("Attempt to register nil handler") return errors.New("Nil handler!") } if startProxyHandlers[priority] == nil { startProxyHandlers[priority] = make(startProxyHandler, 0, 16) } startProxyHandlers[priority] = append(startProxyHandlers[priority], handle) log.Infof("Registered startProxy handler at priority %d", priority) return nil }
func confInit() { content, err := ioutil.ReadFile(config_file) if err != nil { log.Fatalf("unable to load config %s: %s", config_file, err.Error()) } err = yaml.Unmarshal(content, &config) if err != nil { log.Fatalf("error when parsing config file %s: %s", config_file, err.Error()) } validateConfig() if config.Log.Target != "" && config.Log.Target != "-" { config.Log.Target, _ = filepath.Abs(config.Log.Target) log.Info("log path: " + config.Log.Target) } log.Stop() if config.Daemonize { Daemonize() } log.Start() if config.Log.Level != "" { level := log.ToLevel(config.Log.Level) if level == log.INVALID { log.Errorf("Invalid log level %s", config.Log.Level) } else { log.SetLogLevel(level) } } if config.Log.Target != "" && config.Log.Target != "-" { err := log.Open(config.Log.Target) if err != nil { log.Fatalf("Unable to open log %s: %s", config.Log.Target, err.Error()) } } log.Info("config loaded.") log.Info("server listen on: " + config.Listen_addr) log.Infof("%d upstream server(s) found", len(config.Upstream)) }
func (event *NetworkEvent) Infof(format string, v ...interface{}) { if event.log_prefix == "" { event.log_prefix = fmt.Sprintf("[#%d %s]", event.connID, event.RemoteAddr) } log.Infof(event.log_prefix+format, v...) }
func (ws *WrapedSocket) Infof(format string, v ...interface{}) { log.Infof(ws.log_prefix+format, v...) }
func SetConfig(conf string) { log.Infof("using config file %s", conf) config_file = conf }