You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-07 12:30:27 +00:00
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.
This commit is contained in:
@@ -31,6 +31,11 @@
|
|||||||
|
|
||||||
PacketPeerUDP *(*PacketPeerUDP::_create)() = NULL;
|
PacketPeerUDP *(*PacketPeerUDP::_create)() = NULL;
|
||||||
|
|
||||||
|
void PacketPeerUDP::set_blocking_mode(bool p_enable) {
|
||||||
|
|
||||||
|
blocking = p_enable;
|
||||||
|
}
|
||||||
|
|
||||||
String PacketPeerUDP::_get_packet_ip() const {
|
String PacketPeerUDP::_get_packet_ip() const {
|
||||||
|
|
||||||
return get_packet_address();
|
return get_packet_address();
|
||||||
@@ -78,4 +83,6 @@ PacketPeerUDP *PacketPeerUDP::create() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PacketPeerUDP::PacketPeerUDP() {
|
PacketPeerUDP::PacketPeerUDP() {
|
||||||
|
|
||||||
|
blocking = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ class PacketPeerUDP : public PacketPeer {
|
|||||||
GDCLASS(PacketPeerUDP, PacketPeer);
|
GDCLASS(PacketPeerUDP, PacketPeer);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool blocking;
|
||||||
|
|
||||||
static PacketPeerUDP *(*_create)();
|
static PacketPeerUDP *(*_create)();
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
@@ -44,6 +46,8 @@ protected:
|
|||||||
Error _set_dest_address(const String &p_address, int p_port);
|
Error _set_dest_address(const String &p_address, int p_port);
|
||||||
|
|
||||||
public:
|
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 Error listen(int p_port, IP_Address p_bind_address = IP_Address("*"), int p_recv_buffer_size = 65536) = 0;
|
||||||
virtual void close() = 0;
|
virtual void close() = 0;
|
||||||
virtual Error wait() = 0;
|
virtual Error wait() = 0;
|
||||||
|
|||||||
@@ -107,10 +107,14 @@ Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer, int p_buffer_size)
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
_set_sock_blocking(blocking);
|
||||||
|
|
||||||
while ((err = sendto(sock, p_buffer, p_buffer_size, 0, (struct sockaddr *)&addr, addr_size)) != p_buffer_size) {
|
while ((err = sendto(sock, p_buffer, p_buffer_size, 0, (struct sockaddr *)&addr, addr_size)) != p_buffer_size) {
|
||||||
|
|
||||||
if (errno != EAGAIN) {
|
if (errno != EAGAIN) {
|
||||||
return FAILED;
|
return FAILED;
|
||||||
|
} else if (!blocking) {
|
||||||
|
return ERR_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,10 +177,12 @@ Error PacketPeerUDPPosix::_poll(bool p_wait) {
|
|||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_set_sock_blocking(p_wait);
|
||||||
|
|
||||||
struct sockaddr_storage from = { 0 };
|
struct sockaddr_storage from = { 0 };
|
||||||
socklen_t len = sizeof(struct sockaddr_storage);
|
socklen_t len = sizeof(struct sockaddr_storage);
|
||||||
int ret;
|
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;
|
uint32_t port = 0;
|
||||||
|
|
||||||
@@ -243,9 +249,35 @@ int PacketPeerUDPPosix::_get_socket() {
|
|||||||
|
|
||||||
sockfd = _socket_create(sock_type, SOCK_DGRAM, IPPROTO_UDP);
|
sockfd = _socket_create(sock_type, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
|
||||||
|
if (sockfd != -1)
|
||||||
|
_set_sock_blocking(false);
|
||||||
|
|
||||||
return sockfd;
|
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_dest_address(const IP_Address &p_address, int p_port) {
|
void PacketPeerUDPPosix::set_dest_address(const IP_Address &p_address, int p_port) {
|
||||||
|
|
||||||
peer_addr = p_address;
|
peer_addr = p_address;
|
||||||
@@ -264,6 +296,8 @@ void PacketPeerUDPPosix::make_default() {
|
|||||||
|
|
||||||
PacketPeerUDPPosix::PacketPeerUDPPosix() {
|
PacketPeerUDPPosix::PacketPeerUDPPosix() {
|
||||||
|
|
||||||
|
blocking = true;
|
||||||
|
sock_blocking = true;
|
||||||
sockfd = -1;
|
sockfd = -1;
|
||||||
packet_port = 0;
|
packet_port = 0;
|
||||||
queue_count = 0;
|
queue_count = 0;
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ class PacketPeerUDPPosix : public PacketPeerUDP {
|
|||||||
mutable int packet_port;
|
mutable int packet_port;
|
||||||
mutable int queue_count;
|
mutable int queue_count;
|
||||||
int sockfd;
|
int sockfd;
|
||||||
|
bool sock_blocking;
|
||||||
IP::Type sock_type;
|
IP::Type sock_type;
|
||||||
|
|
||||||
IP_Address peer_addr;
|
IP_Address peer_addr;
|
||||||
@@ -55,6 +56,7 @@ class PacketPeerUDPPosix : public PacketPeerUDP {
|
|||||||
_FORCE_INLINE_ int _get_socket();
|
_FORCE_INLINE_ int _get_socket();
|
||||||
|
|
||||||
static PacketPeerUDP *_create();
|
static PacketPeerUDP *_create();
|
||||||
|
void _set_sock_blocking(bool p_blocking);
|
||||||
virtual Error _poll(bool p_block);
|
virtual Error _poll(bool p_block);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ Error PacketPeerUDPWinsock::put_packet(const uint8_t *p_buffer, int p_buffer_siz
|
|||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port, sock_type);
|
size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port, sock_type);
|
||||||
|
|
||||||
_set_blocking(true);
|
_set_sock_blocking(blocking);
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
int err;
|
int err;
|
||||||
@@ -90,7 +90,9 @@ Error PacketPeerUDPWinsock::put_packet(const uint8_t *p_buffer, int p_buffer_siz
|
|||||||
|
|
||||||
if (WSAGetLastError() != WSAEWOULDBLOCK) {
|
if (WSAGetLastError() != WSAEWOULDBLOCK) {
|
||||||
return FAILED;
|
return FAILED;
|
||||||
};
|
} else if (!blocking) {
|
||||||
|
return ERR_UNAVAILABLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
@@ -101,15 +103,13 @@ int PacketPeerUDPWinsock::get_max_packet_size() const {
|
|||||||
return 512; // uhm maybe not
|
return 512; // uhm maybe not
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketPeerUDPWinsock::_set_blocking(bool p_blocking) {
|
void PacketPeerUDPWinsock::_set_sock_blocking(bool p_blocking) {
|
||||||
//am no windows expert
|
|
||||||
//hope this is the right thing
|
|
||||||
|
|
||||||
if (blocking == p_blocking)
|
if (sock_blocking == p_blocking)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
blocking = p_blocking;
|
sock_blocking = p_blocking;
|
||||||
unsigned long par = blocking ? 0 : 1;
|
unsigned long par = sock_blocking ? 0 : 1;
|
||||||
if (ioctlsocket(sockfd, FIONBIO, &par)) {
|
if (ioctlsocket(sockfd, FIONBIO, &par)) {
|
||||||
perror("setting non-block mode");
|
perror("setting non-block mode");
|
||||||
//close();
|
//close();
|
||||||
@@ -139,8 +139,6 @@ Error PacketPeerUDPWinsock::listen(int p_port, IP_Address p_bind_address, int p_
|
|||||||
return ERR_UNAVAILABLE;
|
return ERR_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
blocking = true;
|
|
||||||
|
|
||||||
printf("UDP Connection listening on port %i\n", p_port);
|
printf("UDP Connection listening on port %i\n", p_port);
|
||||||
rb.resize(nearest_shift(p_recv_buffer_size));
|
rb.resize(nearest_shift(p_recv_buffer_size));
|
||||||
return OK;
|
return OK;
|
||||||
@@ -166,7 +164,7 @@ Error PacketPeerUDPWinsock::_poll(bool p_wait) {
|
|||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
_set_blocking(p_wait);
|
_set_sock_blocking(p_wait);
|
||||||
|
|
||||||
struct sockaddr_storage from = { 0 };
|
struct sockaddr_storage from = { 0 };
|
||||||
int len = sizeof(struct sockaddr_storage);
|
int len = sizeof(struct sockaddr_storage);
|
||||||
@@ -252,6 +250,9 @@ int PacketPeerUDPWinsock::_get_socket() {
|
|||||||
|
|
||||||
sockfd = _socket_create(sock_type, SOCK_DGRAM, IPPROTO_UDP);
|
sockfd = _socket_create(sock_type, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
|
||||||
|
if (sockfd != -1)
|
||||||
|
_set_sock_blocking(false);
|
||||||
|
|
||||||
return sockfd;
|
return sockfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,6 +274,8 @@ PacketPeerUDP *PacketPeerUDPWinsock::_create() {
|
|||||||
|
|
||||||
PacketPeerUDPWinsock::PacketPeerUDPWinsock() {
|
PacketPeerUDPWinsock::PacketPeerUDPWinsock() {
|
||||||
|
|
||||||
|
blocking = true;
|
||||||
|
sock_blocking = true;
|
||||||
sockfd = -1;
|
sockfd = -1;
|
||||||
packet_port = 0;
|
packet_port = 0;
|
||||||
queue_count = 0;
|
queue_count = 0;
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ class PacketPeerUDPWinsock : public PacketPeerUDP {
|
|||||||
mutable int packet_port;
|
mutable int packet_port;
|
||||||
mutable int queue_count;
|
mutable int queue_count;
|
||||||
int sockfd;
|
int sockfd;
|
||||||
|
bool sock_blocking;
|
||||||
IP::Type sock_type;
|
IP::Type sock_type;
|
||||||
|
|
||||||
IP_Address peer_addr;
|
IP_Address peer_addr;
|
||||||
@@ -54,8 +55,7 @@ class PacketPeerUDPWinsock : public PacketPeerUDP {
|
|||||||
|
|
||||||
static PacketPeerUDP *_create();
|
static PacketPeerUDP *_create();
|
||||||
|
|
||||||
bool blocking;
|
void _set_sock_blocking(bool p_blocking);
|
||||||
void _set_blocking(bool p_blocking);
|
|
||||||
|
|
||||||
Error _poll(bool p_wait);
|
Error _poll(bool p_wait);
|
||||||
|
|
||||||
|
|||||||
10
thirdparty/enet/godot.cpp
vendored
10
thirdparty/enet/godot.cpp
vendored
@@ -79,7 +79,10 @@ int enet_socket_bind(ENetSocket socket, const ENetAddress *address) {
|
|||||||
|
|
||||||
ENetSocket enet_socket_create(ENetSocketType type) {
|
ENetSocket enet_socket_create(ENetSocketType type) {
|
||||||
|
|
||||||
return PacketPeerUDP::create();
|
PacketPeerUDP *socket = PacketPeerUDP::create();
|
||||||
|
socket->set_blocking_mode(false);
|
||||||
|
|
||||||
|
return socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
void enet_socket_destroy(ENetSocket socket) {
|
void enet_socket_destroy(ENetSocket socket) {
|
||||||
@@ -118,6 +121,11 @@ int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBu
|
|||||||
|
|
||||||
err = sock->put_packet((const uint8_t *)&w[0], size);
|
err = sock->put_packet((const uint8_t *)&w[0], size);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
|
|
||||||
|
if (err == ERR_UNAVAILABLE) { // blocking call
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
WARN_PRINT("Sending failed!");
|
WARN_PRINT("Sending failed!");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user