diff options
Diffstat (limited to 'core/io/packet_peer_udp.cpp')
-rw-r--r-- | core/io/packet_peer_udp.cpp | 75 |
1 files changed, 73 insertions, 2 deletions
diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp index a8cfd741bb..f800ffc3db 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -133,7 +133,11 @@ Error PacketPeerUDP::put_packet(const uint8_t *p_buffer, int p_buffer_size) { } do { - err = _sock->sendto(p_buffer, p_buffer_size, sent, peer_addr, peer_port); + if (connected) { + err = _sock->send(p_buffer, p_buffer_size, sent); + } else { + err = _sock->sendto(p_buffer, p_buffer_size, sent, peer_addr, peer_port); + } if (err != OK) { if (err != ERR_BUSY) return FAILED; @@ -184,12 +188,69 @@ Error PacketPeerUDP::listen(int p_port, const IP_Address &p_bind_address, int p_ return OK; } +Error PacketPeerUDP::connect_socket(Ref<NetSocket> p_sock) { + Error err; + int read = 0; + uint16_t r_port; + IP_Address r_ip; + + err = p_sock->recvfrom(recv_buffer, sizeof(recv_buffer), read, r_ip, r_port, true); + ERR_FAIL_COND_V(err != OK, err); + err = p_sock->connect_to_host(r_ip, r_port); + ERR_FAIL_COND_V(err != OK, err); + _sock = p_sock; + peer_addr = r_ip; + peer_port = r_port; + packet_ip = peer_addr; + packet_port = peer_port; + connected = true; + return OK; +} + +Error PacketPeerUDP::connect_to_host(const IP_Address &p_host, int p_port) { + ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); + ERR_FAIL_COND_V(!p_host.is_valid(), ERR_INVALID_PARAMETER); + + Error err; + + if (!_sock->is_open()) { + IP::Type ip_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; + err = _sock->open(NetSocket::TYPE_UDP, ip_type); + ERR_FAIL_COND_V(err != OK, ERR_CANT_OPEN); + _sock->set_blocking_enabled(false); + } + + err = _sock->connect_to_host(p_host, p_port); + + // I see no reason why we should get ERR_BUSY (wouldblock/eagain) here. + // This is UDP, so connect is only used to tell the OS to which socket + // it shuold deliver packets when multiple are bound on the same address/port. + if (err != OK) { + close(); + ERR_FAIL_V_MSG(FAILED, "Unable to connect"); + } + + connected = true; + + peer_addr = p_host; + peer_port = p_port; + + // Flush any packet we might still have in queue. + rb.clear(); + return OK; +} + +bool PacketPeerUDP::is_connected_to_host() const { + return connected; +} + void PacketPeerUDP::close() { if (_sock.is_valid()) _sock->close(); rb.resize(16); queue_count = 0; + connected = false; } Error PacketPeerUDP::wait() { @@ -212,7 +273,13 @@ Error PacketPeerUDP::_poll() { uint16_t port; while (true) { - err = _sock->recvfrom(recv_buffer, sizeof(recv_buffer), read, ip, port); + if (connected) { + err = _sock->recv(recv_buffer, sizeof(recv_buffer), read); + ip = peer_addr; + port = peer_port; + } else { + err = _sock->recvfrom(recv_buffer, sizeof(recv_buffer), read, ip, port); + } if (err != OK) { if (err == ERR_BUSY) @@ -254,6 +321,7 @@ int PacketPeerUDP::get_packet_port() const { void PacketPeerUDP::set_dest_address(const IP_Address &p_address, int p_port) { + ERR_FAIL_COND_MSG(connected, "Destination address cannot be set for connected sockets"); peer_addr = p_address; peer_port = p_port; } @@ -264,6 +332,8 @@ void PacketPeerUDP::_bind_methods() { ClassDB::bind_method(D_METHOD("close"), &PacketPeerUDP::close); ClassDB::bind_method(D_METHOD("wait"), &PacketPeerUDP::wait); ClassDB::bind_method(D_METHOD("is_listening"), &PacketPeerUDP::is_listening); + ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port"), &PacketPeerUDP::connect_to_host); + ClassDB::bind_method(D_METHOD("is_connected_to_host"), &PacketPeerUDP::is_connected_to_host); ClassDB::bind_method(D_METHOD("get_packet_ip"), &PacketPeerUDP::_get_packet_ip); ClassDB::bind_method(D_METHOD("get_packet_port"), &PacketPeerUDP::get_packet_port); ClassDB::bind_method(D_METHOD("set_dest_address", "host", "port"), &PacketPeerUDP::_set_dest_address); @@ -276,6 +346,7 @@ PacketPeerUDP::PacketPeerUDP() : packet_port(0), queue_count(0), peer_port(0), + connected(false), blocking(true), broadcast(false), _sock(Ref<NetSocket>(NetSocket::create())) { |