Allow non blocking UDP put_packet in C++.
- Add blocking mode option to PacketPeerUDP.
- put_packet returns ERR_UNAVAILABLE when operation would block.
- ENet module uses non-blocking UDP.
(cherry picked from commit 5f681d0b0f
)
This commit is contained in:
parent
05d83a62c6
commit
bd26eacc59
|
@ -32,6 +32,11 @@
|
|||
|
||||
PacketPeerUDP *(*PacketPeerUDP::_create)() = NULL;
|
||||
|
||||
void PacketPeerUDP::set_blocking_mode(bool p_enable) {
|
||||
|
||||
blocking = p_enable;
|
||||
}
|
||||
|
||||
String PacketPeerUDP::_get_packet_ip() const {
|
||||
|
||||
return get_packet_address();
|
||||
|
@ -79,4 +84,6 @@ PacketPeerUDP *PacketPeerUDP::create() {
|
|||
}
|
||||
|
||||
PacketPeerUDP::PacketPeerUDP() {
|
||||
|
||||
blocking = true;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@ class PacketPeerUDP : public PacketPeer {
|
|||
OBJ_TYPE(PacketPeerUDP, PacketPeer);
|
||||
|
||||
protected:
|
||||
bool blocking;
|
||||
|
||||
static PacketPeerUDP *(*_create)();
|
||||
static void _bind_methods();
|
||||
|
||||
|
@ -45,6 +47,8 @@ protected:
|
|||
Error _set_send_address(const String &p_address, int p_port);
|
||||
|
||||
public:
|
||||
void set_blocking_mode(bool p_enable);
|
||||
|
||||
virtual Error listen(int p_port, IP_Address p_bind_address = IP_Address("*"), int p_recv_buffer_size = 65536) = 0;
|
||||
virtual void close() = 0;
|
||||
virtual Error wait() = 0;
|
||||
|
|
|
@ -108,10 +108,14 @@ Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer, int p_buffer_size)
|
|||
errno = 0;
|
||||
int err;
|
||||
|
||||
_set_sock_blocking(blocking);
|
||||
|
||||
while ((err = sendto(sock, p_buffer, p_buffer_size, 0, (struct sockaddr *)&addr, addr_size)) != p_buffer_size) {
|
||||
|
||||
if (errno != EAGAIN) {
|
||||
return FAILED;
|
||||
} else if (!blocking) {
|
||||
return ERR_UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,10 +178,12 @@ Error PacketPeerUDPPosix::_poll(bool p_wait) {
|
|||
return FAILED;
|
||||
}
|
||||
|
||||
_set_sock_blocking(p_wait);
|
||||
|
||||
struct sockaddr_storage from = { 0 };
|
||||
socklen_t len = sizeof(struct sockaddr_storage);
|
||||
int ret;
|
||||
while ((ret = recvfrom(sockfd, recv_buffer, MIN((int)sizeof(recv_buffer), MAX(rb.space_left() - 24, 0)), p_wait ? 0 : MSG_DONTWAIT, (struct sockaddr *)&from, &len)) > 0) {
|
||||
while ((ret = recvfrom(sockfd, recv_buffer, MIN((int)sizeof(recv_buffer), MAX(rb.space_left() - 24, 0)), 0, (struct sockaddr *)&from, &len)) > 0) {
|
||||
|
||||
uint32_t port = 0;
|
||||
|
||||
|
@ -244,9 +250,35 @@ int PacketPeerUDPPosix::_get_socket() {
|
|||
|
||||
sockfd = _socket_create(sock_type, SOCK_DGRAM, IPPROTO_UDP);
|
||||
|
||||
if (sockfd != -1)
|
||||
_set_sock_blocking(false);
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
void PacketPeerUDPPosix::_set_sock_blocking(bool p_blocking) {
|
||||
|
||||
if (sock_blocking == p_blocking)
|
||||
return;
|
||||
|
||||
sock_blocking = p_blocking;
|
||||
|
||||
#ifndef NO_FCNTL
|
||||
int opts = fcntl(sockfd, F_GETFL);
|
||||
int ret = 0;
|
||||
if (sock_blocking)
|
||||
ret = fcntl(sockfd, F_SETFL, opts & ~O_NONBLOCK);
|
||||
else
|
||||
ret = fcntl(sockfd, F_SETFL, opts | O_NONBLOCK);
|
||||
if (ret == -1)
|
||||
perror("setting non-block mode");
|
||||
#else
|
||||
int bval = sock_blocking ? 0 : 1;
|
||||
if (ioctl(sockfd, FIONBIO, &bval) == -1)
|
||||
perror("setting non-block mode");
|
||||
#endif
|
||||
}
|
||||
|
||||
void PacketPeerUDPPosix::set_send_address(const IP_Address &p_address, int p_port) {
|
||||
|
||||
peer_addr = p_address;
|
||||
|
@ -265,6 +297,8 @@ void PacketPeerUDPPosix::make_default() {
|
|||
|
||||
PacketPeerUDPPosix::PacketPeerUDPPosix() {
|
||||
|
||||
blocking = true;
|
||||
sock_blocking = true;
|
||||
sockfd = -1;
|
||||
packet_port = 0;
|
||||
queue_count = 0;
|
||||
|
|
|
@ -48,6 +48,7 @@ class PacketPeerUDPPosix : public PacketPeerUDP {
|
|||
mutable int packet_port;
|
||||
mutable int queue_count;
|
||||
int sockfd;
|
||||
bool sock_blocking;
|
||||
IP::Type sock_type;
|
||||
|
||||
IP_Address peer_addr;
|
||||
|
@ -56,6 +57,7 @@ class PacketPeerUDPPosix : public PacketPeerUDP {
|
|||
_FORCE_INLINE_ int _get_socket();
|
||||
|
||||
static PacketPeerUDP *_create();
|
||||
void _set_sock_blocking(bool p_blocking);
|
||||
virtual Error _poll(bool p_block);
|
||||
|
||||
public:
|
||||
|
|
|
@ -83,7 +83,7 @@ Error PacketPeerUDPWinsock::put_packet(const uint8_t *p_buffer, int p_buffer_siz
|
|||
struct sockaddr_storage addr;
|
||||
size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port, sock_type);
|
||||
|
||||
_set_blocking(true);
|
||||
_set_sock_blocking(blocking);
|
||||
|
||||
errno = 0;
|
||||
int err;
|
||||
|
@ -91,7 +91,9 @@ Error PacketPeerUDPWinsock::put_packet(const uint8_t *p_buffer, int p_buffer_siz
|
|||
|
||||
if (WSAGetLastError() != WSAEWOULDBLOCK) {
|
||||
return FAILED;
|
||||
};
|
||||
} else if (!blocking) {
|
||||
return ERR_UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
@ -102,15 +104,13 @@ int PacketPeerUDPWinsock::get_max_packet_size() const {
|
|||
return 512; // uhm maybe not
|
||||
}
|
||||
|
||||
void PacketPeerUDPWinsock::_set_blocking(bool p_blocking) {
|
||||
//am no windows expert
|
||||
//hope this is the right thing
|
||||
void PacketPeerUDPWinsock::_set_sock_blocking(bool p_blocking) {
|
||||
|
||||
if (blocking == p_blocking)
|
||||
if (sock_blocking == p_blocking)
|
||||
return;
|
||||
|
||||
blocking = p_blocking;
|
||||
unsigned long par = blocking ? 0 : 1;
|
||||
sock_blocking = p_blocking;
|
||||
unsigned long par = sock_blocking ? 0 : 1;
|
||||
if (ioctlsocket(sockfd, FIONBIO, &par)) {
|
||||
perror("setting non-block mode");
|
||||
//close();
|
||||
|
@ -140,8 +140,6 @@ Error PacketPeerUDPWinsock::listen(int p_port, IP_Address p_bind_address, int p_
|
|||
return ERR_UNAVAILABLE;
|
||||
}
|
||||
|
||||
blocking = true;
|
||||
|
||||
printf("UDP Connection listening on port %i\n", p_port);
|
||||
rb.resize(nearest_shift(p_recv_buffer_size));
|
||||
return OK;
|
||||
|
@ -167,7 +165,7 @@ Error PacketPeerUDPWinsock::_poll(bool p_wait) {
|
|||
return FAILED;
|
||||
}
|
||||
|
||||
_set_blocking(p_wait);
|
||||
_set_sock_blocking(p_wait);
|
||||
|
||||
struct sockaddr_storage from = { 0 };
|
||||
int len = sizeof(struct sockaddr_storage);
|
||||
|
@ -253,6 +251,9 @@ int PacketPeerUDPWinsock::_get_socket() {
|
|||
|
||||
sockfd = _socket_create(sock_type, SOCK_DGRAM, IPPROTO_UDP);
|
||||
|
||||
if (sockfd != -1)
|
||||
_set_sock_blocking(false);
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
|
@ -274,6 +275,8 @@ PacketPeerUDP *PacketPeerUDPWinsock::_create() {
|
|||
|
||||
PacketPeerUDPWinsock::PacketPeerUDPWinsock() {
|
||||
|
||||
blocking = true;
|
||||
sock_blocking = true;
|
||||
sockfd = -1;
|
||||
packet_port = 0;
|
||||
queue_count = 0;
|
||||
|
|
|
@ -46,6 +46,7 @@ class PacketPeerUDPWinsock : public PacketPeerUDP {
|
|||
mutable int packet_port;
|
||||
mutable int queue_count;
|
||||
int sockfd;
|
||||
bool sock_blocking;
|
||||
IP::Type sock_type;
|
||||
|
||||
IP_Address peer_addr;
|
||||
|
@ -55,8 +56,7 @@ class PacketPeerUDPWinsock : public PacketPeerUDP {
|
|||
|
||||
static PacketPeerUDP *_create();
|
||||
|
||||
bool blocking;
|
||||
void _set_blocking(bool p_blocking);
|
||||
void _set_sock_blocking(bool p_blocking);
|
||||
|
||||
Error _poll(bool p_wait);
|
||||
|
||||
|
|
Loading…
Reference in New Issue