summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabio Alessandrelli <fabio.alessandrelli@gmail.com>2017-03-08 17:14:01 +0100
committerFabio Alessandrelli <fabio.alessandrelli@gmail.com>2017-03-24 02:30:11 +0100
commit5f681d0b0f28cd39bc033c0cdf8eb3cb3a4acbe6 (patch)
tree5c94a8cc2537076223598b4007943e436cf750b4
parent38d457170a15fd9eb902cecc8c5dc401646cd0b8 (diff)
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.
-rw-r--r--core/io/packet_peer_udp.cpp7
-rw-r--r--core/io/packet_peer_udp.h4
-rw-r--r--drivers/unix/packet_peer_udp_posix.cpp36
-rw-r--r--drivers/unix/packet_peer_udp_posix.h2
-rw-r--r--platform/windows/packet_peer_udp_winsock.cpp25
-rw-r--r--platform/windows/packet_peer_udp_winsock.h4
-rw-r--r--thirdparty/enet/godot.cpp10
7 files changed, 73 insertions, 15 deletions
diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp
index 46accf420a..3bc116f1b6 100644
--- a/core/io/packet_peer_udp.cpp
+++ b/core/io/packet_peer_udp.cpp
@@ -31,6 +31,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();
@@ -78,4 +83,6 @@ PacketPeerUDP *PacketPeerUDP::create() {
}
PacketPeerUDP::PacketPeerUDP() {
+
+ blocking = true;
}
diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h
index c316faad4b..c486f443fb 100644
--- a/core/io/packet_peer_udp.h
+++ b/core/io/packet_peer_udp.h
@@ -36,6 +36,8 @@ class PacketPeerUDP : public PacketPeer {
GDCLASS(PacketPeerUDP, PacketPeer);
protected:
+ bool blocking;
+
static PacketPeerUDP *(*_create)();
static void _bind_methods();
@@ -44,6 +46,8 @@ protected:
Error _set_dest_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;
diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp
index 98883f3267..e70e4fc349 100644
--- a/drivers/unix/packet_peer_udp_posix.cpp
+++ b/drivers/unix/packet_peer_udp_posix.cpp
@@ -107,10 +107,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;
}
}
@@ -173,10 +177,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;
@@ -243,9 +249,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_dest_address(const IP_Address &p_address, int p_port) {
peer_addr = p_address;
@@ -264,6 +296,8 @@ void PacketPeerUDPPosix::make_default() {
PacketPeerUDPPosix::PacketPeerUDPPosix() {
+ blocking = true;
+ sock_blocking = true;
sockfd = -1;
packet_port = 0;
queue_count = 0;
diff --git a/drivers/unix/packet_peer_udp_posix.h b/drivers/unix/packet_peer_udp_posix.h
index b44ef49f2c..60d5bf6580 100644
--- a/drivers/unix/packet_peer_udp_posix.h
+++ b/drivers/unix/packet_peer_udp_posix.h
@@ -47,6 +47,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;
@@ -55,6 +56,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:
diff --git a/platform/windows/packet_peer_udp_winsock.cpp b/platform/windows/packet_peer_udp_winsock.cpp
index 2df8addece..d98b64df7c 100644
--- a/platform/windows/packet_peer_udp_winsock.cpp
+++ b/platform/windows/packet_peer_udp_winsock.cpp
@@ -82,7 +82,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;
@@ -90,7 +90,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;
@@ -101,15 +103,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();
@@ -139,8 +139,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;
@@ -166,7 +164,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);
@@ -252,6 +250,9 @@ int PacketPeerUDPWinsock::_get_socket() {
sockfd = _socket_create(sock_type, SOCK_DGRAM, IPPROTO_UDP);
+ if (sockfd != -1)
+ _set_sock_blocking(false);
+
return sockfd;
}
@@ -273,6 +274,8 @@ PacketPeerUDP *PacketPeerUDPWinsock::_create() {
PacketPeerUDPWinsock::PacketPeerUDPWinsock() {
+ blocking = true;
+ sock_blocking = true;
sockfd = -1;
packet_port = 0;
queue_count = 0;
diff --git a/platform/windows/packet_peer_udp_winsock.h b/platform/windows/packet_peer_udp_winsock.h
index 62107364af..6b37aefead 100644
--- a/platform/windows/packet_peer_udp_winsock.h
+++ b/platform/windows/packet_peer_udp_winsock.h
@@ -45,6 +45,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;
@@ -54,8 +55,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);
diff --git a/thirdparty/enet/godot.cpp b/thirdparty/enet/godot.cpp
index 0f707274ee..18ccc02c50 100644
--- a/thirdparty/enet/godot.cpp
+++ b/thirdparty/enet/godot.cpp
@@ -79,7 +79,10 @@ int enet_socket_bind(ENetSocket socket, const ENetAddress *address) {
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) {
@@ -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);
if (err != OK) {
+
+ if (err == ERR_UNAVAILABLE) { // blocking call
+ return 0;
+ }
+
WARN_PRINT("Sending failed!");
return -1;
}