From 2bcfe5bc4b4d09716e7c7b708adbe5736fa87560 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Thu, 20 Jul 2023 20:31:57 -0700 Subject: [PATCH] check for WSAEMSGSIZE errors when receiving UDP packets on Windows (#3982) * check for WSAEMSGSIZE errors when receiving UDP packets on Windows * check EMSGSIZE error on macOS --- send_queue.go | 2 +- sys_conn_df.go | 7 ++++++- sys_conn_df_darwin.go | 4 +++- sys_conn_df_linux.go | 4 +++- sys_conn_df_windows.go | 7 ++++++- transport.go | 4 ++++ 6 files changed, 23 insertions(+), 5 deletions(-) diff --git a/send_queue.go b/send_queue.go index ab7a45ca..a9f7ca1a 100644 --- a/send_queue.go +++ b/send_queue.go @@ -82,7 +82,7 @@ func (h *sendQueue) Run() error { // 1. Checking for "datagram too large" message from the kernel, as such, // 2. Path MTU discovery,and // 3. Eventual detection of loss PingFrame. - if !isMsgSizeErr(err) { + if !isSendMsgSizeErr(err) { return err } } diff --git a/sys_conn_df.go b/sys_conn_df.go index b90a13da..0db61509 100644 --- a/sys_conn_df.go +++ b/sys_conn_df.go @@ -11,7 +11,12 @@ func setDF(syscall.RawConn) (bool, error) { return false, nil } -func isMsgSizeErr(err error) bool { +func isSendMsgSizeErr(err error) bool { + // to be implemented for more specific platforms + return false +} + +func isRecvMsgSizeErr(err error) bool { // to be implemented for more specific platforms return false } diff --git a/sys_conn_df_darwin.go b/sys_conn_df_darwin.go index e3a9b77f..b51cd8f1 100644 --- a/sys_conn_df_darwin.go +++ b/sys_conn_df_darwin.go @@ -47,10 +47,12 @@ func setDF(rawConn syscall.RawConn) (bool, error) { return true, nil } -func isMsgSizeErr(err error) bool { +func isSendMsgSizeErr(err error) bool { return errors.Is(err, unix.EMSGSIZE) } +func isRecvMsgSizeErr(error) bool { return false } + func isAtLeastMacOS11() (bool, error) { uname := &unix.Utsname{} err := unix.Uname(uname) diff --git a/sys_conn_df_linux.go b/sys_conn_df_linux.go index abd64dd9..199f6347 100644 --- a/sys_conn_df_linux.go +++ b/sys_conn_df_linux.go @@ -57,11 +57,13 @@ func maybeSetGSO(rawConn syscall.RawConn) bool { return true } -func isMsgSizeErr(err error) bool { +func isSendMsgSizeErr(err error) bool { // https://man7.org/linux/man-pages/man7/udp.7.html return errors.Is(err, unix.EMSGSIZE) } +func isRecvMsgSizeErr(err error) bool { return false } + func appendUDPSegmentSizeMsg(b []byte, size uint16) []byte { startLen := len(b) const dataLen = 2 // payload is a uint16 diff --git a/sys_conn_df_windows.go b/sys_conn_df_windows.go index a7f1351a..e27635ec 100644 --- a/sys_conn_df_windows.go +++ b/sys_conn_df_windows.go @@ -43,7 +43,12 @@ func setDF(rawConn syscall.RawConn) (bool, error) { return true, nil } -func isMsgSizeErr(err error) bool { +func isSendMsgSizeErr(err error) bool { + // https://docs.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2 + return errors.Is(err, windows.WSAEMSGSIZE) +} + +func isRecvMsgSizeErr(err error) bool { // https://docs.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2 return errors.Is(err, windows.WSAEMSGSIZE) } diff --git a/transport.go b/transport.go index 3c985965..290b647f 100644 --- a/transport.go +++ b/transport.go @@ -330,6 +330,10 @@ func (t *Transport) listen(conn rawConn) { continue } if err != nil { + // Windows returns an error when receiving a UDP datagram that doesn't fit into the provided buffer. + if isRecvMsgSizeErr(err) { + continue + } t.close(err) return }