243 lines
4.4 KiB
Go
243 lines
4.4 KiB
Go
package raknet
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"strings"
|
|
"strconv"
|
|
)
|
|
|
|
type Stream struct {
|
|
buf []byte
|
|
pos int
|
|
}
|
|
|
|
func NewStream() *Stream {
|
|
return &Stream{}
|
|
}
|
|
|
|
func NewStreamBytes(b []byte) *Stream {
|
|
c := make([]byte, len(b))
|
|
copy(c, b)
|
|
return &Stream{buf: c}
|
|
}
|
|
|
|
func (s *Stream) Bytes() []byte {
|
|
return s.buf
|
|
}
|
|
|
|
func (s *Stream) Len() int {
|
|
return len(s.buf) - s.pos
|
|
}
|
|
|
|
func (s *Stream) Reset() {
|
|
s.buf = s.buf[:0]
|
|
s.pos = 0
|
|
}
|
|
|
|
func (s *Stream) Skip(n int) {
|
|
s.pos += n
|
|
}
|
|
|
|
func (s *Stream) ReadByte() (byte, error) {
|
|
if s.pos >= len(s.buf) {
|
|
return 0, errors.New("stream underflow")
|
|
}
|
|
b := s.buf[s.pos]
|
|
s.pos++
|
|
return b, nil
|
|
}
|
|
|
|
func (s *Stream) ReadBytes(n int) ([]byte, error) {
|
|
if s.pos+n > len(s.buf) {
|
|
return nil, fmt.Errorf("stream underflow: need %d have %d", n, len(s.buf)-s.pos)
|
|
}
|
|
b := s.buf[s.pos : s.pos+n]
|
|
s.pos += n
|
|
return b, nil
|
|
}
|
|
|
|
func (s *Stream) ReadUint16BE() (uint16, error) {
|
|
b, err := s.ReadBytes(2)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return binary.BigEndian.Uint16(b), nil
|
|
}
|
|
|
|
func (s *Stream) ReadUint32BE() (uint32, error) {
|
|
b, err := s.ReadBytes(4)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return binary.BigEndian.Uint32(b), nil
|
|
}
|
|
|
|
func (s *Stream) ReadInt32BE() (int32, error) {
|
|
v, err := s.ReadUint32BE()
|
|
return int32(v), err
|
|
}
|
|
|
|
func (s *Stream) ReadInt64BE() (int64, error) {
|
|
b, err := s.ReadBytes(8)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return int64(binary.BigEndian.Uint64(b)), nil
|
|
}
|
|
|
|
func (s *Stream) ReadUint24LE() (uint32, error) {
|
|
b, err := s.ReadBytes(3)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16, nil
|
|
}
|
|
|
|
func (s *Stream) ReadBool() (bool, error) {
|
|
b, err := s.ReadByte()
|
|
return b != 0, err
|
|
}
|
|
|
|
func (s *Stream) ReadString() (string, error) {
|
|
n, err := s.ReadUint16BE()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
b, err := s.ReadBytes(int(n))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(b), nil
|
|
}
|
|
|
|
func (s *Stream) ReadMagic() (bool, error) {
|
|
b, err := s.ReadBytes(16)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
expected := RaknetMagic()
|
|
for i, v := range expected {
|
|
if b[i] != v {
|
|
return false, nil
|
|
}
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
func (s *Stream) ReadAddress() (net.UDPAddr, error) {
|
|
ver, err := s.ReadByte()
|
|
if err != nil {
|
|
return net.UDPAddr{}, err
|
|
}
|
|
if ver == 4 {
|
|
ip := make([]byte, 4)
|
|
for i := 0; i < 4; i++ {
|
|
b, err := s.ReadByte()
|
|
if err != nil {
|
|
return net.UDPAddr{}, err
|
|
}
|
|
ip[i] = ^b
|
|
}
|
|
port, err := s.ReadUint16BE()
|
|
if err != nil {
|
|
return net.UDPAddr{}, err
|
|
}
|
|
return net.UDPAddr{IP: net.IP(ip), Port: int(port)}, nil
|
|
}
|
|
b, err := s.ReadBytes(18)
|
|
if err != nil {
|
|
return net.UDPAddr{}, err
|
|
}
|
|
port := binary.BigEndian.Uint16(b[0:2])
|
|
ip := net.IP(b[2:18])
|
|
return net.UDPAddr{IP: ip, Port: int(port)}, nil
|
|
}
|
|
|
|
func (s *Stream) WriteByte(v byte) {
|
|
s.buf = append(s.buf, v)
|
|
}
|
|
|
|
func (s *Stream) WriteBytes(v []byte) {
|
|
s.buf = append(s.buf, v...)
|
|
}
|
|
|
|
func (s *Stream) WriteUint16BE(v uint16) {
|
|
s.buf = append(s.buf, byte(v>>8), byte(v))
|
|
}
|
|
|
|
func (s *Stream) WriteUint32BE(v uint32) {
|
|
s.buf = append(s.buf, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
|
|
}
|
|
|
|
func (s *Stream) WriteInt32BE(v int32) {
|
|
s.WriteUint32BE(uint32(v))
|
|
}
|
|
|
|
func (s *Stream) WriteInt64BE(v int64) {
|
|
s.buf = append(s.buf,
|
|
byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32),
|
|
byte(v>>24), byte(v>>16), byte(v>>8), byte(v),
|
|
)
|
|
}
|
|
|
|
func (s *Stream) WriteUint24LE(v uint32) {
|
|
s.buf = append(s.buf, byte(v), byte(v>>8), byte(v>>16))
|
|
}
|
|
|
|
func (s *Stream) WriteBool(v bool) {
|
|
if v {
|
|
s.WriteByte(1)
|
|
} else {
|
|
s.WriteByte(0)
|
|
}
|
|
}
|
|
|
|
func (s *Stream) WriteString(v string) {
|
|
b := []byte(v)
|
|
s.WriteUint16BE(uint16(len(b)))
|
|
s.WriteBytes(b)
|
|
}
|
|
|
|
func (s *Stream) WriteMagic() {
|
|
s.WriteBytes(RaknetMagic())
|
|
}
|
|
|
|
func (s *Stream) WriteAddress(addr net.UDPAddr) {
|
|
ip := addr.IP.To4()
|
|
if ip != nil {
|
|
s.WriteByte(4)
|
|
for _, b := range ip {
|
|
s.WriteByte(^b)
|
|
}
|
|
s.WriteUint16BE(uint16(addr.Port))
|
|
} else {
|
|
s.WriteByte(6)
|
|
s.WriteUint16BE(uint16(addr.Port))
|
|
s.WriteUint32BE(0)
|
|
s.WriteBytes(addr.IP.To16())
|
|
s.WriteUint32BE(0)
|
|
}
|
|
}
|
|
|
|
func (s *Stream) WriteAddressRaw(ipStr string, port uint16) {
|
|
if strings.Contains(ipStr, ".") {
|
|
parts := strings.Split(ipStr, ".")
|
|
s.WriteByte(4)
|
|
for _, p := range parts {
|
|
v, _ := strconv.Atoi(p)
|
|
s.WriteByte(^byte(v))
|
|
}
|
|
s.WriteUint16BE(port)
|
|
} else {
|
|
ip := net.ParseIP(ipStr)
|
|
s.WriteByte(6)
|
|
s.WriteUint16BE(port)
|
|
s.WriteUint32BE(0)
|
|
s.WriteBytes(ip.To16())
|
|
s.WriteUint32BE(0)
|
|
}
|
|
}
|