New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
socket.recvfrom crops UDP packets #3619
Comments
When size parameter is not passed to socket:recv() or socket:recvfrom() it will call recv(fd, NULL, 0 , MSG_TRUNC | MSG_PEEK) on the socket to evaluate size of the buffer to store the receiving datagram. Before this commit a datagram will be cropped to 512 bytes in the case. Added socket:is_udp() and socket:dgram_length() methods to the public API. Part of #3619.
When size parameter is not passed to socket:recv() or socket:recvfrom() it will call recv(fd, NULL, 0 , MSG_TRUNC | MSG_PEEK) on the socket to evaluate size of the buffer to store the receiving datagram. Before this commit a datagram will be cropped to 512 bytes in the case. Added socket:is_udp() and socket:dgram_length() methods to the public API. Part of #3619.
We set MSG_TRUNC for recv / recvfrom calls to receive the real length of the datagram. When the datagram length is larger then the buffer size we set the EMSGSIZE errno, but still return `from` table (in case of recvfrom). Fixes #3619.
When size parameter is not passed to socket:recv() or socket:recvfrom() it will call recv(fd, NULL, 0 , MSG_TRUNC | MSG_PEEK) on the socket to evaluate size of the buffer to store the receiving datagram. Before this commit a datagram will be cropped to 512 bytes in the case. Added socket:is_udp() and socket:dgram_length() methods to the public API. Part of #3619.
We set MSG_TRUNC for recv / recvfrom calls to receive the real length of the datagram. When the datagram length is larger then the buffer size we set the EMSGSIZE errno, but still return `from` table (in case of recvfrom). Fixes #3619.
When size parameter is not passed to socket:recv() or socket:recvfrom() it will call a) or b) on the socket to evaluate size of the buffer to store the receiving datagram. Before this commit a datagram will be truncated to 512 bytes in the case. a) Linux: recv(fd, NULL, 0 , MSG_TRUNC | MSG_PEEK) b) Mac OS: getsockopt(fd, SOL_SOCKET, SO_NREAD, &val, &len) It is recommended to set 'size' parameter (size of the input buffer) explicitly based on known message format and known network conditions (say, set it less then MTU to prevent IP fragmentation, which can be inefficient) or pass it from a configuration option of a library / an application. The reason is that explicit buffer size provided allows to avoid extra recv syscall on Linux. Added socket:is_udp() and socket:dgram_length() methods to the public API. Part of #3619.
When the datagram length is larger then the buffer size we discard the datagram, return nil as the message, set errno to EMSGSIZE, but still return `from` table (in case of recvfrom). The commit changes behaviour of socket:recv and socket:recvfrom methods in case of a UDP socket. They still truncate the input in case of a TCP socket (because of stream nature of TCP). On Linux we set MSG_TRUNC for recv / recvfrom calls to receive the real length of the datagram. On Mac OS we call getsockopt(fd, SOL_SOCKET, SO_NREAD, &val, &len) before the recv / recvfrom call. These extra steps are avoided for TCP sockets, because MSG_TRUNC leads to discarding the input (Linux) and to avoid extra getsockopt syscall (Mac OS). Fixes #3619.
When size parameter is not passed to socket:recv() or socket:recvfrom() it will call a) or b) on the socket to evaluate size of the buffer to store the receiving datagram. Before this commit a datagram will be truncated to 512 bytes in the case. a) Linux: recv(fd, NULL, 0 , MSG_TRUNC | MSG_PEEK) b) Mac OS: getsockopt(fd, SOL_SOCKET, SO_NREAD, &val, &len) It is recommended to set 'size' parameter (size of the input buffer) explicitly based on known message format and known network conditions (say, set it less then MTU to prevent IP fragmentation, which can be inefficient) or pass it from a configuration option of a library / an application. The reason is that explicit buffer size provided allows to avoid extra syscall to evaluate necessary buffer size. When 'size' parameter is set explicitly for recv / recvfrom on a UDP socket and the next datagram length is larger then the size, the returned message will be truncated to the size provided and the rest of the datagram will be discarded. Of course, the tail will not be discarded in case of a TCP socket and will be available to read by the next recv / recvfrom call. Fixes #3619.
Decided to:
Cite from the Yaroslav's (@rosik) message:
|
@TarantoolBot document
Feel free to ask more informatiom from @Totktonada. |
@Totktonada: Accept. |
When size parameter is not passed to socket:recv() or socket:recvfrom() it will call a) or b) on the socket to evaluate size of the buffer to store the receiving datagram. Before this commit a datagram will be truncated to 512 bytes in the case. a) Linux: recv(fd, NULL, 0 , MSG_TRUNC | MSG_PEEK) b) Mac OS: getsockopt(fd, SOL_SOCKET, SO_NREAD, &val, &len) It is recommended to set 'size' parameter (size of the input buffer) explicitly based on known message format and known network conditions (say, set it less then MTU to prevent IP fragmentation, which can be inefficient) or pass it from a configuration option of a library / an application. The reason is that explicit buffer size provided allows to avoid extra syscall to evaluate necessary buffer size. When 'size' parameter is set explicitly for recv / recvfrom on a UDP socket and the next datagram length is larger then the size, the returned message will be truncated to the size provided and the rest of the datagram will be discarded. Of course, the tail will not be discarded in case of a TCP socket and will be available to read by the next recv / recvfrom call. Fixes #3619.
When size parameter is not passed to socket:recv() or socket:recvfrom() it will call a) or b) on the socket to evaluate size of the buffer to store the receiving datagram. Before this commit a datagram will be truncated to 512 bytes in the case. a) Linux: recv(fd, NULL, 0 , MSG_TRUNC | MSG_PEEK) b) Mac OS: getsockopt(fd, SOL_SOCKET, SO_NREAD, &val, &len) It is recommended to set 'size' parameter (size of the input buffer) explicitly based on known message format and known network conditions (say, set it less then MTU to prevent IP fragmentation, which can be inefficient) or pass it from a configuration option of a library / an application. The reason is that explicit buffer size provided allows to avoid extra syscall to evaluate necessary buffer size. When 'size' parameter is set explicitly for recv / recvfrom on a UDP socket and the next datagram length is larger then the size, the returned message will be truncated to the size provided and the rest of the datagram will be discarded. Of course, the tail will not be discarded in case of a TCP socket and will be available to read by the next recv / recvfrom call. Fixes #3619.
When size parameter is not passed to socket:recv() or socket:recvfrom() it will call a) or b) on the socket to evaluate size of the buffer to store the receiving datagram. Before this commit a datagram will be truncated to 512 bytes in the case. a) Linux: recv(fd, NULL, 0 , MSG_TRUNC | MSG_PEEK) b) Mac OS: getsockopt(fd, SOL_SOCKET, SO_NREAD, &val, &len) It is recommended to set 'size' parameter (size of the input buffer) explicitly based on known message format and known network conditions (say, set it less then MTU to prevent IP fragmentation, which can be inefficient) or pass it from a configuration option of a library / an application. The reason is that explicit buffer size provided allows to avoid extra syscall to evaluate necessary buffer size. When 'size' parameter is set explicitly for recv / recvfrom on a UDP socket and the next datagram length is larger then the size, the returned message will be truncated to the size provided and the rest of the datagram will be discarded. Of course, the tail will not be discarded in case of a TCP socket and will be available to read by the next recv / recvfrom call. Fixes #3619.
When size parameter is not passed to socket:recv() or socket:recvfrom() it will call a) or b) on the socket to evaluate size of the buffer to store the receiving datagram. Before this commit a datagram will be truncated to 512 bytes in the case. a) Linux: recv(fd, NULL, 0 , MSG_TRUNC | MSG_PEEK) b) Mac OS: getsockopt(fd, SOL_SOCKET, SO_NREAD, &val, &len) It is recommended to set 'size' parameter (size of the input buffer) explicitly based on known message format and known network conditions (say, set it less then MTU to prevent IP fragmentation, which can be inefficient) or pass it from a configuration option of a library / an application. The reason is that explicit buffer size provided allows to avoid extra syscall to evaluate necessary buffer size. When 'size' parameter is set explicitly for recv / recvfrom on a UDP socket and the next datagram length is larger then the size, the returned message will be truncated to the size provided and the rest of the datagram will be discarded. Of course, the tail will not be discarded in case of a TCP socket and will be available to read by the next recv / recvfrom call. Fixes #3619.
When size parameter is not passed to socket:recv() or socket:recvfrom() it will call a) or b) on the socket to evaluate size of the buffer to store the receiving datagram. Before this commit a datagram will be truncated to 512 bytes in the case. a) Linux: recv(fd, NULL, 0 , MSG_TRUNC | MSG_PEEK) b) Mac OS: getsockopt(fd, SOL_SOCKET, SO_NREAD, &val, &len) It is recommended to set 'size' parameter (size of the input buffer) explicitly based on known message format and known network conditions (say, set it less then MTU to prevent IP fragmentation, which can be inefficient) or pass it from a configuration option of a library / an application. The reason is that explicit buffer size provided allows to avoid extra syscall to evaluate necessary buffer size. When 'size' parameter is set explicitly for recv / recvfrom on a UDP socket and the next datagram length is larger then the size, the returned message will be truncated to the size provided and the rest of the datagram will be discarded. Of course, the tail will not be discarded in case of a TCP socket and will be available to read by the next recv / recvfrom call. Fixes #3619.
Fixed by 11fb3ab |
Here is a reproducer
The output is
The problem is that the message is being cropped by 512 bytes by default (https://github.com/tarantool/tarantool/blob/2.0/src/lua/socket.lua#L802)
And I can not receive large packets in multiple reads.
The text was updated successfully, but these errors were encountered: