Skip to content

Commit ab93c53

Browse files
committed
fix: Compatible with different login start packet formats
1 parent a30694b commit ab93c53

File tree

1 file changed

+31
-16
lines changed

1 file changed

+31
-16
lines changed

service/minecraft/handler.go

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ import (
1818
"github.com/fatih/color"
1919
)
2020

21-
// ErrSuccessfullyHandledMOTDRequest means the Minecraft client requested for MOTD
22-
// and has been correctly handled by program. This used to skip the data forward
23-
// process and directly go to the end of this connection.
24-
var ErrSuccessfullyHandledMOTDRequest = errors.New("")
25-
26-
var ErrRejectedLogin = ErrSuccessfullyHandledMOTDRequest // don't cry baby
21+
var (
22+
// ErrSuccessfullyHandledMOTDRequest means the Minecraft client requested for MOTD
23+
// and has been correctly handled by program. This used to skip the data forward
24+
// process and directly go to the end of this connection.
25+
ErrSuccessfullyHandledMOTDRequest = errors.New("")
26+
ErrRejectedLogin = ErrSuccessfullyHandledMOTDRequest // don't cry baby
27+
ErrBadPlayerName = ErrSuccessfullyHandledMOTDRequest
28+
)
2729

2830
func badPacketPanicRecover(s *config.ConfigProxyService) {
2931
// Non-Minecraft packet which uses `go-mc` packet scan method may cause panic.
@@ -147,23 +149,35 @@ func NewConnHandler(s *config.ConfigProxyService,
147149
// else: login
148150

149151
// Server bound : Login Start
150-
// This packet shall be at most 1+mcprotocol.MaxVarIntLen+16+1+16=39 bytes long.
151-
// 1 stands for packet ID.
152-
// mcprotocol.MaxVarIntLen stands for player name length.
153-
// 16 stands for the maximum length of a valid player name.
154-
// 1 stands for boolean which decides whether the UUID will be sent.
155-
// 16 stands for optional UUID length.
152+
// We only read its packet length and the player name, ignoring the rest part.
153+
// Unread part would be sent to target during the copy stage.
154+
// The reason for doing this is that this packet format has been modified many times in the history
155+
// and it would take a lot of code to make it all compatible. So why not just forward it?
156156
// Get player name and check the profile
157157
buffer.Reset(mcprotocol.MaxVarIntLen)
158-
err = conn.ReadLimitedPacket(buffer, 1+mcprotocol.MaxVarIntLen+16+1+16)
158+
loginStartLen, _, err := mcprotocol.ReadVarIntFrom(c)
159159
if err != nil {
160160
return nil, err
161161
}
162-
var playerName string
163-
err = mcprotocol.Scan(buffer, &packetID, &playerName)
162+
_, _, err = mcprotocol.ReadVarIntFrom(c) // skip packet ID
164163
if err != nil {
165164
return nil, err
166165
}
166+
var playerName string
167+
{
168+
playerNameLen, _, err := mcprotocol.ReadVarIntFrom(c)
169+
if err != nil {
170+
return nil, err
171+
}
172+
if playerNameLen > 16 || playerNameLen <= 0 {
173+
return nil, ErrBadPlayerName
174+
}
175+
_, err = buffer.ReadFullFrom(c, int(playerNameLen))
176+
if err != nil {
177+
return nil, err
178+
}
179+
playerName = string(buffer.Bytes())
180+
}
167181

168182
if s.Minecraft.OnlineCount.EnableMaxLimit && s.Minecraft.OnlineCount.Max <= int(options.OnlineCount.Load()) {
169183
log.Printf("Service %s : %s Rejected a new Minecraft player login request due to online player number limit: %s", s.Name, ctx.ColoredID, playerName)
@@ -293,7 +307,8 @@ func NewConnHandler(s *config.ConfigProxyService,
293307
if err != nil {
294308
return nil, err
295309
}
296-
err = remoteMC.WritePacket(buffer)
310+
mcprotocol.AppendPacketLength(buffer, int(loginStartLen))
311+
_, err = remote.Write(buffer.Bytes())
297312
if err != nil {
298313
return nil, err
299314
}

0 commit comments

Comments
 (0)