diff options
-rw-r--r-- | core/io/file_access_network.cpp | 2 | ||||
-rw-r--r-- | core/io/http_client.cpp | 2 | ||||
-rw-r--r-- | core/io/stream_peer_tcp.cpp | 297 | ||||
-rw-r--r-- | core/io/stream_peer_tcp.h | 38 | ||||
-rw-r--r-- | core/io/tcp_server.cpp | 97 | ||||
-rw-r--r-- | core/io/tcp_server.h | 19 | ||||
-rw-r--r-- | core/register_core_types.cpp | 4 | ||||
-rw-r--r-- | core/script_debugger_remote.cpp | 2 | ||||
-rw-r--r-- | drivers/unix/os_unix.cpp | 4 | ||||
-rw-r--r-- | drivers/unix/stream_peer_tcp_posix.cpp | 411 | ||||
-rw-r--r-- | drivers/unix/stream_peer_tcp_posix.h | 90 | ||||
-rw-r--r-- | drivers/unix/tcp_server_posix.cpp | 207 | ||||
-rw-r--r-- | drivers/unix/tcp_server_posix.h | 58 | ||||
-rw-r--r-- | drivers/windows/stream_peer_tcp_winsock.cpp | 375 | ||||
-rw-r--r-- | drivers/windows/stream_peer_tcp_winsock.h | 92 | ||||
-rw-r--r-- | drivers/windows/tcp_server_winsock.cpp | 189 | ||||
-rw-r--r-- | drivers/windows/tcp_server_winsock.h | 61 | ||||
-rw-r--r-- | editor/fileserver/editor_file_server.cpp | 2 | ||||
-rw-r--r-- | editor/script_editor_debugger.cpp | 2 | ||||
-rw-r--r-- | platform/uwp/os_uwp.cpp | 4 | ||||
-rw-r--r-- | platform/windows/os_windows.cpp | 7 |
21 files changed, 407 insertions, 1556 deletions
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp index 8bffe3e88b..6b6856dcc8 100644 --- a/core/io/file_access_network.cpp +++ b/core/io/file_access_network.cpp @@ -227,7 +227,7 @@ FileAccessNetworkClient::FileAccessNetworkClient() { quit = false; singleton = this; last_id = 0; - client = Ref<StreamPeerTCP>(StreamPeerTCP::create_ref()); + client.instance(); sem = Semaphore::create(); lockcount = 0; } diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index bfa2d3b389..c47ae05dc2 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -683,7 +683,7 @@ void HTTPClient::set_read_chunk_size(int p_size) { HTTPClient::HTTPClient() { - tcp_connection = StreamPeerTCP::create_ref(); + tcp_connection.instance(); resolving = IP::RESOLVER_INVALID_ID; status = STATUS_DISCONNECTED; conn_port = -1; diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp index 54ebb3ae0d..484e160f0e 100644 --- a/core/io/stream_peer_tcp.cpp +++ b/core/io/stream_peer_tcp.cpp @@ -30,7 +30,280 @@ #include "stream_peer_tcp.h" -StreamPeerTCP *(*StreamPeerTCP::_create)() = NULL; +Error StreamPeerTCP::_poll_connection() { + + ERR_FAIL_COND_V(status != STATUS_CONNECTING || !_sock.is_valid() || !_sock->is_open(), FAILED); + + Error err = _sock->connect_to_host(peer_host, peer_port); + + if (err == OK) { + status = STATUS_CONNECTED; + return OK; + } else if (err == ERR_BUSY) { + // Still trying to connect + return OK; + } + + status = STATUS_ERROR; + return ERR_CONNECTION_ERROR; +} + +void StreamPeerTCP::accept_socket(Ref<NetSocket> p_sock, IP_Address p_host, uint16_t p_port) { + + _sock = p_sock; + _sock->set_blocking_enabled(false); + + status = STATUS_CONNECTING; + + peer_host = p_host; + peer_port = p_port; +} + +Error StreamPeerTCP::connect_to_host(const IP_Address &p_host, uint16_t p_port) { + + ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); + ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE); + ERR_FAIL_COND_V(!p_host.is_valid(), ERR_INVALID_PARAMETER); + + Error err; + IP::Type ip_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; + + err = _sock->open(NetSocket::TYPE_TCP, ip_type); + ERR_FAIL_COND_V(err != OK, FAILED); + + _sock->set_blocking_enabled(false); + + err = _sock->connect_to_host(p_host, p_port); + + if (err != OK) { + if (err == ERR_BUSY) { + status = STATUS_CONNECTING; + } else { + ERR_PRINT("Connection to remote host failed!"); + disconnect_from_host(); + return FAILED; + } + } + + status = STATUS_CONNECTED; + peer_host = p_host; + peer_port = p_port; + + return OK; +} + +Error StreamPeerTCP::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) { + + ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); + + if (status == STATUS_NONE || status == STATUS_ERROR) { + + return FAILED; + } + + if (status != STATUS_CONNECTED) { + + if (_poll_connection() != OK) { + + return FAILED; + } + + if (status != STATUS_CONNECTED) { + r_sent = 0; + return OK; + } + } + + if (!_sock->is_open()) + return FAILED; + + Error err; + int data_to_send = p_bytes; + const uint8_t *offset = p_data; + int total_sent = 0; + + while (data_to_send) { + + int sent_amount = 0; + err = _sock->send(offset, data_to_send, sent_amount); + + if (err != OK) { + + if (err != ERR_BUSY) { + disconnect_from_host(); + return FAILED; + } + + if (!p_block) { + r_sent = total_sent; + return OK; + } + + // Block and wait for the socket to accept more data + err = _sock->poll(NetSocket::POLL_TYPE_OUT, -1); + if (err != OK) { + disconnect_from_host(); + return FAILED; + } + } else { + + data_to_send -= sent_amount; + offset += sent_amount; + total_sent += sent_amount; + } + } + + r_sent = total_sent; + + return OK; +} + +Error StreamPeerTCP::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) { + + if (!is_connected_to_host()) { + + return FAILED; + }; + + if (status == STATUS_CONNECTING) { + + if (_poll_connection() != OK) { + + return FAILED; + }; + + if (status != STATUS_CONNECTED) { + r_received = 0; + return OK; + }; + }; + + Error err; + int to_read = p_bytes; + int total_read = 0; + r_received = 0; + + while (to_read) { + + int read = 0; + err = _sock->recv(p_buffer + total_read, to_read, read); + + if (err != OK) { + + if (err != ERR_BUSY) { + disconnect_from_host(); + return FAILED; + } + + if (!p_block) { + r_received = total_read; + return OK; + } + + err = _sock->poll(NetSocket::POLL_TYPE_IN, -1); + + if (err != OK) { + disconnect_from_host(); + return FAILED; + } + + } else if (read == 0) { + + _sock->close(); + status = STATUS_NONE; + peer_port = 0; + peer_host = IP_Address(); + r_received = total_read; + return ERR_FILE_EOF; + + } else { + + to_read -= read; + total_read += read; + } + } + + r_received = total_read; + + return OK; +} + +void StreamPeerTCP::set_no_delay(bool p_enabled) { + + ERR_FAIL_COND(!is_connected_to_host()); + _sock->set_tcp_no_delay_enabled(p_enabled); +} + +bool StreamPeerTCP::is_connected_to_host() const { + + if (status == STATUS_NONE || status == STATUS_ERROR) { + + return false; + } + + if (status != STATUS_CONNECTED) { + return true; + } + + return _sock.is_valid() && _sock->is_open(); +} + +StreamPeerTCP::Status StreamPeerTCP::get_status() { + + if (status == STATUS_CONNECTING) { + _poll_connection(); + } + + return status; +} + +void StreamPeerTCP::disconnect_from_host() { + + if (_sock.is_valid() && _sock->is_open()) + _sock->close(); + + status = STATUS_NONE; + peer_host = IP_Address(); + peer_port = 0; +} + +Error StreamPeerTCP::put_data(const uint8_t *p_data, int p_bytes) { + + int total; + return write(p_data, p_bytes, total, true); +} + +Error StreamPeerTCP::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) { + + return write(p_data, p_bytes, r_sent, false); +} + +Error StreamPeerTCP::get_data(uint8_t *p_buffer, int p_bytes) { + + int total; + return read(p_buffer, p_bytes, total, true); +} + +Error StreamPeerTCP::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) { + + return read(p_buffer, p_bytes, r_received, false); +} + +int StreamPeerTCP::get_available_bytes() const { + + ERR_FAIL_COND_V(!_sock.is_valid(), -1); + return _sock->get_available_bytes(); +} + +IP_Address StreamPeerTCP::get_connected_host() const { + + return peer_host; +} + +uint16_t StreamPeerTCP::get_connected_port() const { + + return peer_port; +} Error StreamPeerTCP::_connect(const String &p_address, int p_port) { @@ -62,23 +335,15 @@ void StreamPeerTCP::_bind_methods() { BIND_ENUM_CONSTANT(STATUS_ERROR); } -Ref<StreamPeerTCP> StreamPeerTCP::create_ref() { +StreamPeerTCP::StreamPeerTCP() { - if (!_create) - return Ref<StreamPeerTCP>(); - return Ref<StreamPeerTCP>(_create()); + _sock = Ref<NetSocket>(NetSocket::create()); + status = STATUS_NONE; + peer_host = IP_Address(); + peer_port = 0; } -StreamPeerTCP *StreamPeerTCP::create() { +StreamPeerTCP::~StreamPeerTCP() { - if (!_create) - return NULL; - return _create(); + disconnect_from_host(); } - -StreamPeerTCP::StreamPeerTCP() { -} - -StreamPeerTCP::~StreamPeerTCP(){ - -}; diff --git a/core/io/stream_peer_tcp.h b/core/io/stream_peer_tcp.h index dcda3b5bd7..de364915cd 100644 --- a/core/io/stream_peer_tcp.h +++ b/core/io/stream_peer_tcp.h @@ -33,6 +33,7 @@ #include "core/io/ip.h" #include "core/io/ip_address.h" +#include "core/io/net_socket.h" #include "core/io/stream_peer.h" class StreamPeerTCP : public StreamPeer { @@ -50,24 +51,37 @@ public: }; protected: - virtual Error _connect(const String &p_address, int p_port); - static StreamPeerTCP *(*_create)(); + Ref<NetSocket> _sock; + Status status; + IP_Address peer_host; + uint16_t peer_port; + + Error _connect(const String &p_address, int p_port); + Error _poll_connection(); + Error write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block); + Error read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block); + static void _bind_methods(); public: - virtual Error connect_to_host(const IP_Address &p_host, uint16_t p_port) = 0; + void accept_socket(Ref<NetSocket> p_sock, IP_Address p_host, uint16_t p_port); + + Error connect_to_host(const IP_Address &p_host, uint16_t p_port); + bool is_connected_to_host() const; + IP_Address get_connected_host() const; + uint16_t get_connected_port() const; + void disconnect_from_host(); - //read/write from streampeer + int get_available_bytes() const; + Status get_status(); - virtual bool is_connected_to_host() const = 0; - virtual Status get_status() const = 0; - virtual void disconnect_from_host() = 0; - virtual IP_Address get_connected_host() const = 0; - virtual uint16_t get_connected_port() const = 0; - virtual void set_no_delay(bool p_enabled) = 0; + void set_no_delay(bool p_enabled); - static Ref<StreamPeerTCP> create_ref(); - static StreamPeerTCP *create(); + // Read/Write from StreamPeer + Error put_data(const uint8_t *p_data, int p_bytes); + Error put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent); + Error get_data(uint8_t *p_buffer, int p_bytes); + Error get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received); StreamPeerTCP(); ~StreamPeerTCP(); diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp index 5916d58390..b8194cb17f 100644 --- a/core/io/tcp_server.cpp +++ b/core/io/tcp_server.cpp @@ -30,29 +30,98 @@ #include "tcp_server.h" -TCP_Server *(*TCP_Server::_create)() = NULL; +void TCP_Server::_bind_methods() { + + ClassDB::bind_method(D_METHOD("listen", "port", "bind_address"), &TCP_Server::listen, DEFVAL("*")); + ClassDB::bind_method(D_METHOD("is_connection_available"), &TCP_Server::is_connection_available); + ClassDB::bind_method(D_METHOD("take_connection"), &TCP_Server::take_connection); + ClassDB::bind_method(D_METHOD("stop"), &TCP_Server::stop); +} + +Error TCP_Server::listen(uint16_t p_port, const IP_Address &p_bind_address) { + + ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); + ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE); + ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); + + Error err; + IP::Type ip_type = IP::TYPE_ANY; + + // If the bind address is valid use its type as the socket type + if (p_bind_address.is_valid()) + ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; + + err = _sock->open(NetSocket::TYPE_TCP, ip_type); + + ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE); + + _sock->set_blocking_enabled(false); + _sock->set_reuse_address_enabled(true); + + err = _sock->bind(p_bind_address, p_port); + + if (err != OK) { + + _sock->close(); + return ERR_ALREADY_IN_USE; + } -Ref<TCP_Server> TCP_Server::create_ref() { + err = _sock->listen(MAX_PENDING_CONNECTIONS); - if (!_create) - return NULL; - return Ref<TCP_Server>(_create()); + if (err != OK) { + _sock->close(); + return FAILED; + } + return OK; } -TCP_Server *TCP_Server::create() { +bool TCP_Server::is_connection_available() const { - if (!_create) - return NULL; - return _create(); + ERR_FAIL_COND_V(!_sock.is_valid(), false); + + if (!_sock->is_open()) + return false; + + Error err = _sock->poll(NetSocket::POLL_TYPE_IN, 0); + if (err != OK) { + return false; + } + + return true; } -void TCP_Server::_bind_methods() { +Ref<StreamPeerTCP> TCP_Server::take_connection() { - ClassDB::bind_method(D_METHOD("listen", "port", "bind_address"), &TCP_Server::listen, DEFVAL("*")); - ClassDB::bind_method(D_METHOD("is_connection_available"), &TCP_Server::is_connection_available); - ClassDB::bind_method(D_METHOD("take_connection"), &TCP_Server::take_connection); - ClassDB::bind_method(D_METHOD("stop"), &TCP_Server::stop); + Ref<StreamPeerTCP> conn; + if (!is_connection_available()) { + return conn; + } + + Ref<NetSocket> ns; + IP_Address ip; + uint16_t port = 0; + ns = _sock->accept(ip, port); + if (!ns.is_valid()) + return conn; + + conn = Ref<StreamPeerTCP>(memnew(StreamPeerTCP)); + conn->accept_socket(ns, ip, port); + return conn; +} + +void TCP_Server::stop() { + + if (_sock.is_valid()) { + _sock->close(); + } } TCP_Server::TCP_Server() { + + _sock = Ref<NetSocket>(NetSocket::create()); +} + +TCP_Server::~TCP_Server() { + + stop(); } diff --git a/core/io/tcp_server.h b/core/io/tcp_server.h index 7353390bef..4c89197d9a 100644 --- a/core/io/tcp_server.h +++ b/core/io/tcp_server.h @@ -32,6 +32,7 @@ #define TCP_SERVER_H #include "core/io/ip.h" +#include "core/io/net_socket.h" #include "core/io/stream_peer.h" #include "core/io/stream_peer_tcp.h" @@ -40,22 +41,22 @@ class TCP_Server : public Reference { GDCLASS(TCP_Server, Reference); protected: - static TCP_Server *(*_create)(); + enum { + MAX_PENDING_CONNECTIONS = 8 + }; - //bind helper + Ref<NetSocket> _sock; static void _bind_methods(); public: - virtual Error listen(uint16_t p_port, const IP_Address &p_bind_address = IP_Address("*")) = 0; - virtual bool is_connection_available() const = 0; - virtual Ref<StreamPeerTCP> take_connection() = 0; + Error listen(uint16_t p_port, const IP_Address &p_bind_address = IP_Address("*")); + bool is_connection_available() const; + Ref<StreamPeerTCP> take_connection(); - virtual void stop() = 0; //stop listening - - static Ref<TCP_Server> create_ref(); - static TCP_Server *create(); + void stop(); // Stop listening TCP_Server(); + ~TCP_Server(); }; #endif // TCP_SERVER_H diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index dcf7ee1de6..b0023b4c26 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -146,8 +146,8 @@ void register_core_types() { ClassDB::register_class<FuncRef>(); ClassDB::register_virtual_class<StreamPeer>(); ClassDB::register_class<StreamPeerBuffer>(); - ClassDB::register_custom_instance_class<StreamPeerTCP>(); - ClassDB::register_custom_instance_class<TCP_Server>(); + ClassDB::register_class<StreamPeerTCP>(); + ClassDB::register_class<TCP_Server>(); ClassDB::register_class<PacketPeerUDP>(); ClassDB::register_custom_instance_class<StreamPeerSSL>(); ClassDB::register_virtual_class<IP>(); diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp index ac684af6fe..0519807e63 100644 --- a/core/script_debugger_remote.cpp +++ b/core/script_debugger_remote.cpp @@ -1084,7 +1084,7 @@ ScriptDebuggerRemote::ScriptDebuggerRemote() : max_frame_functions(16), skip_profile_frame(false), reload_all_scripts(false), - tcp_client(StreamPeerTCP::create_ref()), + tcp_client(Ref<StreamPeerTCP>(memnew(StreamPeerTCP))), packet_peer_stream(Ref<PacketPeerStream>(memnew(PacketPeerStream))), last_perf_time(0), performance(Engine::get_singleton()->get_singleton_object("Performance")), diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 3cca16ee25..1225d00aad 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -40,8 +40,6 @@ #include "drivers/unix/net_socket_posix.h" #include "drivers/unix/rw_lock_posix.h" #include "drivers/unix/semaphore_posix.h" -#include "drivers/unix/stream_peer_tcp_posix.h" -#include "drivers/unix/tcp_server_posix.h" #include "drivers/unix/thread_posix.h" #include "servers/visual_server.h" @@ -125,8 +123,6 @@ void OS_Unix::initialize_core() { #ifndef NO_NETWORK NetSocketPosix::make_default(); - TCPServerPosix::make_default(); - StreamPeerTCPPosix::make_default(); IP_Unix::make_default(); #endif diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp deleted file mode 100644 index 44b9ef1d7c..0000000000 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ /dev/null @@ -1,411 +0,0 @@ -/*************************************************************************/ -/* stream_peer_tcp_posix.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifdef UNIX_ENABLED - -#include "stream_peer_tcp_posix.h" - -#include <errno.h> -#include <netdb.h> -#include <poll.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <unistd.h> -#ifndef NO_FCNTL -#ifdef __HAIKU__ -#include <fcntl.h> -#else -#include <sys/fcntl.h> -#endif -#else -#include <sys/ioctl.h> -#endif -#include <netinet/in.h> - -#include <sys/socket.h> -#ifdef JAVASCRIPT_ENABLED -#include <arpa/inet.h> -#endif - -#include <netinet/tcp.h> - -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) -#define MSG_NOSIGNAL SO_NOSIGPIPE -#endif - -#include "drivers/unix/socket_helpers.h" - -StreamPeerTCP *StreamPeerTCPPosix::_create() { - - return memnew(StreamPeerTCPPosix); -}; - -void StreamPeerTCPPosix::make_default() { - - StreamPeerTCP::_create = StreamPeerTCPPosix::_create; -}; - -Error StreamPeerTCPPosix::_block(int p_sockfd, bool p_read, bool p_write) const { - - struct pollfd pfd; - pfd.fd = p_sockfd; - pfd.events = 0; - if (p_read) - pfd.events |= POLLIN; - if (p_write) - pfd.events |= POLLOUT; - pfd.revents = 0; - - int ret = poll(&pfd, 1, -1); - return ret < 0 ? FAILED : OK; -}; - -Error StreamPeerTCPPosix::_poll_connection() const { - - ERR_FAIL_COND_V(status != STATUS_CONNECTING || sockfd == -1, FAILED); - - struct sockaddr_storage their_addr; - size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port, sock_type); - - if (::connect(sockfd, (struct sockaddr *)&their_addr, addr_size) == -1) { - - if (errno == EISCONN) { - status = STATUS_CONNECTED; - return OK; - }; - - if (errno == EINPROGRESS || errno == EALREADY) { - return OK; - } - - status = STATUS_ERROR; - return ERR_CONNECTION_ERROR; - } else { - - status = STATUS_CONNECTED; - return OK; - }; - - return OK; -}; - -void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_sock_type) { - - sock_type = p_sock_type; - sockfd = p_sockfd; -#ifndef NO_FCNTL - if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) { - WARN_PRINT("Error setting socket as non blocking"); - } -#else - int bval = 1; - if (ioctl(sockfd, FIONBIO, &bval) < 0) { - WARN_PRINT("Error setting socket as non blocking"); - } -#endif - status = STATUS_CONNECTING; - - peer_host = p_host; - peer_port = p_port; -}; - -Error StreamPeerTCPPosix::connect_to_host(const IP_Address &p_host, uint16_t p_port) { - - ERR_FAIL_COND_V(!p_host.is_valid(), ERR_INVALID_PARAMETER); - - sock_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; - sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP); - if (sockfd == -1) { - ERR_PRINT("Socket creation failed!"); - disconnect_from_host(); - //perror("socket"); - return FAILED; - }; - -#ifndef NO_FCNTL - if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) { - WARN_PRINT("Error setting socket as non blocking"); - } -#else - int bval = 1; - if (ioctl(sockfd, FIONBIO, &bval) < 0) { - WARN_PRINT("Error setting socket as non blocking"); - } -#endif - - struct sockaddr_storage their_addr; - size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port, sock_type); - - errno = 0; - if (::connect(sockfd, (struct sockaddr *)&their_addr, addr_size) == -1 && errno != EINPROGRESS) { - - ERR_PRINT("Connection to remote host failed!"); - disconnect_from_host(); - return FAILED; - }; - - if (errno == EINPROGRESS) { - status = STATUS_CONNECTING; - } else { - status = STATUS_CONNECTED; - }; - - peer_host = p_host; - peer_port = p_port; - - return OK; -}; - -Error StreamPeerTCPPosix::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) { - - if (status == STATUS_NONE || status == STATUS_ERROR) { - - return FAILED; - }; - - if (status != STATUS_CONNECTED) { - - if (_poll_connection() != OK) { - - return FAILED; - }; - - if (status != STATUS_CONNECTED) { - r_sent = 0; - return OK; - }; - }; - - int data_to_send = p_bytes; - const uint8_t *offset = p_data; - if (sockfd == -1) return FAILED; - errno = 0; - int total_sent = 0; - - while (data_to_send) { - - int sent_amount = send(sockfd, offset, data_to_send, MSG_NOSIGNAL); - //printf("Sent TCP data of %d bytes, errno %d\n", sent_amount, errno); - - if (sent_amount == -1) { - - if (errno != EAGAIN) { - - perror("Nothing sent"); - disconnect_from_host(); - ERR_PRINT("Server disconnected!\n"); - return FAILED; - }; - - if (!p_block) { - r_sent = total_sent; - return OK; - }; - - _block(sockfd, false, true); - } else { - - data_to_send -= sent_amount; - offset += sent_amount; - total_sent += sent_amount; - }; - } - - r_sent = total_sent; - - return OK; -}; - -Error StreamPeerTCPPosix::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) { - - if (!is_connected_to_host()) { - - return FAILED; - }; - - if (status == STATUS_CONNECTING) { - - if (_poll_connection() != OK) { - - return FAILED; - }; - - if (status != STATUS_CONNECTED) { - r_received = 0; - return OK; - }; - }; - - int to_read = p_bytes; - int total_read = 0; - errno = 0; - - while (to_read) { - - int read = recv(sockfd, p_buffer + total_read, to_read, 0); - - if (read == -1) { - - if (errno != EAGAIN) { - - perror("Nothing read"); - disconnect_from_host(); - ERR_PRINT("Server disconnected!\n"); - return FAILED; - }; - - if (!p_block) { - - r_received = total_read; - return OK; - }; - _block(sockfd, true, false); - - } else if (read == 0) { - - sockfd = -1; - status = STATUS_NONE; - peer_port = 0; - peer_host = IP_Address(); - r_received = total_read; - return ERR_FILE_EOF; - - } else { - - to_read -= read; - total_read += read; - }; - }; - - r_received = total_read; - - return OK; -}; - -void StreamPeerTCPPosix::set_no_delay(bool p_enabled) { - - ERR_FAIL_COND(!is_connected_to_host()); - int flag = p_enabled ? 1 : 0; - if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)) < 0) { - ERR_PRINT("Unable to set TCP no delay option"); - } -} - -bool StreamPeerTCPPosix::is_connected_to_host() const { - - if (status == STATUS_NONE || status == STATUS_ERROR) { - - return false; - }; - if (status != STATUS_CONNECTED) { - return true; - }; - - return (sockfd != -1); -}; - -StreamPeerTCP::Status StreamPeerTCPPosix::get_status() const { - - if (status == STATUS_CONNECTING) { - _poll_connection(); - }; - - return status; -}; - -void StreamPeerTCPPosix::disconnect_from_host() { - - if (sockfd != -1) - close(sockfd); - - sock_type = IP::TYPE_NONE; - sockfd = -1; - - status = STATUS_NONE; - peer_port = 0; - peer_host = IP_Address(); -}; - -Error StreamPeerTCPPosix::put_data(const uint8_t *p_data, int p_bytes) { - - int total; - return write(p_data, p_bytes, total, true); -}; - -Error StreamPeerTCPPosix::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) { - - return write(p_data, p_bytes, r_sent, false); -}; - -Error StreamPeerTCPPosix::get_data(uint8_t *p_buffer, int p_bytes) { - - int total; - return read(p_buffer, p_bytes, total, true); -}; - -Error StreamPeerTCPPosix::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) { - - return read(p_buffer, p_bytes, r_received, false); -}; - -int StreamPeerTCPPosix::get_available_bytes() const { - - unsigned long len; - int ret = ioctl(sockfd, FIONREAD, &len); - ERR_FAIL_COND_V(ret == -1, 0) - return len; -} -IP_Address StreamPeerTCPPosix::get_connected_host() const { - - return peer_host; -}; - -uint16_t StreamPeerTCPPosix::get_connected_port() const { - - return peer_port; -}; - -StreamPeerTCPPosix::StreamPeerTCPPosix() { - - sock_type = IP::TYPE_NONE; - sockfd = -1; - status = STATUS_NONE; - peer_port = 0; -}; - -StreamPeerTCPPosix::~StreamPeerTCPPosix() { - - disconnect_from_host(); -}; - -#endif diff --git a/drivers/unix/stream_peer_tcp_posix.h b/drivers/unix/stream_peer_tcp_posix.h deleted file mode 100644 index 05c48432db..0000000000 --- a/drivers/unix/stream_peer_tcp_posix.h +++ /dev/null @@ -1,90 +0,0 @@ -/*************************************************************************/ -/* stream_peer_tcp_posix.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifdef UNIX_ENABLED - -#ifndef STREAM_PEER_TCP_POSIX_H -#define STREAM_PEER_TCP_POSIX_H - -#include "core/error_list.h" -#include "core/io/ip_address.h" -#include "core/io/stream_peer_tcp.h" - -class StreamPeerTCPPosix : public StreamPeerTCP { - -protected: - mutable Status status; - - IP::Type sock_type; - int sockfd; - - Error _block(int p_sockfd, bool p_read, bool p_write) const; - - Error _poll_connection() const; - - IP_Address peer_host; - int peer_port; - - Error write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block); - Error read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block); - - static StreamPeerTCP *_create(); - -public: - virtual Error connect_to_host(const IP_Address &p_host, uint16_t p_port); - - virtual Error put_data(const uint8_t *p_data, int p_bytes); - virtual Error put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent); - - virtual Error get_data(uint8_t *p_buffer, int p_bytes); - virtual Error get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received); - - virtual int get_available_bytes() const; - - void set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_sock_type); - - virtual IP_Address get_connected_host() const; - virtual uint16_t get_connected_port() const; - - virtual bool is_connected_to_host() const; - virtual Status get_status() const; - virtual void disconnect_from_host(); - - virtual void set_no_delay(bool p_enabled); - - static void make_default(); - - StreamPeerTCPPosix(); - ~StreamPeerTCPPosix(); -}; - -#endif // TCP_CLIENT_POSIX_H - -#endif diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp deleted file mode 100644 index 67ab981f46..0000000000 --- a/drivers/unix/tcp_server_posix.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/*************************************************************************/ -/* tcp_server_posix.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "tcp_server_posix.h" -#include "stream_peer_tcp_posix.h" - -#ifdef UNIX_ENABLED - -#include <poll.h> - -#include <errno.h> -#include <netdb.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <unistd.h> -#ifndef NO_FCNTL -#ifdef __HAIKU__ -#include <fcntl.h> -#else -#include <sys/fcntl.h> -#endif -#else -#include <sys/ioctl.h> -#endif -#ifdef JAVASCRIPT_ENABLED -#include <arpa/inet.h> -#endif -#include <assert.h> -#include <netinet/in.h> -#include <sys/socket.h> - -#include "drivers/unix/socket_helpers.h" - -TCP_Server *TCPServerPosix::_create() { - - return memnew(TCPServerPosix); -}; - -void TCPServerPosix::make_default() { - - TCP_Server::_create = TCPServerPosix::_create; -}; - -Error TCPServerPosix::listen(uint16_t p_port, const IP_Address &p_bind_address) { - - ERR_FAIL_COND_V(listen_sockfd != -1, ERR_ALREADY_IN_USE); - ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); - - int sockfd; -#ifdef __OpenBSD__ - sock_type = IP::TYPE_IPV4; // OpenBSD does not support dual stacking, fallback to IPv4 only. -#else - sock_type = IP::TYPE_ANY; -#endif - - // If the bind address is valid use its type as the socket type - if (p_bind_address.is_valid()) - sock_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; - - sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP); - - ERR_FAIL_COND_V(sockfd == -1, FAILED); - -#ifndef NO_FCNTL - if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) { - WARN_PRINT("Error setting socket as non blocking"); - } -#else - int bval = 1; - if (ioctl(sockfd, FIONBIO, &bval) < 0) { - WARN_PRINT("Error setting socket as non blocking"); - } -#endif - - int reuse = 1; - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) { - WARN_PRINT("REUSEADDR failed!") - } - - struct sockaddr_storage addr; - size_t addr_size = _set_listen_sockaddr(&addr, p_port, sock_type, p_bind_address); - - if (bind(sockfd, (struct sockaddr *)&addr, addr_size) != -1) { - - if (::listen(sockfd, 1) == -1) { - - close(sockfd); - ERR_FAIL_V(FAILED); - }; - } else { - close(sockfd); - return ERR_ALREADY_IN_USE; - }; - - if (listen_sockfd != -1) { - stop(); - }; - - listen_sockfd = sockfd; - - return OK; -}; - -bool TCPServerPosix::is_connection_available() const { - - if (listen_sockfd == -1) { - return false; - }; - - struct pollfd pfd; - pfd.fd = listen_sockfd; - pfd.events = POLLIN; - pfd.revents = 0; - - int ret = poll(&pfd, 1, 0); - ERR_FAIL_COND_V(ret < 0, FAILED); - - if (ret && (pfd.revents & POLLIN)) { - return true; - }; - - return false; -}; - -Ref<StreamPeerTCP> TCPServerPosix::take_connection() { - - if (!is_connection_available()) { - return Ref<StreamPeerTCP>(); - }; - - struct sockaddr_storage their_addr; - socklen_t size = sizeof(their_addr); - int fd = accept(listen_sockfd, (struct sockaddr *)&their_addr, &size); - ERR_FAIL_COND_V(fd == -1, Ref<StreamPeerTCP>()); -#ifndef NO_FCNTL - if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { - WARN_PRINT("Error setting socket as non blocking"); - } -#else - int bval = 1; - if (ioctl(fd, FIONBIO, &bval) < 0) { - WARN_PRINT("Error setting socket as non blocking"); - } -#endif - - Ref<StreamPeerTCPPosix> conn = memnew(StreamPeerTCPPosix); - IP_Address ip; - - int port = 0; - _set_ip_addr_port(ip, port, &their_addr); - - conn->set_socket(fd, ip, port, sock_type); - - return conn; -}; - -void TCPServerPosix::stop() { - - if (listen_sockfd != -1) { - int ret = close(listen_sockfd); - ERR_FAIL_COND(ret != 0); - }; - - listen_sockfd = -1; - sock_type = IP::TYPE_NONE; -}; - -TCPServerPosix::TCPServerPosix() { - - listen_sockfd = -1; - sock_type = IP::TYPE_NONE; -}; - -TCPServerPosix::~TCPServerPosix() { - - stop(); -}; -#endif diff --git a/drivers/unix/tcp_server_posix.h b/drivers/unix/tcp_server_posix.h deleted file mode 100644 index c749314fb3..0000000000 --- a/drivers/unix/tcp_server_posix.h +++ /dev/null @@ -1,58 +0,0 @@ -/*************************************************************************/ -/* tcp_server_posix.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef TCP_SERVER_POSIX_H -#define TCP_SERVER_POSIX_H - -#ifdef UNIX_ENABLED -#include "core/io/tcp_server.h" - -class TCPServerPosix : public TCP_Server { - - int listen_sockfd; - IP::Type sock_type; - - static TCP_Server *_create(); - -public: - virtual Error listen(uint16_t p_port, const IP_Address &p_bind_address = IP_Address("*")); - virtual bool is_connection_available() const; - virtual Ref<StreamPeerTCP> take_connection(); - - virtual void stop(); - - static void make_default(); - - TCPServerPosix(); - ~TCPServerPosix(); -}; - -#endif // TCP_SERVER_POSIX_H -#endif diff --git a/drivers/windows/stream_peer_tcp_winsock.cpp b/drivers/windows/stream_peer_tcp_winsock.cpp deleted file mode 100644 index 19c937170b..0000000000 --- a/drivers/windows/stream_peer_tcp_winsock.cpp +++ /dev/null @@ -1,375 +0,0 @@ -/*************************************************************************/ -/* stream_peer_tcp_winsock.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifdef WINDOWS_ENABLED - -#include "stream_peer_tcp_winsock.h" - -#include <winsock2.h> -#include <ws2tcpip.h> - -#include "drivers/unix/socket_helpers.h" - -int winsock_refcount = 0; - -StreamPeerTCP *StreamPeerTCPWinsock::_create() { - - return memnew(StreamPeerTCPWinsock); -}; - -void StreamPeerTCPWinsock::make_default() { - - StreamPeerTCP::_create = StreamPeerTCPWinsock::_create; - - if (winsock_refcount == 0) { - WSADATA data; - WSAStartup(MAKEWORD(2, 2), &data); - }; - ++winsock_refcount; -}; - -void StreamPeerTCPWinsock::cleanup() { - - --winsock_refcount; - if (winsock_refcount == 0) { - - WSACleanup(); - }; -}; - -Error StreamPeerTCPWinsock::_block(int p_sockfd, bool p_read, bool p_write) const { - - fd_set read, write; - FD_ZERO(&read); - FD_ZERO(&write); - - if (p_read) - FD_SET(p_sockfd, &read); - if (p_write) - FD_SET(p_sockfd, &write); - - int ret = select(p_sockfd + 1, &read, &write, NULL, NULL); // block forever - return ret < 0 ? FAILED : OK; -}; - -Error StreamPeerTCPWinsock::_poll_connection() const { - - ERR_FAIL_COND_V(status != STATUS_CONNECTING || sockfd == INVALID_SOCKET, FAILED); - - struct sockaddr_storage their_addr; - size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port, sock_type); - - if (::connect(sockfd, (struct sockaddr *)&their_addr, addr_size) == SOCKET_ERROR) { - - int err = WSAGetLastError(); - if (err == WSAEISCONN) { - status = STATUS_CONNECTED; - return OK; - }; - - if (err == WSAEINPROGRESS || err == WSAEALREADY) { - return OK; - } - - status = STATUS_ERROR; - return ERR_CONNECTION_ERROR; - } else { - - status = STATUS_CONNECTED; - return OK; - }; - - return OK; -}; - -Error StreamPeerTCPWinsock::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) { - - if (status == STATUS_NONE || status == STATUS_ERROR) { - - return FAILED; - }; - - if (status != STATUS_CONNECTED) { - - if (_poll_connection() != OK) { - - return FAILED; - }; - - if (status != STATUS_CONNECTED) { - r_sent = 0; - return OK; - }; - }; - - int data_to_send = p_bytes; - const uint8_t *offset = p_data; - if (sockfd == -1) return FAILED; - int total_sent = 0; - - while (data_to_send) { - - int sent_amount = send(sockfd, (const char *)offset, data_to_send, 0); - - if (sent_amount == -1) { - - if (WSAGetLastError() != WSAEWOULDBLOCK) { - - perror("Nothing sent"); - disconnect_from_host(); - ERR_PRINT("Server disconnected!\n"); - return FAILED; - }; - - if (!p_block) { - r_sent = total_sent; - return OK; - }; - - _block(sockfd, false, true); - } else { - - data_to_send -= sent_amount; - offset += sent_amount; - total_sent += sent_amount; - }; - } - - r_sent = total_sent; - - return OK; -}; - -Error StreamPeerTCPWinsock::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) { - - if (!is_connected_to_host()) { - - return FAILED; - }; - - if (status != STATUS_CONNECTED) { - - if (_poll_connection() != OK) { - - return FAILED; - }; - - if (status != STATUS_CONNECTED) { - r_received = 0; - return OK; - }; - }; - - int to_read = p_bytes; - int total_read = 0; - - while (to_read) { - - int read = recv(sockfd, (char *)p_buffer + total_read, to_read, 0); - - if (read == -1) { - - if (WSAGetLastError() != WSAEWOULDBLOCK) { - - perror("Nothing read"); - disconnect_from_host(); - ERR_PRINT("Server disconnected!\n"); - return FAILED; - }; - - if (!p_block) { - - r_received = total_read; - return OK; - }; - _block(sockfd, true, false); - } else if (read == 0) { - disconnect_from_host(); - r_received = total_read; - return ERR_FILE_EOF; - } else { - - to_read -= read; - total_read += read; - }; - }; - - r_received = total_read; - - return OK; -}; - -Error StreamPeerTCPWinsock::put_data(const uint8_t *p_data, int p_bytes) { - - int total; - return write(p_data, p_bytes, total, true); -}; - -Error StreamPeerTCPWinsock::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) { - - return write(p_data, p_bytes, r_sent, false); -}; - -Error StreamPeerTCPWinsock::get_data(uint8_t *p_buffer, int p_bytes) { - - int total; - return read(p_buffer, p_bytes, total, true); -}; - -Error StreamPeerTCPWinsock::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) { - - return read(p_buffer, p_bytes, r_received, false); -}; - -StreamPeerTCP::Status StreamPeerTCPWinsock::get_status() const { - - if (status == STATUS_CONNECTING) { - _poll_connection(); - }; - - return status; -}; - -bool StreamPeerTCPWinsock::is_connected_to_host() const { - - if (status == STATUS_NONE || status == STATUS_ERROR) { - - return false; - }; - if (status != STATUS_CONNECTED) { - return true; - }; - - return (sockfd != INVALID_SOCKET); -}; - -void StreamPeerTCPWinsock::disconnect_from_host() { - - if (sockfd != INVALID_SOCKET) - closesocket(sockfd); - sockfd = INVALID_SOCKET; - sock_type = IP::TYPE_NONE; - - status = STATUS_NONE; - - peer_host = IP_Address(); - peer_port = 0; -}; - -void StreamPeerTCPWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_sock_type) { - - sockfd = p_sockfd; - sock_type = p_sock_type; - status = STATUS_CONNECTING; - peer_host = p_host; - peer_port = p_port; -}; - -Error StreamPeerTCPWinsock::connect_to_host(const IP_Address &p_host, uint16_t p_port) { - - ERR_FAIL_COND_V(!p_host.is_valid(), ERR_INVALID_PARAMETER); - - sock_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; - sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP); - if (sockfd == INVALID_SOCKET) { - ERR_PRINT("Socket creation failed!"); - disconnect_from_host(); - //perror("socket"); - return FAILED; - }; - - unsigned long par = 1; - if (ioctlsocket(sockfd, FIONBIO, &par)) { - perror("setting non-block mode"); - disconnect_from_host(); - return FAILED; - }; - - struct sockaddr_storage their_addr; - size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port, sock_type); - - if (::connect(sockfd, (struct sockaddr *)&their_addr, addr_size) == SOCKET_ERROR) { - - if (WSAGetLastError() != WSAEWOULDBLOCK) { - ERR_PRINT("Connection to remote host failed!"); - disconnect_from_host(); - return FAILED; - }; - status = STATUS_CONNECTING; - } else { - status = STATUS_CONNECTED; - }; - - peer_host = p_host; - peer_port = p_port; - - return OK; -}; - -void StreamPeerTCPWinsock::set_no_delay(bool p_enabled) { - ERR_FAIL_COND(!is_connected_to_host()); - int flag = p_enabled ? 1 : 0; - if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)) != 0) { - ERR_PRINT("Unable to set TCP no delay option"); - } -} - -int StreamPeerTCPWinsock::get_available_bytes() const { - - unsigned long len; - int ret = ioctlsocket(sockfd, FIONREAD, &len); - ERR_FAIL_COND_V(ret == -1, 0) - return len; -} - -IP_Address StreamPeerTCPWinsock::get_connected_host() const { - - return peer_host; -}; - -uint16_t StreamPeerTCPWinsock::get_connected_port() const { - - return peer_port; -}; - -StreamPeerTCPWinsock::StreamPeerTCPWinsock() { - - sock_type = IP::TYPE_NONE; - sockfd = INVALID_SOCKET; - status = STATUS_NONE; - peer_port = 0; -}; - -StreamPeerTCPWinsock::~StreamPeerTCPWinsock() { - - disconnect_from_host(); -}; - -#endif diff --git a/drivers/windows/stream_peer_tcp_winsock.h b/drivers/windows/stream_peer_tcp_winsock.h deleted file mode 100644 index 4a50e2f678..0000000000 --- a/drivers/windows/stream_peer_tcp_winsock.h +++ /dev/null @@ -1,92 +0,0 @@ -/*************************************************************************/ -/* stream_peer_tcp_winsock.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifdef WINDOWS_ENABLED - -#ifndef STREAM_PEER_TCP_WINSOCK_H -#define STREAM_PEER_TCP_WINSOCK_H - -#include "core/error_list.h" - -#include "core/io/ip_address.h" -#include "core/io/stream_peer_tcp.h" - -class StreamPeerTCPWinsock : public StreamPeerTCP { - -protected: - mutable Status status; - IP::Type sock_type; - - int sockfd; - - Error _block(int p_sockfd, bool p_read, bool p_write) const; - - Error _poll_connection() const; - - IP_Address peer_host; - int peer_port; - - Error write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block); - Error read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block); - - static StreamPeerTCP *_create(); - -public: - virtual Error connect_to_host(const IP_Address &p_host, uint16_t p_port); - - virtual Error put_data(const uint8_t *p_data, int p_bytes); - virtual Error put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent); - - virtual Error get_data(uint8_t *p_buffer, int p_bytes); - virtual Error get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received); - - virtual int get_available_bytes() const; - - void set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_sock_type); - - virtual IP_Address get_connected_host() const; - virtual uint16_t get_connected_port() const; - - virtual bool is_connected_to_host() const; - virtual Status get_status() const; - virtual void disconnect_from_host(); - - static void make_default(); - static void cleanup(); - - virtual void set_no_delay(bool p_enabled); - - StreamPeerTCPWinsock(); - ~StreamPeerTCPWinsock(); -}; - -#endif // STREAM_PEER_TCP_WINSOCK_H - -#endif diff --git a/drivers/windows/tcp_server_winsock.cpp b/drivers/windows/tcp_server_winsock.cpp deleted file mode 100644 index ddb955549f..0000000000 --- a/drivers/windows/tcp_server_winsock.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/*************************************************************************/ -/* tcp_server_winsock.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifdef WINDOWS_ENABLED - -#include "tcp_server_winsock.h" - -#include "stream_peer_tcp_winsock.h" - -#include <winsock2.h> -#include <ws2tcpip.h> - -#include "drivers/unix/socket_helpers.h" - -extern int winsock_refcount; - -TCP_Server *TCPServerWinsock::_create() { - - return memnew(TCPServerWinsock); -}; - -void TCPServerWinsock::make_default() { - - TCP_Server::_create = TCPServerWinsock::_create; - - if (winsock_refcount == 0) { - WSADATA data; - WSAStartup(MAKEWORD(2, 2), &data); - }; - ++winsock_refcount; -}; - -void TCPServerWinsock::cleanup() { - - --winsock_refcount; - if (winsock_refcount == 0) { - - WSACleanup(); - }; -}; - -Error TCPServerWinsock::listen(uint16_t p_port, const IP_Address &p_bind_address) { - - ERR_FAIL_COND_V(listen_sockfd != -1, ERR_ALREADY_IN_USE); - ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); - - int sockfd; - sock_type = IP::TYPE_ANY; - - // If the bind address is valid use its type as the socket type - if (p_bind_address.is_valid()) - sock_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; - - sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP); - ERR_FAIL_COND_V(sockfd == INVALID_SOCKET, FAILED); - - unsigned long par = 1; - if (ioctlsocket(sockfd, FIONBIO, &par)) { - perror("setting non-block mode"); - stop(); - return FAILED; - }; - - struct sockaddr_storage my_addr; - size_t addr_size = _set_listen_sockaddr(&my_addr, p_port, sock_type, p_bind_address); - - int reuse = 1; - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) { - - printf("REUSEADDR failed!"); - } - - if (bind(sockfd, (struct sockaddr *)&my_addr, addr_size) != SOCKET_ERROR) { - - if (::listen(sockfd, SOMAXCONN) == SOCKET_ERROR) { - - closesocket(sockfd); - ERR_FAIL_V(FAILED); - }; - } else { - closesocket(sockfd); - return ERR_ALREADY_IN_USE; - }; - - if (listen_sockfd != INVALID_SOCKET) { - - stop(); - }; - - listen_sockfd = sockfd; - - return OK; -}; - -bool TCPServerWinsock::is_connection_available() const { - - if (listen_sockfd == -1) { - return false; - }; - - timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 0; - - fd_set pfd; - FD_ZERO(&pfd); - FD_SET(listen_sockfd, &pfd); - - int ret = select(listen_sockfd + 1, &pfd, NULL, NULL, &timeout); - ERR_FAIL_COND_V(ret < 0, 0); - - if (ret && (FD_ISSET(listen_sockfd, &pfd))) { - - return true; - }; - - return false; -}; - -Ref<StreamPeerTCP> TCPServerWinsock::take_connection() { - - if (!is_connection_available()) { - return NULL; - }; - - struct sockaddr_storage their_addr; - int sin_size = sizeof(their_addr); - int fd = accept(listen_sockfd, (struct sockaddr *)&their_addr, &sin_size); - ERR_FAIL_COND_V(fd == INVALID_SOCKET, NULL); - - Ref<StreamPeerTCPWinsock> conn = memnew(StreamPeerTCPWinsock); - IP_Address ip; - int port; - _set_ip_addr_port(ip, port, &their_addr); - - conn->set_socket(fd, ip, port, sock_type); - - return conn; -}; - -void TCPServerWinsock::stop() { - - if (listen_sockfd != INVALID_SOCKET) { - closesocket(listen_sockfd); - }; - - listen_sockfd = -1; - sock_type = IP::TYPE_NONE; -}; - -TCPServerWinsock::TCPServerWinsock() { - - listen_sockfd = INVALID_SOCKET; - sock_type = IP::TYPE_NONE; -}; - -TCPServerWinsock::~TCPServerWinsock() { - - stop(); -}; - -#endif diff --git a/drivers/windows/tcp_server_winsock.h b/drivers/windows/tcp_server_winsock.h deleted file mode 100644 index a6979db42d..0000000000 --- a/drivers/windows/tcp_server_winsock.h +++ /dev/null @@ -1,61 +0,0 @@ -/*************************************************************************/ -/* tcp_server_winsock.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifdef WINDOWS_ENABLED - -#ifndef TCP_SERVER_WINSOCK_H -#define TCP_SERVER_WINSOCK_H - -#include "core/io/tcp_server.h" - -class TCPServerWinsock : public TCP_Server { - - int listen_sockfd; - IP::Type sock_type; - - static TCP_Server *_create(); - -public: - virtual Error listen(uint16_t p_port, const IP_Address &p_bind_address = IP_Address("*")); - virtual bool is_connection_available() const; - virtual Ref<StreamPeerTCP> take_connection(); - - virtual void stop(); //stop listening - - static void make_default(); - static void cleanup(); - - TCPServerWinsock(); - ~TCPServerWinsock(); -}; - -#endif - -#endif diff --git a/editor/fileserver/editor_file_server.cpp b/editor/fileserver/editor_file_server.cpp index d6e89d0573..27fe716855 100644 --- a/editor/fileserver/editor_file_server.cpp +++ b/editor/fileserver/editor_file_server.cpp @@ -330,7 +330,7 @@ void EditorFileServer::stop() { EditorFileServer::EditorFileServer() { - server = TCP_Server::create_ref(); + server.instance(); wait_mutex = Mutex::create(); quit = false; active = false; diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index 43892376b5..b43402e834 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -1952,7 +1952,7 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { inspector->connect("object_id_selected", this, "_scene_tree_property_select_object"); sc->add_child(inspector); - server = TCP_Server::create_ref(); + server.instance(); pending_in_queue = 0; diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index e2edd0c246..5b5f30244e 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -43,8 +43,6 @@ #include "drivers/windows/mutex_windows.h" #include "drivers/windows/rw_lock_windows.h" #include "drivers/windows/semaphore_windows.h" -#include "drivers/windows/stream_peer_tcp_winsock.h" -#include "drivers/windows/tcp_server_winsock.h" #include "main/main.h" #include "platform/windows/windows_terminal_logger.h" #include "servers/audio_server.h" @@ -154,8 +152,6 @@ void OSUWP::initialize_core() { DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_FILESYSTEM); NetSocketPosix::make_default(); - TCPServerWinsock::make_default(); - StreamPeerTCPWinsock::make_default(); // We need to know how often the clock is updated if (!QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second)) diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 580ec37fa4..6723210432 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -42,8 +42,6 @@ #include "drivers/windows/mutex_windows.h" #include "drivers/windows/rw_lock_windows.h" #include "drivers/windows/semaphore_windows.h" -#include "drivers/windows/stream_peer_tcp_winsock.h" -#include "drivers/windows/tcp_server_winsock.h" #include "drivers/windows/thread_windows.h" #include "joypad.h" #include "lang_table.h" @@ -222,8 +220,6 @@ void OS_Windows::initialize_core() { DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_FILESYSTEM); NetSocketPosix::make_default(); - TCPServerWinsock::make_default(); - StreamPeerTCPWinsock::make_default(); // We need to know how often the clock is updated if (!QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second)) @@ -1516,9 +1512,6 @@ void OS_Windows::finalize_core() { timeEndPeriod(1); memdelete(process_map); - - TCPServerWinsock::cleanup(); - StreamPeerTCPWinsock::cleanup(); } void OS_Windows::alert(const String &p_alert, const String &p_title) { |