Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions connsocket.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// SPDX-FileCopyrightText: 2025 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT

package transport

import (
"net"
"time"
)

type NetConnSocket interface {
net.Conn

ReadWithAttributes(p []byte, attr *PacketAttributes) (n int, err error)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better if we unify attribute types in the APIs.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having a generic packet attributes type with variable buffer length would address this comment right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah a generic packet attributes will be cool, good idea.

}

type PacketConnSocket interface {
net.PacketConn

ReadFromWithAttributes(p []byte, attr *PacketAttributes) (n int, addr net.Addr, err error)
}

// NetConnToNetConnSocket wraps a net.Conn and implements the PacketStream interface by delegating
// calls to the underlying connection. ReadWithAttributes delegates to Read and
// ignores the provided PacketAttributes.
type NetConnToNetConnSocket struct {
conn net.Conn
}

// NewNetConnToNetConnSocket returns a new Proxy that wraps the provided net.Conn.
func NewNetConnToNetConnSocket(conn net.Conn) *NetConnToNetConnSocket {
return &NetConnToNetConnSocket{conn: conn}
}

// ReadWithAttributes reads from the underlying connection and ignores attributes.
func (p *NetConnToNetConnSocket) ReadWithAttributes(b []byte, _ *PacketAttributes) (int, error) {
return p.conn.Read(b)
}

// Delegate net.Conn methods to the underlying connection.

Check failure on line 40 in connsocket.go

View workflow job for this annotation

GitHub Actions / lint / Go

ST1020: comment on exported method Read should be of the form "Read ..." (staticcheck)
func (p *NetConnToNetConnSocket) Read(b []byte) (int, error) { return p.conn.Read(b) }
func (p *NetConnToNetConnSocket) Write(b []byte) (int, error) { return p.conn.Write(b) }
func (p *NetConnToNetConnSocket) Close() error { return p.conn.Close() }
func (p *NetConnToNetConnSocket) LocalAddr() net.Addr { return p.conn.LocalAddr() }
func (p *NetConnToNetConnSocket) RemoteAddr() net.Addr { return p.conn.RemoteAddr() }
func (p *NetConnToNetConnSocket) SetDeadline(t time.Time) error { return p.conn.SetDeadline(t) }
func (p *NetConnToNetConnSocket) SetReadDeadline(t time.Time) error { return p.conn.SetReadDeadline(t) }
func (p *NetConnToNetConnSocket) SetWriteDeadline(t time.Time) error {
return p.conn.SetWriteDeadline(t)
}

type PacketConnToPacketConnSocket struct {
conn net.PacketConn
}

func NewPacketConnToPacketConnSocket(conn net.PacketConn) *PacketConnToPacketConnSocket {
return &PacketConnToPacketConnSocket{
conn: conn,
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please explain why we need these two structs and why we need to make them public?
I also think the name of PacketConnToPacketConnSocket can be better.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The answer is not in transport but in other repos like srtp and webrtc. The issue is, the socket is abstracted with either net.Conn or net.PacketConn in the code. For example take mux.

mux implements net.Conn so it has a method Read or Write (just like a socket) but I needed to tell my mux to ReadWithAttributes. This is why these two structs are defined.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't this just be a helper-cast function that simply returns an interface, err without exposing a new public struct?

Copy link
Author

@penhauer penhauer Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean something like?

var conn net.Conn

if s, ok := conn.(*NetConnSocket); ok != nil {
   // some code
}

yes this is doable. I'm not much experienced in Go, but I just learned this for the changes I made, so initially I didn't think of this.


func (u *PacketConnToPacketConnSocket) ReadFromWithAttributes(
p []byte, _ *PacketAttributes) (n int, addr net.Addr, err error) {

Check failure on line 63 in connsocket.go

View workflow job for this annotation

GitHub Actions / lint / Go

File is not properly formatted (gofumpt)
return u.conn.ReadFrom(p)
}

func (u *PacketConnToPacketConnSocket) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
return u.conn.ReadFrom(p)
}

func (u *PacketConnToPacketConnSocket) WriteTo(b []byte, addr net.Addr) (int, error) {
n, err := u.conn.WriteTo(b, addr)

return n, err
}

func (u *PacketConnToPacketConnSocket) Close() error {
return u.conn.Close()
}

func (u *PacketConnToPacketConnSocket) LocalAddr() net.Addr {
return u.conn.LocalAddr()
}

func (u *PacketConnToPacketConnSocket) SetDeadline(t time.Time) error {
return u.conn.SetDeadline(t)
}

func (u *PacketConnToPacketConnSocket) SetReadDeadline(t time.Time) error {
return u.conn.SetReadDeadline(t)
}

func (u *PacketConnToPacketConnSocket) SetWriteDeadline(t time.Time) error {
return u.conn.SetWriteDeadline(t)
}
38 changes: 38 additions & 0 deletions packetattributes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// SPDX-FileCopyrightText: 2025 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT

package transport

const MaxAttributesLen = 1024

type PacketAttributes struct {
Buffer []byte
BytesCopied int
}

func NewPacketAttributesWithLen(length int) *PacketAttributes {
buff := make([]byte, length)

return &PacketAttributes{
Buffer: buff,
BytesCopied: 0,
}
}

func (p *PacketAttributes) Clone() *PacketAttributes {
b := make([]byte, p.BytesCopied)
copy(b, p.Buffer)
return &PacketAttributes{

Check failure on line 25 in packetattributes.go

View workflow job for this annotation

GitHub Actions / lint / Go

return with no blank line before (nlreturn)
Buffer: b,
BytesCopied: p.BytesCopied,
}
}

// Returns the read buffer. Just like when calling a read on a socket we have n, err := conn.Read(buf)

Check failure on line 31 in packetattributes.go

View workflow job for this annotation

GitHub Actions / lint / Go

ST1020: comment on exported method GetReadPacketAttributes should be of the form "GetReadPacketAttributes ..." (staticcheck)
// and the read bytes are in buf[:n], we should use this method after calling the ReadWithAttributes method.
func (p *PacketAttributes) GetReadPacketAttributes() *PacketAttributes {
return &PacketAttributes{
Buffer: p.Buffer[:p.BytesCopied],
BytesCopied: p.BytesCopied,
}
}
Loading
Loading