From b67e0b3e91a87107a08af31b575be88695bcffa1 Mon Sep 17 00:00:00 2001 From: Eric Hop Date: Thu, 22 Jun 2023 17:56:24 -0700 Subject: [PATCH] remove obsolete temp layer --- packages/isc/hname.go | 10 +- packages/peering/lpp/lpp_net_impl.go | 12 +- packages/util/rwutil/convert.go | 274 ++++----------------------- packages/util/rwutil/reader.go | 123 +++++++----- packages/util/rwutil/writer.go | 85 +++++---- 5 files changed, 162 insertions(+), 342 deletions(-) diff --git a/packages/isc/hname.go b/packages/isc/hname.go index 713be5b54d..cc629581f4 100644 --- a/packages/isc/hname.go +++ b/packages/isc/hname.go @@ -73,11 +73,13 @@ func (hn Hname) String() string { } func (hn *Hname) Read(r io.Reader) error { - u32, err := rwutil.ReadUint32(r) - *hn = Hname(u32) - return err + rr := rwutil.NewReader(r) + *hn = Hname(rr.ReadUint32()) + return rr.Err } func (hn *Hname) Write(w io.Writer) error { - return rwutil.WriteUint32(w, uint32(*hn)) + ww := rwutil.NewWriter(w) + ww.WriteUint32(uint32(*hn)) + return ww.Err } diff --git a/packages/peering/lpp/lpp_net_impl.go b/packages/peering/lpp/lpp_net_impl.go index d9ea4b88d6..9127806ae0 100644 --- a/packages/peering/lpp/lpp_net_impl.go +++ b/packages/peering/lpp/lpp_net_impl.go @@ -535,7 +535,7 @@ func (n *netImpl) maintenanceLoop(stopCh chan bool) { } } -// readFrame differs from rwutil.ReadBytes because it uses ReadFull instead of Read to read the data. +// readFrame differs from ReadBytes because it uses ReadFull instead of Read to read the data. func readFrame(stream network.Stream) ([]byte, error) { var msgLenB [4]byte if msgLenN, err := io.ReadFull(stream, msgLenB[:]); err != nil || msgLenN != len(msgLenB) { @@ -560,12 +560,10 @@ func readFrame(stream network.Stream) ([]byte, error) { } func writeFrame(stream network.Stream, payload []byte) error { - err := rwutil.WriteUint32(stream, uint32(len(payload))) - if err != nil { - return err - } + ww := rwutil.NewWriter(stream) + ww.WriteUint32(uint32(len(payload))) if len(payload) != 0 { - _, err = stream.Write(payload) + ww.WriteN(payload) } - return err + return ww.Err } diff --git a/packages/util/rwutil/convert.go b/packages/util/rwutil/convert.go index a39d0213b3..3ed6689e7c 100644 --- a/packages/util/rwutil/convert.go +++ b/packages/util/rwutil/convert.go @@ -4,10 +4,8 @@ package rwutil import ( - "encoding/binary" "errors" "io" - "math" "testing" "github.com/stretchr/testify/require" @@ -52,159 +50,9 @@ func WriteN(w io.Writer, data []byte) error { return nil } -//////////////////// bool \\\\\\\\\\\\\\\\\\\\ +//////////////////// size32 encoding/decoding \\\\\\\\\\\\\\\\\\\\ -func ReadBool(r io.Reader) (bool, error) { - var b [1]byte - err := ReadN(r, b[:]) - if err != nil { - return false, err - } - if (b[0] & 0xfe) != 0x00 { - return false, errors.New("unexpected bool value") - } - return b[0] != 0, nil -} - -func WriteBool(w io.Writer, cond bool) error { - var b [1]byte - if cond { - b[0] = 1 - } - err := WriteN(w, b[:]) - return err -} - -//////////////////// byte \\\\\\\\\\\\\\\\\\\\ - -func ReadByte(r io.Reader) (byte, error) { - var b [1]byte - err := ReadN(r, b[:]) - return b[0], err -} - -func WriteByte(w io.Writer, val byte) error { - return WriteN(w, []byte{val}) -} - -//////////////////// bytes \\\\\\\\\\\\\\\\\\\\ - -func ReadBytes(r io.Reader) ([]byte, error) { - length, err := ReadSize32(r) - if err != nil { - return nil, err - } - if length == 0 { - return []byte{}, nil - } - ret := make([]byte, length) - err = ReadN(r, ret) - if err != nil { - return nil, err - } - return ret, nil -} - -func WriteBytes(w io.Writer, data []byte) error { - size := len(data) - if size > math.MaxUint32 { - panic("data size overflow") - } - err := WriteSize32(w, uint32(size)) - if err != nil { - return err - } - if size != 0 { - return WriteN(w, data) - } - return nil -} - -//////////////////// int8 \\\\\\\\\\\\\\\\\\\\ - -func ReadInt8(r io.Reader) (int8, error) { - val, err := ReadUint8(r) - return int8(val), err -} - -func WriteInt8(w io.Writer, val int8) error { - return WriteUint8(w, uint8(val)) -} - -//////////////////// int16 \\\\\\\\\\\\\\\\\\\\ - -func ReadInt16(r io.Reader) (int16, error) { - val, err := ReadUint16(r) - return int16(val), err -} - -func WriteInt16(w io.Writer, val int16) error { - return WriteUint16(w, uint16(val)) -} - -//////////////////// int32 \\\\\\\\\\\\\\\\\\\\ - -func ReadInt32(r io.Reader) (int32, error) { - val, err := ReadUint32(r) - return int32(val), err -} - -func WriteInt32(w io.Writer, val int32) error { - return WriteUint32(w, uint32(val)) -} - -//////////////////// int64 \\\\\\\\\\\\\\\\\\\\ - -func ReadInt64(r io.Reader) (int64, error) { - val, err := ReadUint64(r) - return int64(val), err -} - -func WriteInt64(w io.Writer, val int64) error { - return WriteUint64(w, uint64(val)) -} - -//////////////////// size32 \\\\\\\\\\\\\\\\\\\\ - -func Size32FromBytes(data []byte) (uint32, error) { - buf := Buffer(data) - return ReadSize32(&buf) -} - -func Size32ToBytes(s uint32) []byte { - switch { - case s < 0x80: - return []byte{byte(s)} - case s < 0x4000: - return []byte{byte(s | 0x80), byte(s >> 7)} - case s < 0x200000: - return []byte{byte(s | 0x80), byte((s >> 7) | 0x80), byte(s >> 14)} - case s < 0x10000000: - return []byte{byte(s | 0x80), byte((s >> 7) | 0x80), byte((s >> 14) | 0x80), byte(s >> 21)} - default: - return []byte{byte(s | 0x80), byte((s >> 7) | 0x80), byte((s >> 14) | 0x80), byte((s >> 21) | 0x80), byte(s >> 28)} - } -} - -func MustSize32FromBytes(b []byte) uint32 { - size, err := Size32FromBytes(b) - if err != nil { - panic(err) - } - return size -} - -func ReadSize32(r io.Reader) (uint32, error) { - return decodeSize32(func() (byte, error) { - return ReadByte(r) - }) -} - -func WriteSize32(w io.Writer, value uint32) error { - return WriteN(w, Size32ToBytes(value)) -} - -func decodeSize32(readByte func() (byte, error)) (uint32, error) { +func size32Decode(readByte func() (byte, error)) (uint32, error) { b, err := readByte() if err != nil { return 0, err @@ -251,95 +99,22 @@ func decodeSize32(readByte func() (byte, error)) (uint32, error) { return 0, errors.New("size32 overflow") } -//////////////////// string \\\\\\\\\\\\\\\\\\\\ - -func ReadString(r io.Reader) (string, error) { - ret, err := ReadBytes(r) - if err != nil { - return "", err - } - return string(ret), err -} - -func WriteString(w io.Writer, str string) error { - return WriteBytes(w, []byte(str)) -} - -//////////////////// uint8 \\\\\\\\\\\\\\\\\\\\ - -func ReadUint8(r io.Reader) (uint8, error) { - var b [1]byte - err := ReadN(r, b[:]) - return b[0], err -} - -func WriteUint8(w io.Writer, val uint8) error { - return WriteN(w, []byte{val}) -} - -//////////////////// uint16 \\\\\\\\\\\\\\\\\\\\ - -func ReadUint16(r io.Reader) (uint16, error) { - var b [2]byte - err := ReadN(r, b[:]) - if err != nil { - return 0, err - } - return binary.LittleEndian.Uint16(b[:]), nil -} - -func WriteUint16(w io.Writer, val uint16) error { - var b [2]byte - binary.LittleEndian.PutUint16(b[:], val) - return WriteN(w, b[:]) -} - -//////////////////// uint32 \\\\\\\\\\\\\\\\\\\\ - -func ReadUint32(r io.Reader) (uint32, error) { - var b [4]byte - err := ReadN(r, b[:]) - if err != nil { - return 0, err - } - return binary.LittleEndian.Uint32(b[:]), nil -} - -func WriteUint32(w io.Writer, val uint32) error { - var b [4]byte - binary.LittleEndian.PutUint32(b[:], val) - return WriteN(w, b[:]) -} - -//////////////////// uint64 \\\\\\\\\\\\\\\\\\\\ - -func ReadUint64(r io.Reader) (uint64, error) { - var b [8]byte - err := ReadN(r, b[:]) - if err != nil { - return 0, err +func size32Encode(s uint32) []byte { + switch { + case s < 0x80: + return []byte{byte(s)} + case s < 0x4000: + return []byte{byte(s | 0x80), byte(s >> 7)} + case s < 0x200000: + return []byte{byte(s | 0x80), byte((s >> 7) | 0x80), byte(s >> 14)} + case s < 0x10000000: + return []byte{byte(s | 0x80), byte((s >> 7) | 0x80), byte((s >> 14) | 0x80), byte(s >> 21)} + default: + return []byte{byte(s | 0x80), byte((s >> 7) | 0x80), byte((s >> 14) | 0x80), byte((s >> 21) | 0x80), byte(s >> 28)} } - return binary.LittleEndian.Uint64(b[:]), nil -} - -func WriteUint64(w io.Writer, val uint64) error { - var b [8]byte - binary.LittleEndian.PutUint64(b[:], val) - return WriteN(w, b[:]) } -//////////////////// bytes \\\\\\\\\\\\\\\\\\\\ - -// ReadFromFunc allows a reader to use any FromBytes()-like function as a source. -// It will read the next group of bytes and pass it to the specified function and -// returns the correct type of object -func ReadFromFunc[T any](rr *Reader, fromBytes func([]byte) (T, error)) (ret T) { - data := rr.ReadBytes() - if rr.Err == nil { - ret, rr.Err = fromBytes(data) - } - return ret -} +//////////////////// one-line implementation wrapper functions \\\\\\\\\\\\\\\\\\\\ // ReadFromBytes is a wrapper that uses an object's Read() function to marshal // the object from data bytes. It's typically used to implement a one-line @@ -371,6 +146,25 @@ func WriteToBytes(obj IoWriter) []byte { return ww.Bytes() } +//////////////////// misc generic wrapper functions \\\\\\\\\\\\\\\\\\\\ + +// ReadFromFunc allows a reader to use any FromBytes()-like function as a source. +// It will read the next group of bytes and pass it to the specified function and +// returns the correct type of object +func ReadFromFunc[T any](rr *Reader, fromBytes func([]byte) (T, error)) (ret T) { + data := rr.ReadBytes() + if rr.Err == nil { + ret, rr.Err = fromBytes(data) + } + return ret +} + +// SerializationTest can be used with any object that implements IoReader and IoWriter +// to test whether the Read() and Write() functions complement each other correctly. +// You pass in an object that has all fields that need serialization set, plus a new, +// empty object that will receive the deserialized data. The function will Write, Read, +// and Write again and compare the objects for equality and both serialized versions +// as well. func SerializationTest[T IoReadWriter](t *testing.T, obj1 T, newObj T) { data1 := WriteToBytes(obj1) obj2, err := ReadFromBytes(data1, newObj) diff --git a/packages/util/rwutil/reader.go b/packages/util/rwutil/reader.go index 1b90cd8f9d..4e54d50d62 100644 --- a/packages/util/rwutil/reader.go +++ b/packages/util/rwutil/reader.go @@ -4,6 +4,7 @@ package rwutil import ( + "encoding/binary" "errors" "io" "math" @@ -88,65 +89,72 @@ func (rr *Reader) ReadN(ret []byte) { } } -func (rr *Reader) ReadBool() (ret bool) { - if rr.Err == nil { - ret, rr.Err = ReadBool(rr.r) +func (rr *Reader) ReadBool() bool { + if rr.Err != nil { + return false } - return ret + var b [1]byte + rr.Err = ReadN(rr.r, b[:]) + if (b[0] & 0xfe) != 0x00 { + rr.Err = errors.New("unexpected bool value") + return false + } + return b[0] != 0x00 } //nolint:govet -func (rr *Reader) ReadByte() (ret byte) { - if rr.Err == nil { - ret, rr.Err = ReadByte(rr.r) +func (rr *Reader) ReadByte() byte { + if rr.Err != nil { + return 0 } - return ret + var b [1]byte + rr.Err = ReadN(rr.r, b[:]) + return b[0] } -func (rr *Reader) ReadBytes() (ret []byte) { - if rr.Err == nil { - ret, rr.Err = ReadBytes(rr.r) +func (rr *Reader) ReadBytes() []byte { + if rr.Err != nil { + return nil + } + size := rr.ReadSize32() + if rr.Err != nil { + return nil + } + if size == 0 { + return []byte{} + } + ret := make([]byte, size) + rr.Err = ReadN(rr.r, ret) + if rr.Err != nil { + return nil } return ret } func (rr *Reader) ReadDuration() (ret time.Duration) { - return time.Duration(rr.ReadInt64()) + return time.Duration(rr.ReadUint64()) } -func (rr *Reader) ReadFromFunc(read func(w io.Reader) (int, error)) *Reader { +func (rr *Reader) ReadFromFunc(read func(w io.Reader) (int, error)) { if rr.Err == nil { _, rr.Err = read(rr.r) } - return rr } func (rr *Reader) ReadInt8() (ret int8) { - if rr.Err == nil { - ret, rr.Err = ReadInt8(rr.r) - } - return ret + return int8(rr.ReadUint8()) } func (rr *Reader) ReadInt16() (ret int16) { - if rr.Err == nil { - ret, rr.Err = ReadInt16(rr.r) - } - return ret + return int16(rr.ReadUint16()) } func (rr *Reader) ReadInt32() (ret int32) { - if rr.Err == nil { - ret, rr.Err = ReadInt32(rr.r) - } - return ret + return int32(rr.ReadUint32()) } func (rr *Reader) ReadInt64() (ret int64) { - if rr.Err == nil { - ret, rr.Err = ReadInt64(rr.r) - } - return ret + return int64(rr.ReadUint64()) } func (rr *Reader) ReadKind() Kind { @@ -228,13 +236,16 @@ func (rr *Reader) ReadSize32() (size int) { // ReadSizeWithLimit reads an int size from the stream, and verifies that // it does not exceed the specified limit. By limiting the size we can -// better detect malformed input data. +// better detect malformed input data. The size returned will always be +// zero if an error occurred. func (rr *Reader) ReadSizeWithLimit(limit uint32) int { if rr.Err != nil { return 0 } var size32 uint32 - size32, rr.Err = ReadSize32(rr.r) + size32, rr.Err = size32Decode(func() (byte, error) { + return rr.ReadByte(), rr.Err + }) if size32 > limit && rr.Err == nil { rr.Err = errors.New("read size limit overflow") return 0 @@ -243,42 +254,54 @@ func (rr *Reader) ReadSizeWithLimit(limit uint32) int { } func (rr *Reader) ReadString() (ret string) { - if rr.Err == nil { - ret, rr.Err = ReadString(rr.r) - } - return ret + return string(rr.ReadBytes()) } func (rr *Reader) ReadUint8() (ret uint8) { - if rr.Err == nil { - ret, rr.Err = ReadUint8(rr.r) - } - return ret + return rr.ReadByte() } func (rr *Reader) ReadUint16() (ret uint16) { - if rr.Err == nil { - ret, rr.Err = ReadUint16(rr.r) + if rr.Err != nil { + return 0 } - return ret + var b [2]byte + rr.Err = ReadN(rr.r, b[:]) + if rr.Err != nil { + return 0 + } + return uint16(b[0]) | (uint16(b[1]) << 8) } func (rr *Reader) ReadUint32() (ret uint32) { - if rr.Err == nil { - ret, rr.Err = ReadUint32(rr.r) + if rr.Err != nil { + return 0 } - return ret + var b [4]byte + rr.Err = ReadN(rr.r, b[:]) + if rr.Err != nil { + return 0 + } + return binary.LittleEndian.Uint32(b[:]) } func (rr *Reader) ReadUint64() (ret uint64) { - if rr.Err == nil { - ret, rr.Err = ReadUint64(rr.r) + if rr.Err != nil { + return 0 } - return ret + var b [8]byte + rr.Err = ReadN(rr.r, b[:]) + if rr.Err != nil { + return 0 + } + return binary.LittleEndian.Uint64(b[:]) } func (rr *Reader) ReadUint256() (ret *big.Int) { ret = new(big.Int) - ret.SetBytes(rr.ReadBytes()) + data := rr.ReadBytes() + if data != nil { + ret.SetBytes(data) + } return ret } diff --git a/packages/util/rwutil/writer.go b/packages/util/rwutil/writer.go index f6c313a8c2..36e208facd 100644 --- a/packages/util/rwutil/writer.go +++ b/packages/util/rwutil/writer.go @@ -4,6 +4,7 @@ package rwutil import ( + "encoding/binary" "errors" "io" "math" @@ -75,7 +76,11 @@ func (ww *Writer) WriteN(val []byte) *Writer { func (ww *Writer) WriteBool(val bool) *Writer { if ww.Err == nil { - ww.Err = WriteBool(ww.w, val) + data := []byte{0x00} + if val { + data[0] = 0x01 + } + ww.Err = WriteN(ww.w, data) } return ww } @@ -83,20 +88,27 @@ func (ww *Writer) WriteBool(val bool) *Writer { //nolint:govet func (ww *Writer) WriteByte(val byte) *Writer { if ww.Err == nil { - ww.Err = WriteByte(ww.w, val) + ww.Err = WriteN(ww.w, []byte{val}) } return ww } -func (ww *Writer) WriteBytes(val []byte) *Writer { +func (ww *Writer) WriteBytes(data []byte) *Writer { if ww.Err == nil { - ww.Err = WriteBytes(ww.w, val) + size := len(data) + if size > math.MaxInt32 { + panic("data size overflow") + } + ww.WriteSize32(size) + if size != 0 { + ww.WriteN(data) + } } return ww } func (ww *Writer) WriteDuration(val time.Duration) *Writer { - return ww.WriteInt64(int64(val)) + return ww.WriteUint64(uint64(val)) } func (ww *Writer) WriteFromBytes(obj interface{ Bytes() []byte }) *Writer { @@ -114,31 +126,19 @@ func (ww *Writer) WriteFromFunc(write func(w io.Writer) (int, error)) *Writer { } func (ww *Writer) WriteInt8(val int8) *Writer { - if ww.Err == nil { - ww.Err = WriteInt8(ww.w, val) - } - return ww + return ww.WriteUint8(uint8(val)) } func (ww *Writer) WriteInt16(val int16) *Writer { - if ww.Err == nil { - ww.Err = WriteInt16(ww.w, val) - } - return ww + return ww.WriteUint16(uint16(val)) } func (ww *Writer) WriteInt32(val int32) *Writer { - if ww.Err == nil { - ww.Err = WriteInt32(ww.w, val) - } - return ww + return ww.WriteUint32(uint32(val)) } func (ww *Writer) WriteInt64(val int64) *Writer { - if ww.Err == nil { - ww.Err = WriteInt64(ww.w, val) - } - return ww + return ww.WriteUint64(uint64(val)) } func (ww *Writer) WriteKind(msgType Kind) *Writer { @@ -152,7 +152,8 @@ type serializable interface { // WriteSerialized writes the serializable object to the stream. // If no sizes are present a 16-bit size is written to the stream. // The first size indicates a different limit for the size written to the stream. -// The second size indicates the expected size and does not write it to the stream. +// The second size indicates the expected size and does not write it to the stream, +// but verifies that the serialized size is equal to the expected size.. func (ww *Writer) WriteSerialized(obj serializable, sizes ...int) *Writer { if ww.Err != nil { return ww @@ -193,63 +194,65 @@ func (ww *Writer) WriteSize16(val int) *Writer { func (ww *Writer) WriteSize32(val int) *Writer { // note we cannot exceed SIGNED max - // because if int is actually 32 bit it would be negative + // because if int is actually 32 bit it would become negative return ww.WriteSizeWithLimit(val, math.MaxInt32) } func (ww *Writer) WriteSizeWithLimit(val int, limit uint32) *Writer { if ww.Err == nil { - if val < 0 || val > int(limit) { - ww.Err = errors.New("invalid write size limit") - return ww + if 0 <= val && val <= int(limit) { + return ww.WriteN(size32Encode(uint32(val))) } - ww.Err = WriteSize32(ww.w, uint32(val)) + ww.Err = errors.New("invalid write size limit") } return ww } func (ww *Writer) WriteString(val string) *Writer { - if ww.Err == nil { - ww.Err = WriteString(ww.w, val) - } - return ww + return ww.WriteBytes([]byte(val)) } func (ww *Writer) WriteUint8(val uint8) *Writer { if ww.Err == nil { - ww.Err = WriteUint8(ww.w, val) + ww.Err = WriteN(ww.w, []byte{val}) } return ww } func (ww *Writer) WriteUint16(val uint16) *Writer { if ww.Err == nil { - ww.Err = WriteUint16(ww.w, val) + ww.Err = WriteN(ww.w, []byte{byte(val), byte(val >> 8)}) } return ww } func (ww *Writer) WriteUint32(val uint32) *Writer { if ww.Err == nil { - ww.Err = WriteUint32(ww.w, val) + var b [4]byte + binary.LittleEndian.PutUint32(b[:], val) + ww.Err = WriteN(ww.w, b[:]) } return ww } func (ww *Writer) WriteUint64(val uint64) *Writer { if ww.Err == nil { - ww.Err = WriteUint64(ww.w, val) + var b [8]byte + binary.LittleEndian.PutUint64(b[:], val) + ww.Err = WriteN(ww.w, b[:]) } return ww } func (ww *Writer) WriteUint256(val *big.Int) *Writer { - if val == nil { - val = new(big.Int) - } - if ww.Err == nil && val.Sign() < 0 { + if ww.Err == nil { + if val == nil { + val = new(big.Int) + } + if val.Sign() >= 0 { + return ww.WriteBytes(val.Bytes()) + } ww.Err = errors.New("negative uint256") - return ww } - return ww.WriteBytes(val.Bytes()) + return ww }