func (this *ConnectImpl) HandlePacket(packet packet.Packet) (err error) { switch packet.Id() { case connect.PACKET_KEEPALIVE: err = this.Write(packet) case connect.PACKET_RESULT: packetResult := packet.(*connect.PacketResult) err = this.DispatchResult(packetResult.SequenceId, packetResult.StatusCode, packetResult.Result) case connect.PACKET_MESSAGE_EVENT: this.DispatchEvent("message", WrapEventMessage(packet.(*connect.PacketMessageEvent))) case connect.PACKET_REDIRECT_EVENT: this.DispatchEvent("redirect", WrapEventRedirect(packet.(*connect.PacketRedirectEvent))) case connect.PACKET_SERVER_EVENT: this.DispatchEvent("server", WrapEventServer(packet.(*connect.PacketServerEvent))) } return }
func (this *Session) HandlePacket(packet packet.Packet) (err error) { switch this.state { case STATE_DISCONNECTED: if packet.Id() == minecraft.PACKET_SERVER_HANDSHAKE { handshakePacket := packet.(*minecraft.PacketServerHandshake) this.protocolVersion = handshakePacket.ProtocolVersion this.serverAddress = handshakePacket.ServerAddress supportedVersion := false for _, version := range minecraft.Versions { if version != this.protocolVersion { continue } supportedVersion = true break } if handshakePacket.State == 1 { if !supportedVersion { this.protocolVersion = minecraft.Versions[0] } this.pipeline.Replace("registry", minecraft.StatusPacketServerCodec) this.state = STATE_STATUS } else if handshakePacket.State == 2 { if !supportedVersion { err = errors.New("Protocol version does not match") return } this.protocol17 = this.protocolVersion < minecraft.Versions[0] if this.protocol17 { this.pipeline.Replace("registry", minecraft.LoginPacketServerCodec17) } else { this.pipeline.Replace("registry", minecraft.LoginPacketServerCodec) } this.state = STATE_LOGIN } else { err = errors.New("Unexpected state") return } } else { err = errors.New("Unexpected packet") return } case STATE_STATUS: if packet.Id() == minecraft.PACKET_SERVER_STATUS_REQUEST { samplePath := this.server.router.RouteSample(this.serverAddress) sampleTxt, sampleErr := ioutil.ReadFile(samplePath) sample := make([]map[string]interface{}, 0) if sampleErr == nil { lines := strings.Split(string(sampleTxt), "\n") for _, line := range lines { line = strings.Replace(line, "\r", "", -1) if len(strings.TrimSpace(line)) == 0 { continue } entry := make(map[string]interface{}) entry["name"] = minecraft.Colorize(line) entry["id"] = "00000000-0000-0000-0000-000000000000" sample = append(sample, entry) } } icons := this.server.router.RouteIcons(this.serverAddress) iconPath := icons[RandomInt(len(icons))] icon, iconErr := ioutil.ReadFile(iconPath) var iconString string if iconErr == nil { iconString = "data:image/png;base64," + base64.StdEncoding.EncodeToString(icon) } version := make(map[string]interface{}) version["name"] = minecraft.STRING_VERSION version["protocol"] = this.protocolVersion players := make(map[string]interface{}) if this.server.SyncMaxPlayers() { players["max"] = this.server.connect.MaxPlayers() } else { players["max"] = this.server.MaxPlayers() } players["online"] = this.server.connect.Players() players["sample"] = sample description := make(map[string]interface{}) motds := this.server.router.RouteMotds(this.serverAddress) motd := motds[RandomInt(len(motds))] description["text"] = minecraft.Colorize(motd) response := make(map[string]interface{}) response["version"] = version response["players"] = players response["description"] = description if iconString != "" { response["favicon"] = iconString } var marshalled []byte marshalled, err = json.Marshal(response) if err != nil { return } err = this.Write(minecraft.NewPacketClientStatusResponse(string(marshalled))) if err != nil { return } this.state = STATE_STATUS_PING } else { err = errors.New("Unexpected packet") return } case STATE_STATUS_PING: if packet.Id() == minecraft.PACKET_SERVER_STATUS_PING { err = this.Write(minecraft.NewPacketClientStatusPing(packet.(*minecraft.PacketServerStatusPing).Time)) if err != nil { return } this.conn.Close() } else { err = errors.New("Unexpected packet") return } case STATE_LOGIN: if packet.Id() == minecraft.PACKET_SERVER_LOGIN_START { this.name = packet.(*minecraft.PacketServerLoginStart).Name if this.server.Authenticate() { this.serverId, err = GenSalt() if err != nil { return } this.publicKey, err = x509.MarshalPKIXPublicKey(&this.server.privateKey.PublicKey) if err != nil { return } this.verifyToken, err = RandomBytes(4) if err != nil { return } err = this.Write(minecraft.NewPacketClientLoginEncryptRequest(this.serverId, this.publicKey, this.verifyToken)) if err != nil { return } this.state = STATE_LOGIN_ENCRYPT } else { this.profile = auth.GameProfile{ Id: GenNameUUID("OfflinePlayer:" + this.name), Properties: make([]auth.GameProfileProperty, 0), } this.SetAuthenticated(true) } } else { err = errors.New("Unexpected packet") return } case STATE_LOGIN_ENCRYPT: if packet.Id() == minecraft.PACKET_SERVER_LOGIN_ENCRYPT_RESPONSE { loginEncryptResponsePacket := packet.(*minecraft.PacketServerLoginEncryptResponse) var sharedSecret []byte sharedSecret, err = rsa.DecryptPKCS1v15(rand.Reader, this.server.privateKey, loginEncryptResponsePacket.SharedSecret) if err != nil { return } var verifyToken []byte verifyToken, err = rsa.DecryptPKCS1v15(rand.Reader, this.server.privateKey, loginEncryptResponsePacket.VerifyToken) if err != nil { return } if bytes.Compare(this.verifyToken, verifyToken) != 0 { err = errors.New("Verify token does not match") return } err = this.SetEncryption(sharedSecret) if err != nil { return } var authErr error this.profile, authErr = auth.Authenticate(this.name, this.serverId, sharedSecret, this.publicKey) if authErr != nil { this.SetAuthenticated(false) fmt.Println("Proxy server, failed to authorize:", this.name, "ip:", this.remoteIp, "err:", authErr) } else { this.SetAuthenticated(true) fmt.Println("Proxy server, authorized:", this.name, "ip:", this.remoteIp) } } else { err = errors.New("Unexpected packet") return } case STATE_CONNECTED: if packet.Id() == minecraft.PACKET_SERVER_CLIENT_SETTINGS { this.clientSettings = packet } if packet.Id() == minecraft.PACKET_SERVER_PLUGIN_MESSAGE { pluginMessagePacket := packet.(*minecraft.PacketServerPluginMessage) if pluginMessagePacket.Channel == "REGISTER" { for _, channelBytes := range bytes.Split(pluginMessagePacket.Data[:], []byte{0}) { channel := string(channelBytes) if _, ok := this.pluginChannels[channel]; ok { continue } if len(this.pluginChannels) >= 128 { break } this.pluginChannels[channel] = struct{}{} } } else if pluginMessagePacket.Channel == "UNREGISTER" { for _, channelBytes := range bytes.Split(pluginMessagePacket.Data[:], []byte{0}) { channel := string(channelBytes) delete(this.pluginChannels, channel) } } } if this.redirecting { break } if genericPacket, ok := packet.(*minecraft.PacketGeneric); ok { genericPacket.SwapEntities(this.clientEntityId, this.serverEntityId, false, this.protocol17) } this.outBridge.Write(packet) } return }
func (this *Session) HandlePacket(packet packet.Packet) (err error) { switch packet.Id() { case connect.PACKET_KEEPALIVE: if this.keepalive == nil { this.Close() return } if *this.keepalive != packet.(*connect.PacketKeepalive).Random { this.Close() return } this.keepalive = nil case connect.PACKET_REQUEST: request := packet.(*connect.PacketRequest).Request var result connect.Result var statusCode uint8 switch request.Id() { case connect.REQUEST_AUTHENTICATE: if !this.Authorized() { username := request.(*connect.RequestAuthenticate).Username var ok bool ok, err = this.server.Authenticator().Authenticate(username, request.(*connect.RequestAuthenticate).Password, this.salt) if err != nil { return } if ok { this.RegisterAuthorized(username) fmt.Println("Connect server, authorized:", this.Id(), "ip:", this.RemoteIp()) result = &connect.ResultAuthenticate{} statusCode = connect.STATUS_SUCCESS } else { fmt.Println("Connect server, failure to authorize:", username, "ip:", this.RemoteIp()) statusCode = connect.STATUS_ERROR_GENERIC } } else { statusCode = connect.STATUS_ERROR_ROLE } case connect.REQUEST_AS_PROXY: if this.Authorized() { if this.RegisterProxy(request.(*connect.RequestAsProxy).Address, request.(*connect.RequestAsProxy).Port, request.(*connect.RequestAsProxy).Motd, request.(*connect.RequestAsProxy).Version, request.(*connect.RequestAsProxy).Maxplayers) { fmt.Println("Connect server, roled as proxy:", this.Id(), "ip:", this.RemoteIp()) result = &connect.ResultAsProxy{} statusCode = connect.STATUS_SUCCESS } else { statusCode = connect.STATUS_ERROR_GENERIC } } else { statusCode = connect.STATUS_ERROR_ROLE } case connect.REQUEST_AS_SERVER: if this.Authorized() { if this.RegisterServer(request.(*connect.RequestAsServer).Address, request.(*connect.RequestAsServer).Port) { fmt.Println("Connect server, roled as server:", this.Id(), "ip:", this.RemoteIp()) result = &connect.ResultAsServer{this.serverSecurityKey} statusCode = connect.STATUS_SUCCESS } else { statusCode = connect.STATUS_ERROR_GENERIC } } else { statusCode = connect.STATUS_ERROR_ROLE } case connect.REQUEST_GET_DETAILS: if this.Authorized() { networkCache := this.server.NetworkCache() result = &connect.ResultGetDetails{networkCache.Address(), networkCache.Port(), networkCache.Motd(), networkCache.Version()} statusCode = connect.STATUS_SUCCESS } else { statusCode = connect.STATUS_ERROR_ROLE } case connect.REQUEST_GET_PLAYERS: if this.Authorized() { networkCache := this.server.NetworkCache() players := networkCache.Players() if request.(*connect.RequestGetPlayers).List { result = &connect.ResultGetPlayers{true, uint16(len(players)), networkCache.MaxPlayers(), players} } else { result = &connect.ResultGetPlayers{false, uint16(len(players)), networkCache.MaxPlayers(), nil} } statusCode = connect.STATUS_SUCCESS } else { statusCode = connect.STATUS_ERROR_ROLE } case connect.REQUEST_GET_SALT: result = &connect.ResultGetSalt{this.salt} statusCode = connect.STATUS_SUCCESS case connect.REQUEST_GET_WHOAMI: result = &connect.ResultGetWhoami{this.Id()} statusCode = connect.STATUS_SUCCESS case connect.REQUEST_MESSAGE: if this.Authorized() { sessionRegistry := this.server.SessionRegistry(AUTHORIZED) recipients := request.(*connect.RequestMessage).Recipients messagePacket := &connect.PacketMessageEvent{this.Id(), request.(*connect.RequestMessage).Channel, request.(*connect.RequestMessage).Message} messageSent := false if len(recipients) == 0 { for _, recipient := range sessionRegistry.GetAll() { recipient.Write(messagePacket) messageSent = true } } else { for _, recipientId := range recipients { recipient := sessionRegistry.GetById(recipientId) if recipient == nil { continue } recipient.Write(messagePacket) messageSent = true } } if messageSent { result = &connect.ResultMessage{} statusCode = connect.STATUS_SUCCESS } else { statusCode = connect.STATUS_ERROR_GENERIC } } else { statusCode = connect.STATUS_ERROR_ROLE } case connect.REQUEST_NOTIFY_PLAYER: if this.Authorized() && this.role == ROLE_PROXY { add := request.(*connect.RequestNotifyPlayer).Add player := request.(*connect.RequestNotifyPlayer).Player if add { if !this.server.NetworkCache().AddPlayer(player, this) { statusCode = connect.STATUS_ERROR_GENERIC break } this.proxyPlayers[player] = true } else { if _, ok := this.proxyPlayers[player]; ok { this.server.NetworkCache().RemovePlayer(player) delete(this.proxyPlayers, player) } } result = &connect.ResultNotifyPlayer{} statusCode = connect.STATUS_SUCCESS } else { statusCode = connect.STATUS_ERROR_ROLE } case connect.REQUEST_REDIRECT: if this.Authorized() { server := request.(*connect.RequestRedirect).Server player := request.(*connect.RequestRedirect).Player session := this.server.NetworkCache().ProxyByPlayer(player) if session == nil { statusCode = connect.STATUS_ERROR_GENERIC break } session.Write(&connect.PacketRedirectEvent{server, player}) result = &connect.ResultRedirect{} statusCode = connect.STATUS_SUCCESS } else { statusCode = connect.STATUS_ERROR_ROLE } default: err = errors.New(fmt.Sprintf("Request Id is not handled by server: %d", request.Id())) return } err = this.Write(&connect.PacketResult{packet.(*connect.PacketRequest).SequenceId, statusCode, result}) default: err = errors.New(fmt.Sprintf("Packet Id is not handled by server: %d", packet.Id())) } return }
func (this *SessionOutBridge) HandlePacket(packet packet.Packet) (err error) { if !this.session.Authenticated() { this.conn.Close() return } switch this.state { case STATE_LOGIN: if packet.Id() == minecraft.PACKET_CLIENT_LOGIN_SUCCESS { this.session.redirectMutex.Lock() this.state = STATE_INIT this.session.redirecting = true this.EnsureCompression() if this.session.protocol17 { this.pipeline.Replace("registry", minecraft.PlayPacketClientCodec17) } else { this.pipeline.Replace("registry", minecraft.PlayPacketClientCodec) } } else if packet.Id() == minecraft.PACKET_CLIENT_LOGIN_DISCONNECT { this.session.DisconnectJson(packet.(*minecraft.PacketClientLoginDisconnect).Json) this.conn.Close() } else if packet.Id() == minecraft.PACKET_CLIENT_LOGIN_SET_COMPRESSION { this.SetCompression(packet.(*minecraft.PacketClientLoginSetCompression).Threshold) } else { if this.session.Initializing() { this.session.Disconnect("Error: Outbound Protocol Mismatch") } this.conn.Close() } case STATE_INIT: if packet.Id() == minecraft.PACKET_CLIENT_PLAYER_POSITION_AND_LOOK { this.session.outBridge = this this.session.redirecting = false this.session.state = STATE_CONNECTED this.state = STATE_CONNECTED this.session.redirectMutex.Unlock() } fallthrough case STATE_CONNECTED: if packet.Id() == minecraft.PACKET_CLIENT_DISCONNECT { this.state = STATE_DISCONNECTED } if this.state == STATE_CONNECTED { this.session.redirectMutex.Lock() if this.session.outBridge != this { this.session.outBridge.EnsureCompression() this.conn.Close() this.session.redirectMutex.Unlock() break } this.session.redirectMutex.Unlock() } switch packet.Id() { case minecraft.PACKET_CLIENT_JOIN_GAME: joinGamePacket := packet.(*minecraft.PacketClientJoinGame) if this.session.clientSettings != nil { this.Write(this.session.clientSettings) } this.session.serverEntityId = joinGamePacket.EntityId if this.session.state == STATE_INIT { this.session.clientEntityId = joinGamePacket.EntityId } else { var swapDimension int32 if joinGamePacket.Dimension == 0 { swapDimension = 1 } else { swapDimension = 0 } this.session.Write(minecraft.NewPacketClientRespawn(swapDimension, 2, 0, "DEFAULT")) this.session.Write(minecraft.NewPacketClientRespawn(int32(joinGamePacket.Dimension), joinGamePacket.Difficulty, joinGamePacket.Gamemode, joinGamePacket.LevelType)) if len(this.session.playerList) > 0 { if this.session.protocol17 { for player, _ := range this.session.playerList { this.session.Write(minecraft.NewPacketClientPlayerList17Remove(player)) } } else { items := make([]minecraft.PacketClientPlayerListItem, 0, len(this.session.playerList)) for uuidString, _ := range this.session.playerList { items = append(items, minecraft.PacketClientPlayerListItem{UUID: uuid.UUID(uuidString)}) } this.session.Write(minecraft.NewPacketClientPlayerList(minecraft.PACKET_CLIENT_PLAYER_LIST_ACTION_REMOVE, items)) } this.session.playerList = make(map[string]struct{}) } if len(this.session.scoreboards) > 0 { for scoreboard, _ := range this.session.scoreboards { this.session.Write(minecraft.NewPacketClientScoreboardObjectiveRemove(scoreboard)) } this.session.scoreboards = make(map[string]struct{}) } if len(this.session.teams) > 0 { for team, _ := range this.session.teams { this.session.Write(minecraft.NewPacketClientTeamsRemove(team)) } this.session.teams = make(map[string]struct{}) } if len(this.session.pluginChannels) > 0 { channels := make([][]byte, 0, len(this.session.pluginChannels)) for channel, _ := range this.session.pluginChannels { channels = append(channels, []byte(channel)) } this.Write(minecraft.NewPacketServerPluginMessage("REGISTER", bytes.Join(channels, []byte{0}))) } return } case minecraft.PACKET_CLIENT_PLAYER_LIST: if this.session.protocol17 { playerListPacket := packet.(*minecraft.PacketClientPlayerList17) if playerListPacket.Online { this.session.playerList[playerListPacket.Name] = struct{}{} } else { delete(this.session.playerList, playerListPacket.Name) } } else { playerListPacket := packet.(*minecraft.PacketClientPlayerList) if playerListPacket.Action == minecraft.PACKET_CLIENT_PLAYER_LIST_ACTION_ADD { for _, item := range playerListPacket.Items { this.session.playerList[string(item.UUID)] = struct{}{} } } else if playerListPacket.Action == minecraft.PACKET_CLIENT_PLAYER_LIST_ACTION_REMOVE { for _, item := range playerListPacket.Items { delete(this.session.playerList, string(item.UUID)) } } } case minecraft.PACKET_CLIENT_SCOREBOARD_OBJECTIVE: scoreboardPacket := packet.(*minecraft.PacketClientScoreboardObjective) if scoreboardPacket.Action == minecraft.PACKET_CLIENT_SCOREBOARD_OBJECTIVE_ACTION_ADD { this.session.scoreboards[scoreboardPacket.Name] = struct{}{} } else if scoreboardPacket.Action == minecraft.PACKET_CLIENT_SCOREBOARD_OBJECTIVE_ACTION_REMOVE { delete(this.session.scoreboards, scoreboardPacket.Name) } case minecraft.PACKET_CLIENT_TEAMS: teamPacket := packet.(*minecraft.PacketClientTeams) if teamPacket.Action == minecraft.PACKET_CLIENT_TEAMS_ACTION_ADD { this.session.teams[teamPacket.Name] = struct{}{} } else if teamPacket.Action == minecraft.PACKET_CLIENT_TEAMS_ACTION_REMOVE { delete(this.session.teams, teamPacket.Name) } case minecraft.PACKET_CLIENT_DISCONNECT: this.session.DisconnectJson(packet.(*minecraft.PacketClientDisconnect).Json) return case minecraft.PACKET_CLIENT_SET_COMPRESSION: this.SetCompression(packet.(*minecraft.PacketClientSetCompression).Threshold) return default: if genericPacket, ok := packet.(*minecraft.PacketGeneric); ok { genericPacket.SwapEntities(this.session.clientEntityId, this.session.serverEntityId, true, this.session.protocol17) } } this.session.Write(packet) } return }
func (this *SessionOutBridge) HandlePacket(packet packet.Packet) (err error) { this.session.outMutex.Lock() defer this.session.outMutex.Unlock() if !this.session.Authenticated() { this.conn.Close() return } switch this.state { case STATE_LOGIN: if packet.Id() == minecraft.PACKET_CLIENT_LOGIN_SUCCESS { this.state = STATE_INIT this.session.redirecting = true this.codec.SetEncodeCodec(minecraft.PlayPacketServerCodec) this.codec.SetDecodeCodec(minecraft.PlayPacketClientCodec) } else if packet.Id() == minecraft.PACKET_CLIENT_LOGIN_DISCONNECT { this.session.DisconnectRaw(packet.(*minecraft.PacketClientLoginDisconnect).Json) this.conn.Close() } else { if this.session.Initializing() { this.session.Disconnect("Error: Outbound Protocol Mismatch") } this.conn.Close() } case STATE_INIT: if packet.Id() == 0x08 { oldOutBridge := this.session.outBridge if oldOutBridge != nil { oldOutBridge.conn.Close() } this.session.outBridge = this this.session.redirecting = false this.session.state = STATE_CONNECTED this.state = STATE_CONNECTED } fallthrough case STATE_CONNECTED: if packet.Id() == minecraft.PACKET_CLIENT_DISCONNECT { this.state = STATE_DISCONNECTED } if this.session.outBridge == this && this.session.redirecting { break } switch packet.Id() { case minecraft.PACKET_CLIENT_JOIN_GAME: joinGamePacket := packet.(*minecraft.PacketClientJoinGame) if this.session.clientSettings != nil { this.Write(this.session.clientSettings) } this.session.serverEntityId = joinGamePacket.EntityId if this.session.state == STATE_INIT { this.session.clientEntityId = joinGamePacket.EntityId } else { var swapDimension int32 if joinGamePacket.Dimension == 0 { swapDimension = 1 } else { swapDimension = 0 } this.session.Write(&minecraft.PacketClientRespawn{swapDimension, 2, 0, "DEFAULT"}) this.session.Write(&minecraft.PacketClientRespawn{int32(joinGamePacket.Dimension), joinGamePacket.Difficulty, joinGamePacket.Gamemode, joinGamePacket.LevelType}) for player, _ := range this.session.playerList { this.session.Write(&minecraft.PacketClientPlayerListItem{player, false, 0}) } this.session.playerList = make(map[string]bool) for scoreboard, _ := range this.session.scoreboards { this.session.Write(&minecraft.PacketClientScoreboardObjective{scoreboard, "", 1}) } this.session.scoreboards = make(map[string]bool) for team, _ := range this.session.teams { this.session.Write(&minecraft.PacketClientTeams{team, 1, "", "", "", 0, nil}) } this.session.teams = make(map[string]bool) return } case minecraft.PACKET_CLIENT_PLAYER_LIST_ITEM: playerListPacket := packet.(*minecraft.PacketClientPlayerListItem) if playerListPacket.Online { this.session.playerList[playerListPacket.Name] = true } else { delete(this.session.playerList, playerListPacket.Name) } case minecraft.PACKET_CLIENT_SCOREBOARD_OBJECTIVE: scoreboardPacket := packet.(*minecraft.PacketClientScoreboardObjective) if scoreboardPacket.Action == 0 { this.session.scoreboards[scoreboardPacket.Name] = true } else if scoreboardPacket.Action == 1 { delete(this.session.scoreboards, scoreboardPacket.Name) } case minecraft.PACKET_CLIENT_TEAMS: teamPacket := packet.(*minecraft.PacketClientTeams) if teamPacket.Action == 0 { this.session.teams[teamPacket.Name] = true } else if teamPacket.Action == 1 { delete(this.session.teams, teamPacket.Name) } case minecraft.PACKET_CLIENT_DISCONNECT: this.session.DisconnectRaw(packet.(*minecraft.PacketClientDisconnect).Json) return default: if genericPacket, ok := packet.(*minecraft.PacketGeneric); ok { genericPacket.SwapEntities(this.session.clientEntityId, this.session.serverEntityId, true) } } this.session.Write(packet) } return }
func (this *Session) HandlePacket(packet packet.Packet) (err error) { switch this.state { case STATE_DISCONNECTED: if packet.Id() == minecraft.PACKET_SERVER_HANDSHAKE { handshakePacket := packet.(*minecraft.PacketServerHandshake) this.serverAddress = handshakePacket.ServerAddress if handshakePacket.State == 1 { this.codec.SetEncodeCodec(minecraft.StatusPacketClientCodec) this.codec.SetDecodeCodec(minecraft.StatusPacketServerCodec) this.state = STATE_STATUS } else if handshakePacket.State == 2 { if handshakePacket.ProtocolVersion != minecraft.VERSION { err = errors.New("Protocol version does not match") return } this.codec.SetEncodeCodec(minecraft.LoginPacketClientCodec) this.codec.SetDecodeCodec(minecraft.LoginPacketServerCodec) this.state = STATE_LOGIN } else { err = errors.New("Unexpected state") return } } else { err = errors.New("Unexpected packet") return } case STATE_STATUS: if packet.Id() == minecraft.PACKET_SERVER_STATUS_REQUEST { favicon, faviconErr := ioutil.ReadFile("server-icon.png") var faviconString string if faviconErr == nil { faviconString = "data:image/png;base64," + base64.StdEncoding.EncodeToString(favicon) } version := make(map[string]interface{}) version["name"] = minecraft.STRING_VERSION version["protocol"] = minecraft.VERSION players := make(map[string]interface{}) players["max"] = this.server.Connect().MaxPlayers() players["online"] = this.server.Connect().Players() description := make(map[string]interface{}) description["text"] = minecraft.Colorize(this.server.Router().RouteMotd(this.serverAddress)) response := make(map[string]interface{}) response["version"] = version response["players"] = players response["description"] = description if faviconString != "" { response["favicon"] = faviconString } var marshalled []byte marshalled, err = json.Marshal(response) if err != nil { return } err = this.Write(&minecraft.PacketClientStatusResponse{string(marshalled)}) if err != nil { return } this.state = STATE_STATUS_PING } else { err = errors.New("Unexpected packet") return } case STATE_STATUS_PING: if packet.Id() == minecraft.PACKET_SERVER_STATUS_PING { err = this.Write(&minecraft.PacketClientStatusPing{packet.(*minecraft.PacketServerStatusPing).Time}) if err != nil { return } this.conn.Close() } else { err = errors.New("Unexpected packet") return } case STATE_LOGIN: if packet.Id() == minecraft.PACKET_SERVER_LOGIN_START { this.name = packet.(*minecraft.PacketServerLoginStart).Name if this.server.Authenticate() { this.serverId, err = GenSalt() if err != nil { return } this.publicKey, err = x509.MarshalPKIXPublicKey(&this.server.PrivateKey().PublicKey) if err != nil { return } this.verifyToken, err = RandomBytes(4) if err != nil { return } err = this.Write(&minecraft.PacketClientLoginEncryptRequest{this.serverId, this.publicKey, this.verifyToken}) if err != nil { return } this.state = STATE_LOGIN_ENCRYPT } else { this.uuid = GenNameUUID("OfflinePlayer:" + this.name) this.SetAuthenticated(true) } } else { err = errors.New("Unexpected packet") return } case STATE_LOGIN_ENCRYPT: if packet.Id() == minecraft.PACKET_SERVER_LOGIN_ENCRYPT_RESPONSE { loginEncryptResponsePacket := packet.(*minecraft.PacketServerLoginEncryptResponse) var sharedSecret []byte sharedSecret, err = rsa.DecryptPKCS1v15(rand.Reader, this.server.PrivateKey(), loginEncryptResponsePacket.SharedSecret) if err != nil { return } var verifyToken []byte verifyToken, err = rsa.DecryptPKCS1v15(rand.Reader, this.server.PrivateKey(), loginEncryptResponsePacket.VerifyToken) if err != nil { return } if bytes.Compare(this.verifyToken, verifyToken) != 0 { err = errors.New("Verify token does not match") return } var block cipher.Block block, err = aes.NewCipher(sharedSecret) if err != nil { return } this.connCodec.SetReader(&cipher.StreamReader{ R: this.connCodec.Reader(), S: minecraft.NewCFB8Decrypter(block, sharedSecret), }) this.connCodec.SetWriter(&cipher.StreamWriter{ W: this.connCodec.Writer(), S: minecraft.NewCFB8Encrypter(block, sharedSecret), }) var authErr error this.uuid, authErr = auth.Authenticate(this.name, this.serverId, sharedSecret, this.publicKey) if authErr != nil { this.SetAuthenticated(false) fmt.Println("Proxy server, failed to authorize:", this.name, "ip:", this.RemoteIp(), "err:", authErr) } else { this.SetAuthenticated(true) fmt.Println("Proxy server, authorized:", this.name, "ip:", this.RemoteIp()) } } else { err = errors.New("Unexpected packet") return } case STATE_CONNECTED: if packet.Id() == minecraft.PACKET_SERVER_CLIENT_SETTINGS { this.clientSettings = packet } if this.redirecting { break } if genericPacket, ok := packet.(*minecraft.PacketGeneric); ok { genericPacket.SwapEntities(this.clientEntityId, this.serverEntityId, false) } this.outBridge.Write(packet) } return }