NET: Add SO_RCVBUF / SO_SNDBUF defaults to .._bnet_socket

The OS defaults for SO_RCVBUF / SO_SNDBUF may not match what the defaults for the PS3 are.
And the code may be happy with the PS3 defaults, so may not set this explicitly.
So we'll do it when we establish the socket.
It also looks like the Windows recv behaviour is different for the MSG_PEEK option (and possibly in all situations where a smaller buffer is provided). I believe other platforms will return the size of the data received into the socket buffer, even if the supplied user buffer is smaller. Windows returns WSAEMSGSIZE instead. For the length of '1' MSG_PEEK request that is currently seen, we just mask this and return the full size of the buffer. This might need to be the case in all situations, I assume there will be applications that will supply an artificially small buffer and resize it as necessary based on the size of the received packet.
Add some additional translations from native->PS3 error codes

Rewrote handling of MSG_PEEK to just be a copy of what GalCiv suggested
Added WSAESHUTDOWN, and WSASetLastError as done by Cygwin
This commit is contained in:
Bevan Weiss 2020-10-25 22:02:57 +11:00 committed by Ivan
parent e791678dfc
commit f4070731a8

View File

@ -200,21 +200,56 @@ static sys_net_error get_last_error(bool is_blocking, int native_error = 0)
}
#ifdef _WIN32
switch (native_error)
#define ERROR_CASE(error) case WSA ## error: result = SYS_NET_ ## error; name = #error; break;
#else
switch (native_error)
#define ERROR_CASE(error) case error: result = SYS_NET_ ## error; name = #error; break;
#endif
switch (native_error)
{
#ifndef _WIN32
ERROR_CASE(ENOENT);
ERROR_CASE(ENOMEM);
ERROR_CASE(EBUSY);
ERROR_CASE(ENOSPC);
#endif
// TODO: We don't currently support EFAULT or EINTR
//ERROR_CASE(EFAULT);
//ERROR_CASE(EINTR);
ERROR_CASE(EBADF);
ERROR_CASE(EACCES);
ERROR_CASE(EINVAL);
ERROR_CASE(EMFILE);
ERROR_CASE(EPIPE);
ERROR_CASE(EWOULDBLOCK);
ERROR_CASE(EINPROGRESS);
ERROR_CASE(EALREADY);
ERROR_CASE(ENOTCONN);
ERROR_CASE(ECONNRESET);
ERROR_CASE(EDESTADDRREQ);
ERROR_CASE(EMSGSIZE);
ERROR_CASE(EPROTOTYPE);
ERROR_CASE(ENOPROTOOPT);
ERROR_CASE(EPROTONOSUPPORT);
ERROR_CASE(EOPNOTSUPP);
ERROR_CASE(EPFNOSUPPORT);
ERROR_CASE(EAFNOSUPPORT);
ERROR_CASE(EADDRINUSE);
ERROR_CASE(EADDRNOTAVAIL);
ERROR_CASE(ENETDOWN);
ERROR_CASE(ENETUNREACH);
ERROR_CASE(ECONNABORTED);
ERROR_CASE(ECONNRESET);
ERROR_CASE(ENOBUFS);
ERROR_CASE(EISCONN);
default: sys_net.error("Unknown/illegal socket error: %d", native_error);
ERROR_CASE(ENOTCONN);
ERROR_CASE(ESHUTDOWN);
ERROR_CASE(ETOOMANYREFS);
ERROR_CASE(ETIMEDOUT);
ERROR_CASE(ECONNREFUSED);
ERROR_CASE(EHOSTDOWN);
ERROR_CASE(EHOSTUNREACH);
default:
fmt::throw_exception("sys_net get_last_error(is_blocking=%d, native_error=%d): Unknown/illegal socket error", is_blocking, native_error);
}
if (name && result != SYS_NET_EWOULDBLOCK && result != SYS_NET_EINPROGRESS)
@ -2269,6 +2304,23 @@ error_code sys_net_bnet_recvfrom(ppu_thread& ppu, s32 s, vm::ptr<void> buf, u32
return true;
}
#ifdef _WIN32
else
{
// Windows returns an error when trying to peek at a message and buffer not long enough to contain the whole message, should be ignored
if ((native_flags & MSG_PEEK) && get_native_error() == WSAEMSGSIZE)
{
native_result = len;
return true;
}
// Windows will return WSASHUTDOWN when the connection is shutdown, POSIX just returns EOF (0) in this situation.
if( get_native_error() == WSAESHUTDOWN)
{
native_result = 0;
return true;
}
}
#endif
result = get_last_error(!sock.so_nbio && (flags & SYS_NET_MSG_DONTWAIT) == 0);
@ -2939,6 +2991,12 @@ error_code sys_net_bnet_socket(ppu_thread& ppu, s32 family, s32 type, s32 protoc
{
return -get_last_error(false);
}
u32 default_RCVBUF = (type==SYS_NET_SOCK_STREAM) ? 65535 : 9216;
if (setsockopt(native_socket, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<const char*>(&default_RCVBUF), sizeof(default_RCVBUF)) != 0)
sys_net.error("Error setting defalult SO_RCVBUF on sys_net_bnet_socket socket");
u32 default_SNDBUF = 131072;
if (setsockopt(native_socket, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<const char*>(&default_SNDBUF), sizeof(default_SNDBUF)) != 0)
sys_net.error("Error setting default SO_SNDBUF on sys_net_bnet_socket socket");
}
auto sock_lv2 = std::make_shared<lv2_socket>(native_socket, type, family);