mirror of
https://github.com/btcsuite/btcd.git
synced 2025-02-23 14:40:44 +01:00
wire/netaddress: add optimiezed read/writeNetAddressBuf
This commit is contained in:
parent
dc4fbb04b3
commit
8bf07cc0bf
1 changed files with 65 additions and 15 deletions
|
@ -5,7 +5,6 @@
|
|||
package wire
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
|
@ -89,31 +88,59 @@ func NewNetAddress(addr *net.TCPAddr, services ServiceFlag) *NetAddress {
|
|||
// version and whether or not the timestamp is included per ts. Some messages
|
||||
// like version do not include the timestamp.
|
||||
func readNetAddress(r io.Reader, pver uint32, na *NetAddress, ts bool) error {
|
||||
var ip [16]byte
|
||||
buf := binarySerializer.Borrow()
|
||||
err := readNetAddressBuf(r, pver, na, ts, buf)
|
||||
binarySerializer.Return(buf)
|
||||
return err
|
||||
}
|
||||
|
||||
// readNetAddressBuf reads an encoded NetAddress from r depending on the
|
||||
// protocol version and whether or not the timestamp is included per ts. Some
|
||||
// messages like version do not include the timestamp.
|
||||
//
|
||||
// If b is non-nil, the provided buffer will be used for serializing small
|
||||
// values. Otherwise a buffer will be drawn from the binarySerializer's pool
|
||||
// and return when the method finishes.
|
||||
//
|
||||
// NOTE: b MUST either be nil or at least an 8-byte slice.
|
||||
func readNetAddressBuf(r io.Reader, pver uint32, na *NetAddress, ts bool,
|
||||
buf []byte) error {
|
||||
|
||||
var (
|
||||
timestamp time.Time
|
||||
services ServiceFlag
|
||||
ip [16]byte
|
||||
port uint16
|
||||
)
|
||||
|
||||
// NOTE: The bitcoin protocol uses a uint32 for the timestamp so it will
|
||||
// stop working somewhere around 2106. Also timestamp wasn't added until
|
||||
// protocol version >= NetAddressTimeVersion
|
||||
if ts && pver >= NetAddressTimeVersion {
|
||||
err := readElement(r, (*uint32Time)(&na.Timestamp))
|
||||
if err != nil {
|
||||
if _, err := io.ReadFull(r, buf[:4]); err != nil {
|
||||
return err
|
||||
}
|
||||
timestamp = time.Unix(int64(littleEndian.Uint32(buf[:4])), 0)
|
||||
}
|
||||
|
||||
err := readElements(r, &na.Services, &ip)
|
||||
if err != nil {
|
||||
if _, err := io.ReadFull(r, buf); err != nil {
|
||||
return err
|
||||
}
|
||||
services = ServiceFlag(littleEndian.Uint64(buf))
|
||||
|
||||
if _, err := io.ReadFull(r, ip[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Sigh. Bitcoin protocol mixes little and big endian.
|
||||
port, err := binarySerializer.Uint16(r, bigEndian)
|
||||
if err != nil {
|
||||
if _, err := io.ReadFull(r, buf[:2]); err != nil {
|
||||
return err
|
||||
}
|
||||
port = bigEndian.Uint16(buf[:2])
|
||||
|
||||
*na = NetAddress{
|
||||
Timestamp: na.Timestamp,
|
||||
Services: na.Services,
|
||||
Timestamp: timestamp,
|
||||
Services: services,
|
||||
IP: net.IP(ip[:]),
|
||||
Port: port,
|
||||
}
|
||||
|
@ -124,26 +151,49 @@ func readNetAddress(r io.Reader, pver uint32, na *NetAddress, ts bool) error {
|
|||
// version and whether or not the timestamp is included per ts. Some messages
|
||||
// like version do not include the timestamp.
|
||||
func writeNetAddress(w io.Writer, pver uint32, na *NetAddress, ts bool) error {
|
||||
buf := binarySerializer.Borrow()
|
||||
err := writeNetAddressBuf(w, pver, na, ts, buf)
|
||||
binarySerializer.Return(buf)
|
||||
return err
|
||||
}
|
||||
|
||||
// writeNetAddressBuf serializes a NetAddress to w depending on the protocol
|
||||
// version and whether or not the timestamp is included per ts. Some messages
|
||||
// like version do not include the timestamp.
|
||||
//
|
||||
// If b is non-nil, the provided buffer will be used for serializing small
|
||||
// values. Otherwise a buffer will be drawn from the binarySerializer's pool
|
||||
// and return when the method finishes.
|
||||
//
|
||||
// NOTE: b MUST either be nil or at least an 8-byte slice.
|
||||
func writeNetAddressBuf(w io.Writer, pver uint32, na *NetAddress, ts bool, buf []byte) error {
|
||||
// NOTE: The bitcoin protocol uses a uint32 for the timestamp so it will
|
||||
// stop working somewhere around 2106. Also timestamp wasn't added until
|
||||
// until protocol version >= NetAddressTimeVersion.
|
||||
if ts && pver >= NetAddressTimeVersion {
|
||||
err := writeElement(w, uint32(na.Timestamp.Unix()))
|
||||
if err != nil {
|
||||
littleEndian.PutUint32(buf[:4], uint32(na.Timestamp.Unix()))
|
||||
if _, err := w.Write(buf[:4]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
littleEndian.PutUint64(buf, uint64(na.Services))
|
||||
if _, err := w.Write(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ensure to always write 16 bytes even if the ip is nil.
|
||||
var ip [16]byte
|
||||
if na.IP != nil {
|
||||
copy(ip[:], na.IP.To16())
|
||||
}
|
||||
err := writeElements(w, na.Services, ip)
|
||||
if err != nil {
|
||||
if _, err := w.Write(ip[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Sigh. Bitcoin protocol mixes little and big endian.
|
||||
return binary.Write(w, bigEndian, na.Port)
|
||||
bigEndian.PutUint16(buf[:2], na.Port)
|
||||
_, err := w.Write(buf[:2])
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue