diff --git a/udp_mux_test.go b/udp_mux_test.go index 8b64f651..5fdb67a4 100644 --- a/udp_mux_test.go +++ b/udp_mux_test.go @@ -166,6 +166,20 @@ func TestAddressEncoding(t *testing.T) { } } +func BenchmarkAddressEncoding(b *testing.B) { + addr := &net.UDPAddr{ + IP: net.ParseIP("127.0.0.1"), + Port: 1234, + } + buf := make([]byte, 64) + + for i := 0; i < b.N; i++ { + if _, err := encodeUDPAddr(addr, buf); err != nil { + require.NoError(b, err) + } + } +} + func testMuxConnection(t *testing.T, udpMux *UDPMuxDefault, ufrag string, network string) { pktConn, err := udpMux.GetConn(ufrag, udpMux.LocalAddr()) require.NoError(t, err, "error retrieving muxed connection for ufrag") diff --git a/udp_muxed_conn.go b/udp_muxed_conn.go index 0244d130..88c1a53c 100644 --- a/udp_muxed_conn.go +++ b/udp_muxed_conn.go @@ -7,8 +7,11 @@ import ( "encoding/binary" "io" "net" + "net/netip" + "reflect" "sync" "time" + "unsafe" "github.com/pion/logging" "github.com/pion/transport/v3/packetio" @@ -211,19 +214,26 @@ func (c *udpMuxedConn) writePacket(data []byte, addr *net.UDPAddr) error { } func encodeUDPAddr(addr *net.UDPAddr, buf []byte) (int, error) { - ipData, err := addr.IP.MarshalText() - if err != nil { - return 0, err + if len(addr.IP) != 0 && len(addr.IP) != net.IPv4len && len(addr.IP) != net.IPv6len { + return 0, errInvalidAddress + } + + var n int + if ip4 := addr.IP.To4(); len(ip4) == net.IPv4len { + d := (*reflect.SliceHeader)(unsafe.Pointer(&ip4)) // nolint:gosec + n = len(netip.AddrFrom4(*(*[4]byte)(unsafe.Pointer(d.Data))).AppendTo(buf[2:2])) // nolint:gosec + } else if len(addr.IP) != 0 { + d := (*reflect.SliceHeader)(unsafe.Pointer(&addr.IP)) // nolint:gosec + n = len(netip.AddrFrom16(*(*[16]byte)(unsafe.Pointer(d.Data))).AppendTo(buf[2:2])) // nolint:gosec } - total := 2 + len(ipData) + 2 + len(addr.Zone) + + total := 2 + n + 2 + len(addr.Zone) if total > len(buf) { return 0, io.ErrShortBuffer } - binary.LittleEndian.PutUint16(buf, uint16(len(ipData))) - offset := 2 - n := copy(buf[offset:], ipData) - offset += n + binary.LittleEndian.PutUint16(buf, uint16(n)) + offset := 2 + n binary.LittleEndian.PutUint16(buf[offset:], uint16(addr.Port)) offset += 2 copy(buf[offset:], addr.Zone)