Skip to content

Commit 0f7746f

Browse files
authored
Expose socket ReadBuffer & WriteBuffer functions (#223)
1 parent 18260e1 commit 0f7746f

File tree

4 files changed

+115
-4
lines changed

4 files changed

+115
-4
lines changed

conn.go

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -434,17 +434,20 @@ func (c *Conn) SetOption(option ConnOption, enable bool) error {
434434
return newOpError("set-option", conn.SetOption(option, enable))
435435
}
436436

437-
// A bufferSetter is a Socket that supports setting connection buffer sizes.
438-
type bufferSetter interface {
437+
// A bufferedSocket is a Socket that supports getting & setting connection
438+
// buffer sizes.
439+
type bufferedSocket interface {
439440
Socket
440441
SetReadBuffer(bytes int) error
441442
SetWriteBuffer(bytes int) error
443+
ReadBuffer() (int, error)
444+
WriteBuffer() (int, error)
442445
}
443446

444447
// SetReadBuffer sets the size of the operating system's receive buffer
445448
// associated with the Conn.
446449
func (c *Conn) SetReadBuffer(bytes int) error {
447-
conn, ok := c.sock.(bufferSetter)
450+
conn, ok := c.sock.(bufferedSocket)
448451
if !ok {
449452
return notSupported("set-read-buffer")
450453
}
@@ -455,14 +458,45 @@ func (c *Conn) SetReadBuffer(bytes int) error {
455458
// SetWriteBuffer sets the size of the operating system's transmit buffer
456459
// associated with the Conn.
457460
func (c *Conn) SetWriteBuffer(bytes int) error {
458-
conn, ok := c.sock.(bufferSetter)
461+
conn, ok := c.sock.(bufferedSocket)
459462
if !ok {
460463
return notSupported("set-write-buffer")
461464
}
462465

463466
return newOpError("set-write-buffer", conn.SetWriteBuffer(bytes))
464467
}
465468

469+
// ReadBuffer reads the size of the operating system's receive buffer
470+
// associated with the Conn.
471+
func (c *Conn) ReadBuffer() (int, error) {
472+
conn, ok := c.sock.(bufferedSocket)
473+
if !ok {
474+
return 0, notSupported("get-read-buffer")
475+
}
476+
477+
buff, err := conn.ReadBuffer()
478+
if err != nil {
479+
return 0, newOpError("get-read-buffer", err)
480+
}
481+
return buff, nil
482+
}
483+
484+
// WriteBuffer reads the size of the operating system's transmit buffer
485+
// associated with the Conn.
486+
func (c *Conn) WriteBuffer() (int, error) {
487+
conn, ok := c.sock.(bufferedSocket)
488+
if !ok {
489+
return 0, notSupported("get-write-buffer")
490+
}
491+
492+
buff, err := conn.WriteBuffer()
493+
if err != nil {
494+
return 0, newOpError("get-write-buffer", err)
495+
}
496+
497+
return buff, nil
498+
}
499+
466500
// A syscallConner is a Socket that supports syscall.Conn.
467501
type syscallConner interface {
468502
Socket

conn_linux.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,14 @@ func (c *conn) SetReadBuffer(bytes int) error { return c.s.SetReadBuffer(bytes)
212212
// associated with the Conn.
213213
func (c *conn) SetWriteBuffer(bytes int) error { return c.s.SetWriteBuffer(bytes) }
214214

215+
// ReadBuffer reads the size of the operating system's receive buffer
216+
// associated with the Conn.
217+
func (c *conn) ReadBuffer() (int, error) { return c.s.ReadBuffer() }
218+
219+
// WriteBuffer reads the size of the operating system's transmit buffer
220+
// associated with the Conn.
221+
func (c *conn) WriteBuffer() (int, error) { return c.s.WriteBuffer() }
222+
215223
// SyscallConn returns a raw network connection.
216224
func (c *conn) SyscallConn() (syscall.RawConn, error) { return c.s.SyscallConn() }
217225

conn_linux_integration_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,58 @@ func TestIntegrationConnSetBuffersSyscallConn(t *testing.T) {
425425
}
426426
}
427427

428+
func TestIntegrationConnBuffersSyscallConn(t *testing.T) {
429+
c, err := netlink.Dial(unix.NETLINK_GENERIC, nil)
430+
if err != nil {
431+
t.Fatalf("failed to dial netlink: %v", err)
432+
}
433+
defer c.Close()
434+
435+
rcvBuff, err := c.ReadBuffer()
436+
if err != nil {
437+
t.Fatalf("failed to get read buffer size: %v", err)
438+
}
439+
440+
sndBuff, err := c.WriteBuffer()
441+
if err != nil {
442+
t.Fatalf("failed to get write buffer size: %v", err)
443+
}
444+
445+
// Now that we've read the buffers, we can check the size by asking the
446+
// kernel using SyscallConn and getsockopt.
447+
448+
rc, err := c.SyscallConn()
449+
if err != nil {
450+
t.Fatalf("failed to get syscall conn: %v", err)
451+
}
452+
453+
mustSize := func(opt int) int {
454+
var (
455+
value int
456+
serr error
457+
)
458+
459+
err := rc.Control(func(fd uintptr) {
460+
value, serr = unix.GetsockoptInt(int(fd), unix.SOL_SOCKET, opt)
461+
})
462+
if err != nil {
463+
t.Fatalf("failed to call control: %v", err)
464+
}
465+
if serr != nil {
466+
t.Fatalf("failed to call getsockopt: %v", serr)
467+
}
468+
469+
return value
470+
}
471+
472+
if diff := cmp.Diff(rcvBuff, mustSize(unix.SO_RCVBUF)); diff != "" {
473+
t.Fatalf("unexpected read buffer size (-want +got):\n%s", diff)
474+
}
475+
if diff := cmp.Diff(sndBuff, mustSize(unix.SO_SNDBUF)); diff != "" {
476+
t.Fatalf("unexpected write buffer size (-want +got):\n%s", diff)
477+
}
478+
}
479+
428480
func TestIntegrationConnSetBPFEmpty(t *testing.T) {
429481
c, err := netlink.Dial(unix.NETLINK_GENERIC, nil)
430482
if err != nil {

conn_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,23 @@ func TestConnSetBuffersUnsupported(t *testing.T) {
261261
}
262262
}
263263

264+
func TestConnBuffersUnsupported(t *testing.T) {
265+
c := nltest.Dial(nil)
266+
defer c.Close()
267+
268+
ops := []func() (int, error){
269+
c.ReadBuffer,
270+
c.WriteBuffer,
271+
}
272+
273+
for _, op := range ops {
274+
_, err := op()
275+
if !strings.Contains(err.Error(), "not supported") {
276+
t.Fatalf("unexpected error: %v", err)
277+
}
278+
}
279+
}
280+
264281
func TestConnSyscallConnUnsupported(t *testing.T) {
265282
c := nltest.Dial(nil)
266283
defer c.Close()

0 commit comments

Comments
 (0)