Files
Frodding/raknet/packets.go
2026-03-03 15:05:55 +03:00

167 lines
3.2 KiB
Go

package raknet
import (
"encoding/binary"
"net"
)
func BuildUnconnectedPong(timestamp int64, serverGUID int64, motd string) []byte {
s := NewStream()
s.WriteByte(0x1c)
s.WriteInt64BE(timestamp)
s.WriteInt64BE(serverGUID)
s.WriteMagic()
s.WriteString(motd)
return s.Bytes()
}
func BuildOpenConnectionReply1(serverGUID int64, mtu uint16) []byte {
s := NewStream()
s.WriteByte(0x06)
s.WriteMagic()
s.WriteInt64BE(serverGUID)
s.WriteBool(false)
s.WriteUint16BE(mtu)
return s.Bytes()
}
func BuildOpenConnectionReply2(serverGUID int64, clientAddr net.UDPAddr, mtu uint16) []byte {
s := NewStream()
s.WriteByte(0x08)
s.WriteMagic()
s.WriteInt64BE(serverGUID)
s.WriteAddress(clientAddr)
s.WriteUint16BE(mtu)
s.WriteBool(false)
return s.Bytes()
}
func BuildConnectionRequestAccepted(clientAddr net.UDPAddr, clientTimestamp int64, serverTimestamp int64) []byte {
s := NewStream()
s.WriteByte(0x10)
s.WriteAddress(clientAddr)
s.WriteUint16BE(0)
for i := 0; i < 10; i++ {
s.WriteAddress(net.UDPAddr{IP: net.ParseIP("0.0.0.0"), Port: 0})
}
s.WriteInt64BE(clientTimestamp)
s.WriteInt64BE(serverTimestamp)
return s.Bytes()
}
func BuildConnectedPong(pingTime int64, pongTime int64) []byte {
s := NewStream()
s.WriteByte(0x03)
s.WriteInt64BE(pingTime)
s.WriteInt64BE(pongTime)
return s.Bytes()
}
func ParseUnconnectedPing(data []byte) (timestamp int64, guid int64, ok bool) {
if len(data) < 1+8+16 {
return
}
timestamp = int64(binary.BigEndian.Uint64(data[1:9]))
magic := RaknetMagic()
for i, b := range magic {
if data[9+i] != b {
return
}
}
if len(data) >= 1+8+16+8 {
guid = int64(binary.BigEndian.Uint64(data[25:33]))
}
ok = true
return
}
func ParseOCR1(data []byte) (proto byte, mtu uint16, ok bool) {
if len(data) < 1+16+1 {
return
}
magic := RaknetMagic()
for i, b := range magic {
if data[1+i] != b {
return
}
}
proto = data[17]
mtu = uint16(len(data) + 28)
ok = true
return
}
func ParseOCR2(data []byte) (clientGUID int64, clientAddr net.UDPAddr, mtu uint16, ok bool) {
s := NewStreamBytes(data)
s.Skip(1)
magic := RaknetMagic()
mb, err := s.ReadBytes(16)
if err != nil {
return
}
for i, b := range magic {
if mb[i] != b {
return
}
}
addr, err := s.ReadAddress()
if err != nil {
return
}
clientAddr = addr
mtuV, err := s.ReadUint16BE()
if err != nil {
return
}
mtu = mtuV
guidV, err := s.ReadInt64BE()
if err != nil {
return
}
clientGUID = guidV
ok = true
return
}
func ParseConnectionRequest(payload []byte) (clientGUID int64, timestamp int64, ok bool) {
if len(payload) < 17 {
return
}
if payload[0] != 0x09 {
return
}
s := NewStreamBytes(payload[1:])
g, err := s.ReadInt64BE()
if err != nil {
return
}
t, err := s.ReadInt64BE()
if err != nil {
return
}
clientGUID = g
timestamp = t
ok = true
return
}
func IsNewIncomingConnection(payload []byte) bool {
return len(payload) > 0 && payload[0] == 0x13
}
func IsDisconnect(payload []byte) bool {
return len(payload) > 0 && payload[0] == 0x15
}
func ParseConnectedPing(payload []byte) (timestamp int64, ok bool) {
if len(payload) < 9 || payload[0] != 0x00 {
return
}
s := NewStreamBytes(payload[1:])
t, err := s.ReadInt64BE()
if err != nil {
return
}
return t, true
}