120 lines
3.2 KiB
Go
120 lines
3.2 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"encoding/binary"
|
||
|
"errors"
|
||
|
"hash/crc32"
|
||
|
"net"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
// sendPacket sends a packet with the given packetID and data over the provided TCP connection.
|
||
|
func sendPacket(packetID uint8, data []byte, conn *net.TCPConn) error {
|
||
|
// Create a buffer with the packet ID and data
|
||
|
tempBuffer := append([]byte{packetID}, data...)
|
||
|
|
||
|
// Calculate the checksum of the packet ID + data
|
||
|
checksum := crc32.ChecksumIEEE(tempBuffer)
|
||
|
|
||
|
// Convert the checksum to a 4-byte slice
|
||
|
checksumBytes := make([]byte, 4)
|
||
|
binary.LittleEndian.PutUint32(checksumBytes, checksum)
|
||
|
|
||
|
// Prepend the checksum to the beginning of the buffer
|
||
|
tempBuffer = append(checksumBytes, tempBuffer...)
|
||
|
|
||
|
// Calculate the total length (checksum + packet ID + data)
|
||
|
packetLength := uint32(len(tempBuffer))
|
||
|
|
||
|
// Prepare the output buffer with the length field
|
||
|
outBuffer := make([]byte, 4)
|
||
|
binary.LittleEndian.PutUint32(outBuffer, packetLength)
|
||
|
|
||
|
// Append the tempBuffer (checksum + packet ID + data) to outBuffer
|
||
|
outBuffer = append(outBuffer, tempBuffer...)
|
||
|
|
||
|
// Send the packet over the connection
|
||
|
writeLen, err := conn.Write(outBuffer)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if writeLen != len(outBuffer) {
|
||
|
return errors.New("write length does not match output buffer length")
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// receivePacket receives a packet from the provided TCP connection and verifies it.
|
||
|
func receivePacket(conn *net.TCPConn) (uint8, uint32, []byte, error) {
|
||
|
// Step 1: Read the packet length (4 bytes)
|
||
|
lengthBuffer := make([]byte, 4)
|
||
|
n, err := conn.Read(lengthBuffer)
|
||
|
if err != nil {
|
||
|
return 0, 0, nil, err
|
||
|
}
|
||
|
if n != len(lengthBuffer) {
|
||
|
return 0, 0, nil, errors.New("read length does not match read length")
|
||
|
}
|
||
|
|
||
|
packetLength := binary.LittleEndian.Uint32(lengthBuffer)
|
||
|
|
||
|
// Step 2: Allocate a buffer to hold the rest of the packet (checksum + packetID + data)
|
||
|
packetBuffer := make([]byte, packetLength)
|
||
|
n, err = conn.Read(packetBuffer)
|
||
|
if err != nil {
|
||
|
return 0, 0, nil, err
|
||
|
}
|
||
|
if n != int(packetLength) {
|
||
|
return 0, 0, nil, errors.New("read length does not match packet length")
|
||
|
}
|
||
|
|
||
|
// Ensure we've read enough bytes
|
||
|
if uint32(len(packetBuffer)) != packetLength {
|
||
|
return 0, 0, nil, errors.New("incomplete packet received")
|
||
|
}
|
||
|
|
||
|
// Step 3: Extract the checksum (4 bytes)
|
||
|
receivedChecksum := binary.LittleEndian.Uint32(packetBuffer[:4])
|
||
|
|
||
|
// Step 4: Extract the packet ID (1 byte)
|
||
|
packetID := packetBuffer[4]
|
||
|
|
||
|
// Step 5: Extract the data
|
||
|
data := packetBuffer[5:]
|
||
|
|
||
|
// Step 6: Verify the checksum
|
||
|
calculatedChecksum := crc32.ChecksumIEEE(append([]byte{packetID}, data...))
|
||
|
|
||
|
if receivedChecksum != calculatedChecksum {
|
||
|
return 0, 0, nil, errors.New("checksum mismatch")
|
||
|
}
|
||
|
|
||
|
// Return the packet ID and data
|
||
|
return packetID, uint32(len(data)), data, nil
|
||
|
}
|
||
|
|
||
|
func boolToByte(b bool) byte {
|
||
|
if b {
|
||
|
return 1
|
||
|
}
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
func byteToBool(b byte) bool {
|
||
|
return b == 1
|
||
|
}
|
||
|
|
||
|
func getCurrentVersion() []uint8 {
|
||
|
versionArrayString := strings.Split(GameVersion, ".")
|
||
|
if len(versionArrayString) < 3 {
|
||
|
return []uint8{}
|
||
|
}
|
||
|
var versionArray []uint8
|
||
|
for i := 0; i < len(versionArrayString); i++ {
|
||
|
intVersion, _ := strconv.Atoi(versionArrayString[i])
|
||
|
versionArray = append(versionArray, uint8(intVersion))
|
||
|
}
|
||
|
return versionArray
|
||
|
}
|