167 lines
3.2 KiB
Go
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
|
|
}
|