This commit is contained in:
Jordan Schidlowsky 2021-11-08 23:14:37 -06:00 committed by GitHub
commit 7d66d0cb54
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 110 additions and 32 deletions

View file

@ -34,6 +34,16 @@
#include "core/io/ip.h"
#include "core/reference.h"
typedef struct {
#ifdef WINDOWS_ENABLED
size_t dataLength;
void *data;
#else
void *data;
size_t dataLength;
#endif
} NetSocketBuffer;
class NetSocket : public Reference {
protected:
static NetSocket *(*_create)();
@ -63,6 +73,7 @@ public:
virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port, bool p_peek = false) = 0;
virtual Error send(const uint8_t *p_buffer, int p_len, int &r_sent) = 0;
virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) = 0;
virtual Error sendmsg(const NetSocketBuffer *p_buffers, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) = 0;
virtual Ref<NetSocket> accept(IP_Address &r_ip, uint16_t &r_port) = 0;
virtual bool is_open() const = 0;

View file

@ -618,6 +618,43 @@ Error NetSocketPosix::sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP
return OK;
}
Error NetSocketPosix::sendmsg(const NetSocketBuffer *p_buffers, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) {
ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED);
struct sockaddr_storage addr;
size_t addr_size = _set_addr_storage(&addr, p_ip, p_port, _ip_type);
#ifdef WINDOWS_ENABLED
DWORD sentLength = 0;
if (WSASendTo(_sock, (LPWSABUF)p_buffers, (DWORD)p_len, &sentLength, 0, (struct sockaddr *)&addr, addr_size, NULL, NULL) == SOCKET_ERROR) {
NetError err = _get_socket_error();
if (err == ERR_NET_WOULD_BLOCK)
return ERR_BUSY;
return FAILED;
}
r_sent = (int)sentLength;
#else
struct msghdr msgHdr;
memset(&msgHdr, 0, sizeof(struct msghdr));
msgHdr.msg_name = (struct sockaddr *)&addr;
msgHdr.msg_namelen = addr_size;
msgHdr.msg_iov = (struct iovec *)p_buffers;
msgHdr.msg_iovlen = (int)p_len;
r_sent = ::sendmsg(_sock, &msgHdr, 0);
if (r_sent < 0) {
NetError err = _get_socket_error();
if (err == ERR_NET_WOULD_BLOCK)
return ERR_BUSY;
return FAILED;
}
#endif
return OK;
}
Error NetSocketPosix::set_broadcasting_enabled(bool p_enabled) {
ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED);
// IPv6 has no broadcast support.

View file

@ -83,6 +83,7 @@ public:
virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port, bool p_peek = false);
virtual Error send(const uint8_t *p_buffer, int p_len, int &r_sent);
virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port);
virtual Error sendmsg(const NetSocketBuffer *p_buffers, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port);
virtual Ref<NetSocket> accept(IP_Address &r_ip, uint16_t &r_port);
virtual bool is_open() const;

View file

@ -217,22 +217,25 @@ void NetworkedMultiplayerENet::poll() {
_pop_current_packet();
if (!host || !active) { // Might be disconnected
return;
}
ENetEvent event;
/* Keep servicing until there are no available events left in queue. */
while (true) {
if (!host || !active) { // Might have been disconnected while emitting a notification
int ret = enet_host_service(host, &event, 0);
if (ret < 0) {
ERR_FAIL_MSG("Enet host service error");
} else if (ret == 0) {
return; // No events
}
/* Keep servicing until there are no available events left in the queue. */
do {
if (!host || !active) { // Check again after every event
return;
}
int ret = enet_host_service(host, &event, 0);
if (ret < 0) {
// Error, do something?
break;
} else if (ret == 0) {
break;
}
switch (event.type) {
case ENET_EVENT_TYPE_CONNECT: {
// Store any relevant client information here.
@ -436,7 +439,7 @@ void NetworkedMultiplayerENet::poll() {
// Do nothing
} break;
}
}
} while (enet_host_check_events(host, &event) > 0);
}
bool NetworkedMultiplayerENet::is_server() const {
@ -546,9 +549,10 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer
packet_flags = ENET_PACKET_FLAG_UNSEQUENCED;
}
channel = SYSCH_UNRELIABLE;
packet_flags |= ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT;
} break;
case TRANSFER_MODE_UNRELIABLE_ORDERED: {
packet_flags = 0;
packet_flags = ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT;
channel = SYSCH_UNRELIABLE;
} break;
case TRANSFER_MODE_RELIABLE: {

View file

@ -59,8 +59,13 @@ typedef void *ENetSocket;
typedef struct
{
#ifdef WINDOWS_ENABLED
size_t dataLength;
void *data;
#else
void *data;
size_t dataLength;
#endif
} ENetBuffer;
#define ENET_CALLBACK

View file

@ -48,6 +48,7 @@ class ENetGodotSocket {
public:
virtual Error bind(IP_Address p_ip, uint16_t p_port) = 0;
virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) = 0;
virtual Error sendmsg(const NetSocketBuffer *p_buffers, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) = 0;
virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port) = 0;
virtual int set_option(ENetSocketOption p_option, int p_value) = 0;
virtual void close() = 0;
@ -93,6 +94,10 @@ public:
return sock->sendto(p_buffer, p_len, r_sent, p_ip, p_port);
}
Error sendmsg(const NetSocketBuffer *p_buffers, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) {
return sock->sendmsg(p_buffers, p_len, r_sent, p_ip, p_port);
}
Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port) {
Error err = sock->poll(NetSocket::POLL_TYPE_IN, 0);
if (err != OK) {
@ -196,6 +201,22 @@ public:
return dtls->put_packet(p_buffer, p_len);
}
Error sendmsg(const NetSocketBuffer *p_buffers, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) {
r_sent = 0;
for(int i = 0; i < p_len; i++) {
int sent = 0;
Error e = sendto((const uint8_t *)p_buffers[i].data, p_buffers[i].dataLength, sent, p_ip, p_port);
if(e != OK) {
return e;
}
r_sent += sent;
if(sent < p_buffers[i].dataLength) {
break;
}
}
return OK;
}
Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port) {
dtls->poll();
if (dtls->get_status() == PacketPeerDTLS::STATUS_HANDSHAKING) {
@ -279,6 +300,22 @@ public:
return err;
}
Error sendmsg(const NetSocketBuffer *p_buffers, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) {
r_sent = 0;
for(int i = 0; i < p_len; i++) {
int sent = 0;
Error e = sendto((const uint8_t *)p_buffers[i].data, p_buffers[i].dataLength, sent, p_ip, p_port);
if(e != OK) {
return e;
}
r_sent += sent;
if(sent < p_buffers[i].dataLength) {
break;
}
}
return OK;
}
Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port) {
udp_server->poll();
// TODO limits? Maybe we can better enforce allowed connections!
@ -459,26 +496,9 @@ int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBu
dest.set_ipv6(address->host);
// Create a single packet.
PoolVector<uint8_t> out;
PoolVector<uint8_t>::Write w;
int size = 0;
int pos = 0;
for (i = 0; i < bufferCount; i++) {
size += buffers[i].dataLength;
}
out.resize(size);
w = out.write();
for (i = 0; i < bufferCount; i++) {
memcpy(&w[pos], buffers[i].data, buffers[i].dataLength);
pos += buffers[i].dataLength;
}
int sent = 0;
err = sock->sendto((const uint8_t *)&w[0], size, sent, dest, address->port);
err = sock->sendmsg((const NetSocketBuffer*)buffers, bufferCount, sent, dest, address->port);
if (err != OK) {
if (err == ERR_BUSY) { // Blocking call
return 0;
}