summaryrefslogtreecommitdiff
path: root/core/io/tcp_server.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/io/tcp_server.cpp')
-rw-r--r--core/io/tcp_server.cpp97
1 files changed, 83 insertions, 14 deletions
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();
}