func (s *Server) IsMinecraftServerResponding() bool { conn, err := net.DialTimeout("tcp", s.IPAddress+":25565", time.Second*5) if err != nil { return false } defer conn.Close() conn.SetDeadline(time.Now().Add(time.Second * 5)) stream := protocol.NewStream(conn) handshake := protocol.NewPacketWithID(0x00) handshake.WriteVarInt(5) handshake.WriteString(s.IPAddress) handshake.WriteUInt16(25565) handshake.WriteVarInt(1) if err := stream.WritePacket(handshake); err != nil { return false } request := protocol.NewPacketWithID(0x00) if err := stream.WritePacket(request); err != nil { return false } conn.SetDeadline(time.Now().Add(time.Second * 5)) _, length, err := stream.GetPacketStream() if err != nil { return false } if length > 5 { return true } return false }
// DisplayMessage responds with a disconnect message to the player // when they attempt to connect to the server. func DisplayMessage(s protocol.Stream, message string) error { responsePacket := protocol.NewPacketWithID(0x00) chatMessage := message data, err := json.Marshal(chatMessage) if err != nil { return err } responsePacket.WriteString(string(data)) err = s.WritePacket(responsePacket) return err }
// HandlePingPacket handles a ping packet used by the Minecraft client // used to measure the round trip time of the connection. func HandlePingPacket(s protocol.Stream, status Status) error { if !status.ShowConnection { s.ReadInt64() return nil } time, err := s.ReadInt64() if err != nil { return err } responsePacket := protocol.NewPacketWithID(0x01) responsePacket.WriteInt64(time) err = s.WritePacket(responsePacket) return err }
// WriteHandshakeResponse writes a response with a status that will be // displayed on the requesting player's server list menu. func WriteHandshakeResponse(s protocol.Stream, status Status) error { statusResponse := statusResponse{ Version: version{ Name: "1lann/beacon " + getReleaseName(status.ProtocolNumber), Protocol: status.ProtocolNumber, }, Players: players{ Max: status.MaxPlayers, Online: status.OnlinePlayers, }, Description: status.Message, } data, err := json.Marshal(statusResponse) if err != nil { return err } responsePacket := protocol.NewPacketWithID(0x00) responsePacket.WriteString(string(data)) err = s.WritePacket(responsePacket) return err }
func handlePacketID0(player *Player, ps protocol.PacketStream) error { if ps.GetRemainingBytes() == 0 { if player.State != 1 { return nil } status, found := statuses[player.Hostname] if !found { player.ShouldClose = true return nil } err := ping.WriteHandshakeResponse(ps.Stream, *status) if err != nil { return err } return nil } switch player.State { case 1: handshake, err := ping.ReadHandshakePacket(ps.Stream) if err != nil { log.Println("beacon: Handshake packet read error:", err) } player.Hostname = strings.ToLower(handshake.ServerAddress) if address, found := forwarders[player.Hostname]; found { // Write the handshake data initialPacket := protocol.NewPacketWithID(0x00) initialPacket.WriteVarInt(handshake.ProtocolNumber) initialPacket.WriteString(handshake.ServerAddress) initialPacket.WriteUInt16(handshake.ServerPort) initialPacket.WriteVarInt(handshake.NextState) player.InitialPacket = initialPacket player.ForwardAddress = address player.State = handshake.NextState return nil } if handshake.NextState == 1 { player.State = 1 } else if handshake.NextState == 2 { player.State = 2 } case 2: username, err := ps.ReadString() if err != nil { return err } player.Username = username handler, found := handlers[player.Hostname] if !found { log.Println("beacon: Missing handler for hostname: " + player.Hostname) err := ping.DisplayMessage(ps.Stream, "Connection rejected. There is no server on this hostname.") if err != nil { return err } return nil } err = ping.DisplayMessage(ps.Stream, handler(player)) if err != nil { return err } } return nil }