summaryrefslogtreecommitdiff
path: root/core/io
diff options
context:
space:
mode:
Diffstat (limited to 'core/io')
-rw-r--r--core/io/SCsub3
-rw-r--r--core/io/compression.cpp9
-rw-r--r--core/io/compression.h2
-rw-r--r--core/io/config_file.cpp7
-rw-r--r--core/io/config_file.h2
-rw-r--r--core/io/file_access_buffered.cpp4
-rw-r--r--core/io/file_access_buffered.h7
-rw-r--r--core/io/file_access_compressed.cpp5
-rw-r--r--core/io/file_access_compressed.h4
-rw-r--r--core/io/file_access_encrypted.cpp4
-rw-r--r--core/io/file_access_encrypted.h2
-rw-r--r--core/io/file_access_memory.cpp8
-rw-r--r--core/io/file_access_memory.h2
-rw-r--r--core/io/file_access_network.cpp15
-rw-r--r--core/io/file_access_network.h11
-rw-r--r--core/io/file_access_pack.cpp7
-rw-r--r--core/io/file_access_pack.h10
-rw-r--r--core/io/file_access_zip.h4
-rw-r--r--core/io/http_client.cpp56
-rw-r--r--core/io/http_client.h8
-rw-r--r--core/io/image_loader.cpp4
-rw-r--r--core/io/image_loader.h10
-rw-r--r--core/io/ip.cpp7
-rw-r--r--core/io/ip.h4
-rw-r--r--core/io/ip_address.h2
-rw-r--r--core/io/json.cpp3
-rw-r--r--core/io/json.h2
-rw-r--r--core/io/logger.cpp10
-rw-r--r--core/io/logger.h9
-rw-r--r--core/io/marshalls.cpp22
-rw-r--r--core/io/marshalls.h6
-rw-r--r--core/io/multiplayer_api.cpp191
-rw-r--r--core/io/multiplayer_api.h9
-rw-r--r--core/io/net_socket.cpp42
-rw-r--r--core/io/net_socket.h79
-rw-r--r--core/io/networked_multiplayer_peer.h2
-rw-r--r--core/io/packet_peer.cpp5
-rw-r--r--core/io/packet_peer.h7
-rw-r--r--core/io/packet_peer_udp.cpp197
-rw-r--r--core/io/packet_peer_udp.h42
-rw-r--r--core/io/pck_packer.cpp3
-rw-r--r--core/io/resource_format_binary.cpp4
-rw-r--r--core/io/resource_format_binary.h7
-rw-r--r--core/io/resource_import.cpp4
-rw-r--r--core/io/resource_import.h3
-rw-r--r--core/io/resource_loader.cpp30
-rw-r--r--core/io/resource_loader.h10
-rw-r--r--core/io/resource_saver.cpp11
-rw-r--r--core/io/resource_saver.h4
-rw-r--r--core/io/stream_peer.cpp18
-rw-r--r--core/io/stream_peer.h7
-rw-r--r--core/io/stream_peer_ssl.cpp63
-rw-r--r--core/io/stream_peer_ssl.h7
-rw-r--r--core/io/stream_peer_tcp.cpp311
-rw-r--r--core/io/stream_peer_tcp.h45
-rw-r--r--core/io/tcp_server.cpp97
-rw-r--r--core/io/tcp_server.h25
-rw-r--r--core/io/translation_loader_po.cpp5
-rw-r--r--core/io/translation_loader_po.h7
-rw-r--r--core/io/xml_parser.cpp4
-rw-r--r--core/io/xml_parser.h8
-rw-r--r--core/io/zip_io.cpp137
-rw-r--r--core/io/zip_io.h114
63 files changed, 1304 insertions, 443 deletions
diff --git a/core/io/SCsub b/core/io/SCsub
index 79b56cb716..1c5f954470 100644
--- a/core/io/SCsub
+++ b/core/io/SCsub
@@ -3,6 +3,3 @@
Import('env')
env.add_source_files(env.core_sources, "*.cpp")
-
-Export('env')
-
diff --git a/core/io/compression.cpp b/core/io/compression.cpp
index bc3bfcf356..3c0b6541bd 100644
--- a/core/io/compression.cpp
+++ b/core/io/compression.cpp
@@ -29,9 +29,10 @@
/*************************************************************************/
#include "compression.h"
-#include "os/copymem.h"
-#include "project_settings.h"
-#include "zip_io.h"
+
+#include "core/io/zip_io.h"
+#include "core/os/copymem.h"
+#include "core/project_settings.h"
#include "thirdparty/misc/fastlz.h"
@@ -174,7 +175,7 @@ int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p
} break;
case MODE_ZSTD: {
ZSTD_DCtx *dctx = ZSTD_createDCtx();
- if (zstd_long_distance_matching) ZSTD_DCtx_setMaxWindowSize(dctx, 1 << zstd_window_log_size);
+ if (zstd_long_distance_matching) ZSTD_DCtx_setMaxWindowSize(dctx, (size_t)1 << zstd_window_log_size);
int ret = ZSTD_decompressDCtx(dctx, p_dst, p_dst_max_size, p_src, p_src_size);
ZSTD_freeDCtx(dctx);
return ret;
diff --git a/core/io/compression.h b/core/io/compression.h
index a0ccd539cb..2f770e6aee 100644
--- a/core/io/compression.h
+++ b/core/io/compression.h
@@ -31,7 +31,7 @@
#ifndef COMPRESSION_H
#define COMPRESSION_H
-#include "typedefs.h"
+#include "core/typedefs.h"
class Compression {
diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp
index aa06ae5cc0..e2bc0f5d8f 100644
--- a/core/io/config_file.cpp
+++ b/core/io/config_file.cpp
@@ -29,9 +29,10 @@
/*************************************************************************/
#include "config_file.h"
-#include "os/file_access.h"
-#include "os/keyboard.h"
-#include "variant_parser.h"
+
+#include "core/os/file_access.h"
+#include "core/os/keyboard.h"
+#include "core/variant_parser.h"
PoolStringArray ConfigFile::_get_sections() const {
diff --git a/core/io/config_file.h b/core/io/config_file.h
index ac749bed76..2bc439d413 100644
--- a/core/io/config_file.h
+++ b/core/io/config_file.h
@@ -32,7 +32,7 @@
#define CONFIG_FILE_H
#include "core/ordered_hash_map.h"
-#include "reference.h"
+#include "core/reference.h"
class ConfigFile : public Reference {
diff --git a/core/io/file_access_buffered.cpp b/core/io/file_access_buffered.cpp
index dcaf99e24a..d44c8a9585 100644
--- a/core/io/file_access_buffered.cpp
+++ b/core/io/file_access_buffered.cpp
@@ -30,9 +30,7 @@
#include "file_access_buffered.h"
-#include <string.h>
-
-#include "error_macros.h"
+#include "core/error_macros.h"
Error FileAccessBuffered::set_error(Error p_error) const {
diff --git a/core/io/file_access_buffered.h b/core/io/file_access_buffered.h
index f4ed47d6bc..a36a9a4603 100644
--- a/core/io/file_access_buffered.h
+++ b/core/io/file_access_buffered.h
@@ -31,10 +31,9 @@
#ifndef FILE_ACCESS_BUFFERED_H
#define FILE_ACCESS_BUFFERED_H
-#include "os/file_access.h"
-
-#include "dvector.h"
-#include "ustring.h"
+#include "core/dvector.h"
+#include "core/os/file_access.h"
+#include "core/ustring.h"
class FileAccessBuffered : public FileAccess {
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index d6547ba19f..645d97ae7e 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -29,7 +29,9 @@
/*************************************************************************/
#include "file_access_compressed.h"
-#include "print_string.h"
+
+#include "core/print_string.h"
+
void FileAccessCompressed::configure(const String &p_magic, Compression::Mode p_mode, int p_block_size) {
magic = p_magic.ascii().get_data();
@@ -291,7 +293,6 @@ uint8_t FileAccessCompressed::get_8() const {
} else {
read_block--;
at_end = true;
- ret = 0;
}
}
diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h
index 587f58a7c6..5be42a6d32 100644
--- a/core/io/file_access_compressed.h
+++ b/core/io/file_access_compressed.h
@@ -31,8 +31,8 @@
#ifndef FILE_ACCESS_COMPRESSED_H
#define FILE_ACCESS_COMPRESSED_H
-#include "io/compression.h"
-#include "os/file_access.h"
+#include "core/io/compression.h"
+#include "core/os/file_access.h"
class FileAccessCompressed : public FileAccess {
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index 812e881114..28bf55b962 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -30,9 +30,9 @@
#include "file_access_encrypted.h"
+#include "core/os/copymem.h"
+#include "core/print_string.h"
#include "core/variant.h"
-#include "os/copymem.h"
-#include "print_string.h"
#include "thirdparty/misc/aes256.h"
#include "thirdparty/misc/md5.h"
diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h
index b9365a9fd0..873dbfa7e8 100644
--- a/core/io/file_access_encrypted.h
+++ b/core/io/file_access_encrypted.h
@@ -31,7 +31,7 @@
#ifndef FILE_ACCESS_ENCRYPTED_H
#define FILE_ACCESS_ENCRYPTED_H
-#include "os/file_access.h"
+#include "core/os/file_access.h"
class FileAccessEncrypted : public FileAccess {
public:
diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp
index c4eb2848b1..4c2aa4294d 100644
--- a/core/io/file_access_memory.cpp
+++ b/core/io/file_access_memory.cpp
@@ -30,10 +30,10 @@
#include "file_access_memory.h"
-#include "map.h"
-#include "os/copymem.h"
-#include "os/dir_access.h"
-#include "project_settings.h"
+#include "core/map.h"
+#include "core/os/copymem.h"
+#include "core/os/dir_access.h"
+#include "core/project_settings.h"
static Map<String, Vector<uint8_t> > *files = NULL;
diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h
index 2136f4cc0c..e474fb0d05 100644
--- a/core/io/file_access_memory.h
+++ b/core/io/file_access_memory.h
@@ -31,7 +31,7 @@
#ifndef FILE_ACCESS_MEMORY_H
#define FILE_ACCESS_MEMORY_H
-#include "os/file_access.h"
+#include "core/os/file_access.h"
class FileAccessMemory : public FileAccess {
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index d72d3ca9f1..b9544ac166 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -29,10 +29,11 @@
/*************************************************************************/
#include "file_access_network.h"
-#include "io/ip.h"
-#include "marshalls.h"
-#include "os/os.h"
-#include "project_settings.h"
+
+#include "core/io/ip.h"
+#include "core/io/marshalls.h"
+#include "core/os/os.h"
+#include "core/project_settings.h"
//#define DEBUG_PRINT(m_p) print_line(m_p)
//#define DEBUG_TIME(m_what) printf("MS: %s - %lli\n",m_what,OS::get_singleton()->get_ticks_usec());
@@ -226,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;
}
@@ -499,8 +500,9 @@ uint64_t FileAccessNetwork::_get_modified_time(const String &p_file) {
void FileAccessNetwork::configure() {
GLOBAL_DEF("network/remote_fs/page_size", 65536);
+ ProjectSettings::get_singleton()->set_custom_property_info("network/remote_fs/page_size", PropertyInfo(Variant::INT, "network/remote_fs/page_size", PROPERTY_HINT_RANGE, "1,65536,1,or_greater")); //is used as denominator and can't be zero
GLOBAL_DEF("network/remote_fs/page_read_ahead", 4);
- GLOBAL_DEF("network/remote_fs/max_pages", 20);
+ ProjectSettings::get_singleton()->set_custom_property_info("network/remote_fs/page_read_ahead", PropertyInfo(Variant::INT, "network/remote_fs/page_read_ahead", PROPERTY_HINT_RANGE, "0,8,1,or_greater"));
}
FileAccessNetwork::FileAccessNetwork() {
@@ -518,7 +520,6 @@ FileAccessNetwork::FileAccessNetwork() {
nc->unlock_mutex();
page_size = GLOBAL_GET("network/remote_fs/page_size");
read_ahead = GLOBAL_GET("network/remote_fs/page_read_ahead");
- max_pages = GLOBAL_GET("network/remote_fs/max_pages");
last_activity_val = 0;
waiting_on_page = -1;
last_page = -1;
diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h
index be9bdb1af6..c929e8446d 100644
--- a/core/io/file_access_network.h
+++ b/core/io/file_access_network.h
@@ -31,10 +31,10 @@
#ifndef FILE_ACCESS_NETWORK_H
#define FILE_ACCESS_NETWORK_H
-#include "io/stream_peer_tcp.h"
-#include "os/file_access.h"
-#include "os/semaphore.h"
-#include "os/thread.h"
+#include "core/io/stream_peer_tcp.h"
+#include "core/os/file_access.h"
+#include "core/os/semaphore.h"
+#include "core/os/thread.h"
class FileAccessNetwork;
@@ -47,8 +47,6 @@ class FileAccessNetworkClient {
int size;
};
- int ml;
-
List<BlockRequest> block_requests;
Semaphore *sem;
@@ -100,7 +98,6 @@ class FileAccessNetwork : public FileAccess {
int page_size;
int read_ahead;
- int max_pages;
mutable int waiting_on_page;
mutable int last_activity_val;
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index efb4c7a073..40f756ba9a 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -29,7 +29,8 @@
/*************************************************************************/
#include "file_access_pack.h"
-#include "version.h"
+
+#include "core/version.h"
#include <stdio.h>
@@ -168,11 +169,11 @@ bool PackedSourcePCK::try_open_pack(const String &p_path) {
uint32_t version = f->get_32();
uint32_t ver_major = f->get_32();
uint32_t ver_minor = f->get_32();
- uint32_t ver_rev = f->get_32();
+ f->get_32(); // ver_rev
ERR_EXPLAIN("Pack version unsupported: " + itos(version));
ERR_FAIL_COND_V(version != PACK_VERSION, false);
- ERR_EXPLAIN("Pack created with a newer version of the engine: " + itos(ver_major) + "." + itos(ver_minor) + "." + itos(ver_rev));
+ ERR_EXPLAIN("Pack created with a newer version of the engine: " + itos(ver_major) + "." + itos(ver_minor));
ERR_FAIL_COND_V(ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), false);
for (int i = 0; i < 16; i++) {
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index f29e431d9a..9e31bcf88a 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -31,11 +31,11 @@
#ifndef FILE_ACCESS_PACK_H
#define FILE_ACCESS_PACK_H
-#include "list.h"
-#include "map.h"
-#include "os/dir_access.h"
-#include "os/file_access.h"
-#include "print_string.h"
+#include "core/list.h"
+#include "core/map.h"
+#include "core/os/dir_access.h"
+#include "core/os/file_access.h"
+#include "core/print_string.h"
class PackSource;
diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h
index df83575f6a..9bb1ad221a 100644
--- a/core/io/file_access_zip.h
+++ b/core/io/file_access_zip.h
@@ -34,7 +34,7 @@
#define FILE_ACCESS_ZIP_H
#include "core/io/file_access_pack.h"
-#include "map.h"
+#include "core/map.h"
#include "thirdparty/minizip/unzip.h"
@@ -90,8 +90,6 @@ class FileAccessZip : public FileAccess {
mutable bool at_eof;
- ZipArchive *archive;
-
public:
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp
index 2425bb6d69..36dd688e77 100644
--- a/core/io/http_client.cpp
+++ b/core/io/http_client.cpp
@@ -29,8 +29,9 @@
/*************************************************************************/
#include "http_client.h"
-#include "io/stream_peer_ssl.h"
-#include "version.h"
+
+#include "core/io/stream_peer_ssl.h"
+#include "core/version.h"
const char *HTTPClient::_methods[METHOD_MAX] = {
"GET",
@@ -274,7 +275,7 @@ void HTTPClient::close() {
response_headers.clear();
response_str.clear();
- body_size = 0;
+ body_size = -1;
body_left = 0;
chunk_left = 0;
read_until_eof = false;
@@ -348,7 +349,7 @@ Error HTTPClient::poll() {
}
if (ssl->get_status() == StreamPeerSSL::STATUS_CONNECTED) {
- // Handshake has been successfull
+ // Handshake has been successful
handshaking = false;
status = STATUS_CONNECTED;
return OK;
@@ -373,7 +374,20 @@ Error HTTPClient::poll() {
} break;
}
} break;
+ case STATUS_BODY:
case STATUS_CONNECTED: {
+ // Check if we are still connected
+ if (ssl) {
+ Ref<StreamPeerSSL> tmp = connection;
+ tmp->poll();
+ if (tmp->get_status() != StreamPeerSSL::STATUS_CONNECTED) {
+ status = STATUS_CONNECTION_ERROR;
+ return ERR_CONNECTION_ERROR;
+ }
+ } else if (tcp_connection->get_status() != StreamPeerTCP::STATUS_CONNECTED) {
+ status = STATUS_CONNECTION_ERROR;
+ return ERR_CONNECTION_ERROR;
+ }
// Connection established, requests can now be made
return OK;
} break;
@@ -403,7 +417,7 @@ Error HTTPClient::poll() {
String response;
response.parse_utf8((const char *)response_str.ptr());
Vector<String> responses = response.split("\n");
- body_size = 0;
+ body_size = -1;
chunked = false;
body_left = 0;
chunk_left = 0;
@@ -447,7 +461,7 @@ Error HTTPClient::poll() {
}
}
- if (body_size || chunked) {
+ if (body_size != -1 || chunked) {
status = STATUS_BODY;
} else if (!keep_alive) {
@@ -467,7 +481,8 @@ Error HTTPClient::poll() {
case STATUS_DISCONNECTED: {
return ERR_UNCONFIGURED;
} break;
- case STATUS_CONNECTION_ERROR: {
+ case STATUS_CONNECTION_ERROR:
+ case STATUS_SSL_HANDSHAKE_ERROR: {
return ERR_CONNECTION_ERROR;
} break;
case STATUS_CANT_CONNECT: {
@@ -664,11 +679,24 @@ Error HTTPClient::_get_http_data(uint8_t *p_buffer, int p_bytes, int &r_received
if (blocking) {
- Error err = connection->get_data(p_buffer, p_bytes);
- if (err == OK)
- r_received = p_bytes;
- else
- r_received = 0;
+ // We can't use StreamPeer.get_data, since when reaching EOF we will get an
+ // error without knowing how many bytes we received.
+ Error err = ERR_FILE_EOF;
+ int read = 0;
+ int left = p_bytes;
+ r_received = 0;
+ while (left > 0) {
+ err = connection->get_partial_data(p_buffer + r_received, left, read);
+ if (err == OK) {
+ r_received += read;
+ } else if (err == ERR_FILE_EOF) {
+ r_received += read;
+ return err;
+ } else {
+ return err;
+ }
+ left -= read;
+ }
return err;
} else {
return connection->get_partial_data(p_buffer, p_bytes, r_received);
@@ -682,11 +710,11 @@ 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;
- body_size = 0;
+ body_size = -1;
chunked = false;
body_left = 0;
read_until_eof = false;
diff --git a/core/io/http_client.h b/core/io/http_client.h
index 82b56b01db..9e674e4c1d 100644
--- a/core/io/http_client.h
+++ b/core/io/http_client.h
@@ -31,10 +31,10 @@
#ifndef HTTP_CLIENT_H
#define HTTP_CLIENT_H
-#include "io/ip.h"
-#include "io/stream_peer.h"
-#include "io/stream_peer_tcp.h"
-#include "reference.h"
+#include "core/io/ip.h"
+#include "core/io/stream_peer.h"
+#include "core/io/stream_peer_tcp.h"
+#include "core/reference.h"
class HTTPClient : public Reference {
diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp
index b8fd13d67c..3ae9ff676c 100644
--- a/core/io/image_loader.cpp
+++ b/core/io/image_loader.cpp
@@ -30,7 +30,8 @@
#include "image_loader.h"
-#include "print_string.h"
+#include "core/print_string.h"
+
bool ImageFormatLoader::recognize(const String &p_extension) const {
List<String> extensions;
@@ -117,7 +118,6 @@ RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_origin
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
- memdelete(f);
return RES();
}
diff --git a/core/io/image_loader.h b/core/io/image_loader.h
index fbb654c326..561f275e0c 100644
--- a/core/io/image_loader.h
+++ b/core/io/image_loader.h
@@ -31,11 +31,11 @@
#ifndef IMAGE_LOADER_H
#define IMAGE_LOADER_H
-#include "image.h"
-#include "io/resource_loader.h"
-#include "list.h"
-#include "os/file_access.h"
-#include "ustring.h"
+#include "core/image.h"
+#include "core/io/resource_loader.h"
+#include "core/list.h"
+#include "core/os/file_access.h"
+#include "core/ustring.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
diff --git a/core/io/ip.cpp b/core/io/ip.cpp
index 82c94ca0b2..f56e850796 100644
--- a/core/io/ip.cpp
+++ b/core/io/ip.cpp
@@ -29,9 +29,10 @@
/*************************************************************************/
#include "ip.h"
-#include "hash_map.h"
-#include "os/semaphore.h"
-#include "os/thread.h"
+
+#include "core/hash_map.h"
+#include "core/os/semaphore.h"
+#include "core/os/thread.h"
VARIANT_ENUM_CAST(IP::ResolverStatus);
diff --git a/core/io/ip.h b/core/io/ip.h
index d55b05b6fe..967f04a4bd 100644
--- a/core/io/ip.h
+++ b/core/io/ip.h
@@ -31,8 +31,8 @@
#ifndef IP_H
#define IP_H
-#include "io/ip_address.h"
-#include "os/os.h"
+#include "core/io/ip_address.h"
+#include "core/os/os.h"
struct _IP_ResolverPrivate;
diff --git a/core/io/ip_address.h b/core/io/ip_address.h
index d7b031b960..607ce81ef4 100644
--- a/core/io/ip_address.h
+++ b/core/io/ip_address.h
@@ -31,7 +31,7 @@
#ifndef IP_ADDRESS_H
#define IP_ADDRESS_H
-#include "ustring.h"
+#include "core/ustring.h"
struct IP_Address {
diff --git a/core/io/json.cpp b/core/io/json.cpp
index 7b2c5a62df..26e18828e5 100644
--- a/core/io/json.cpp
+++ b/core/io/json.cpp
@@ -29,7 +29,8 @@
/*************************************************************************/
#include "json.h"
-#include "print_string.h"
+
+#include "core/print_string.h"
const char *JSON::tk_name[TK_MAX] = {
"'{'",
diff --git a/core/io/json.h b/core/io/json.h
index 9c12423798..af6c463331 100644
--- a/core/io/json.h
+++ b/core/io/json.h
@@ -31,7 +31,7 @@
#ifndef JSON_H
#define JSON_H
-#include "variant.h"
+#include "core/variant.h"
class JSON {
diff --git a/core/io/logger.cpp b/core/io/logger.cpp
index 786bec461b..01755c8ee9 100644
--- a/core/io/logger.cpp
+++ b/core/io/logger.cpp
@@ -30,9 +30,9 @@
#include "logger.h"
-#include "os/dir_access.h"
-#include "os/os.h"
-#include "print_string.h"
+#include "core/os/dir_access.h"
+#include "core/os/os.h"
+#include "core/print_string.h"
// va_copy was defined in the C99, but not in C++ standards before C++11.
// When you compile C++ without --std=c++<XX> option, compilers still define
@@ -45,6 +45,10 @@
#endif
#endif
+#if defined(MINGW_ENABLED) || defined(_MSC_VER)
+#define sprintf sprintf_s
+#endif
+
bool Logger::should_log(bool p_err) {
return (!p_err || _print_error_enabled) && (p_err || _print_line_enabled);
}
diff --git a/core/io/logger.h b/core/io/logger.h
index 631e7a0589..d32b43b030 100644
--- a/core/io/logger.h
+++ b/core/io/logger.h
@@ -31,9 +31,10 @@
#ifndef LOGGER_H
#define LOGGER_H
-#include "os/file_access.h"
-#include "ustring.h"
-#include "vector.h"
+#include "core/os/file_access.h"
+#include "core/ustring.h"
+#include "core/vector.h"
+
#include <stdarg.h>
class Logger {
@@ -106,4 +107,4 @@ public:
virtual ~CompositeLogger();
};
-#endif \ No newline at end of file
+#endif
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index e97df0c261..6338cee39d 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -29,9 +29,11 @@
/*************************************************************************/
#include "marshalls.h"
-#include "os/keyboard.h"
-#include "print_string.h"
-#include "reference.h"
+
+#include "core/os/keyboard.h"
+#include "core/print_string.h"
+#include "core/reference.h"
+
#include <limits.h>
#include <stdio.h>
@@ -805,7 +807,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
case Variant::INT: {
int64_t val = p_variant;
- if (val > 0x7FFFFFFF || val < -0x80000000) {
+ if (val > (int64_t)INT_MAX || val < (int64_t)INT_MIN) {
flags |= ENCODE_FLAG_64;
}
} break;
@@ -822,6 +824,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
flags |= ENCODE_FLAG_OBJECT_AS_ID;
}
} break;
+ default: {} // nothing to do at this stage
}
if (buf) {
@@ -847,17 +850,16 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
} break;
case Variant::INT: {
- int64_t val = p_variant;
- if (val > 0x7FFFFFFF || val < -0x80000000) {
+ if (flags & ENCODE_FLAG_64) {
//64 bits
if (buf) {
- encode_uint64(val, buf);
+ encode_uint64(p_variant.operator int64_t(), buf);
}
r_len += 8;
} else {
if (buf) {
- encode_uint32(int32_t(val), buf);
+ encode_uint32(p_variant.operator int32_t(), buf);
}
r_len += 4;
@@ -865,9 +867,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
} break;
case Variant::REAL: {
- double d = p_variant;
- float f = d;
- if (double(f) != d) {
+ if (flags & ENCODE_FLAG_64) {
if (buf) {
encode_double(p_variant.operator double(), buf);
}
diff --git a/core/io/marshalls.h b/core/io/marshalls.h
index 381e4e3d20..1284520945 100644
--- a/core/io/marshalls.h
+++ b/core/io/marshalls.h
@@ -31,10 +31,10 @@
#ifndef MARSHALLS_H
#define MARSHALLS_H
-#include "typedefs.h"
+#include "core/reference.h"
+#include "core/typedefs.h"
+#include "core/variant.h"
-#include "reference.h"
-#include "variant.h"
/**
* Miscellaneous helpers for marshalling data types, and encoding
* in an endian independent way
diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp
index 8e67f1c97a..b3f0a76a80 100644
--- a/core/io/multiplayer_api.cpp
+++ b/core/io/multiplayer_api.cpp
@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "core/io/multiplayer_api.h"
+#include "multiplayer_api.h"
+
#include "core/io/marshalls.h"
#include "scene/main/node.h"
@@ -37,24 +38,26 @@ _FORCE_INLINE_ bool _should_call_local(MultiplayerAPI::RPCMode mode, bool is_mas
switch (mode) {
case MultiplayerAPI::RPC_MODE_DISABLED: {
- //do nothing
+ // Do nothing.
} break;
case MultiplayerAPI::RPC_MODE_REMOTE: {
- //do nothing also, no need to call local
+ // Do nothing also. Remote cannot produce a local call.
} break;
+ case MultiplayerAPI::RPC_MODE_MASTERSYNC: {
+ if (is_master)
+ r_skip_rpc = true; // I am the master, so skip remote call.
+ } // Do not break, fall over to other sync.
case MultiplayerAPI::RPC_MODE_REMOTESYNC:
- case MultiplayerAPI::RPC_MODE_MASTERSYNC:
- case MultiplayerAPI::RPC_MODE_SLAVESYNC:
- case MultiplayerAPI::RPC_MODE_SYNC: {
- //call it, sync always results in call
+ case MultiplayerAPI::RPC_MODE_PUPPETSYNC: {
+ // Call it, sync always results in a local call.
return true;
} break;
case MultiplayerAPI::RPC_MODE_MASTER: {
if (is_master)
- r_skip_rpc = true; //no other master so..
+ r_skip_rpc = true; // I am the master, so skip remote call.
return is_master;
} break;
- case MultiplayerAPI::RPC_MODE_SLAVE: {
+ case MultiplayerAPI::RPC_MODE_PUPPET: {
return !is_master;
} break;
}
@@ -67,19 +70,16 @@ _FORCE_INLINE_ bool _can_call_mode(Node *p_node, MultiplayerAPI::RPCMode mode, i
case MultiplayerAPI::RPC_MODE_DISABLED: {
return false;
} break;
- case MultiplayerAPI::RPC_MODE_REMOTE: {
- return true;
- } break;
- case MultiplayerAPI::RPC_MODE_REMOTESYNC:
- case MultiplayerAPI::RPC_MODE_SYNC: {
+ case MultiplayerAPI::RPC_MODE_REMOTE:
+ case MultiplayerAPI::RPC_MODE_REMOTESYNC: {
return true;
} break;
case MultiplayerAPI::RPC_MODE_MASTERSYNC:
case MultiplayerAPI::RPC_MODE_MASTER: {
return p_node->is_network_master();
} break;
- case MultiplayerAPI::RPC_MODE_SLAVESYNC:
- case MultiplayerAPI::RPC_MODE_SLAVE: {
+ case MultiplayerAPI::RPC_MODE_PUPPETSYNC:
+ case MultiplayerAPI::RPC_MODE_PUPPET: {
return !p_node->is_network_master() && p_remote_id == p_node->get_network_master();
} break;
}
@@ -94,7 +94,7 @@ void MultiplayerAPI::poll() {
network_peer->poll();
- if (!network_peer.is_valid()) //it's possible that polling might have resulted in a disconnection, so check here
+ if (!network_peer.is_valid()) // It's possible that polling might have resulted in a disconnection, so check here.
return;
while (network_peer->get_available_packet_count()) {
@@ -113,7 +113,7 @@ void MultiplayerAPI::poll() {
rpc_sender_id = 0;
if (!network_peer.is_valid()) {
- break; //it's also possible that a packet or RPC caused a disconnection, so also check here
+ break; // It's also possible that a packet or RPC caused a disconnection, so also check here.
}
}
}
@@ -160,7 +160,9 @@ Ref<NetworkedMultiplayerPeer> MultiplayerAPI::get_network_peer() const {
void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_packet_len) {
+ ERR_EXPLAIN("Multiplayer root node was not initialized. If you are using custom multiplayer, remember to set the root node via MultiplayerAPI.set_root_node before using it");
ERR_FAIL_COND(root_node == NULL);
+ ERR_EXPLAIN("Invalid packet received. Size too small.");
ERR_FAIL_COND(p_packet_len < 1);
uint8_t packet_type = p_packet[0];
@@ -180,13 +182,15 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_
case NETWORK_COMMAND_REMOTE_CALL:
case NETWORK_COMMAND_REMOTE_SET: {
+ ERR_EXPLAIN("Invalid packet received. Size too small.");
ERR_FAIL_COND(p_packet_len < 6);
Node *node = _process_get_node(p_from, p_packet, p_packet_len);
+ ERR_EXPLAIN("Invalid packet received. Requested node was not found.");
ERR_FAIL_COND(node == NULL);
- //detect cstring end
+ // Detect cstring end.
int len_end = 5;
for (; len_end < p_packet_len; len_end++) {
if (p_packet[len_end] == 0) {
@@ -194,6 +198,7 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_
}
}
+ ERR_EXPLAIN("Invalid packet received. Size too small.");
ERR_FAIL_COND(len_end >= p_packet_len);
StringName name = String::utf8((const char *)&p_packet[5]);
@@ -222,9 +227,11 @@ Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, int
Node *node = NULL;
if (target & 0x80000000) {
- //use full path (not cached yet)
+ // Use full path (not cached yet).
int ofs = target & 0x7FFFFFFF;
+
+ ERR_EXPLAIN("Invalid packet received. Size smaller than declared.");
ERR_FAIL_COND_V(ofs >= p_packet_len, NULL);
String paths;
@@ -237,17 +244,19 @@ Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, int
if (!node)
ERR_PRINTS("Failed to get path from RPC: " + String(np));
} else {
- //use cached path
+ // Use cached path.
int id = target;
Map<int, PathGetCache>::Element *E = path_get_cache.find(p_from);
+ ERR_EXPLAIN("Invalid packet received. Requests invalid peer cache.");
ERR_FAIL_COND_V(!E, NULL);
Map<int, PathGetCache::NodeInfo>::Element *F = E->get().nodes.find(id);
+ ERR_EXPLAIN("Invalid packet received. Unabled to find requested cached node.");
ERR_FAIL_COND_V(!F, NULL);
PathGetCache::NodeInfo *ni = &F->get();
- //do proper caching later
+ // Do proper caching later.
node = root_node->get_node(ni->path);
if (!node)
@@ -258,9 +267,10 @@ Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, int
void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) {
+ ERR_EXPLAIN("Invalid packet received. Size too small.");
ERR_FAIL_COND(p_offset >= p_packet_len);
- // Check that remote can call the RPC on this node
+ // Check that remote can call the RPC on this node.
RPCMode rpc_mode = RPC_MODE_DISABLED;
const Map<StringName, RPCMode>::Element *E = p_node->get_node_rpc_mode(p_name);
if (E) {
@@ -268,6 +278,8 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_
} else if (p_node->get_script_instance()) {
rpc_mode = p_node->get_script_instance()->get_rpc_mode(p_name);
}
+
+ ERR_EXPLAIN("RPC '" + String(p_name) + "' is not allowed from: " + itos(p_from) + ". Mode is " + itos((int)rpc_mode) + ", master is " + itos(p_node->get_network_master()) + ".");
ERR_FAIL_COND(!_can_call_mode(p_node, rpc_mode, p_from));
int argc = p_packet[p_offset];
@@ -280,11 +292,14 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_
for (int i = 0; i < argc; i++) {
+ ERR_EXPLAIN("Invalid packet received. Size too small.");
ERR_FAIL_COND(p_offset >= p_packet_len);
+
int vlen;
Error err = decode_variant(args.write[i], &p_packet[p_offset], p_packet_len - p_offset, &vlen);
+ ERR_EXPLAIN("Invalid packet received. Unable to decode RPC argument.");
ERR_FAIL_COND(err != OK);
- //args[i]=p_packet[3+i];
+
argp.write[i] = &args[i];
p_offset += vlen;
}
@@ -301,9 +316,10 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_
void MultiplayerAPI::_process_rset(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) {
+ ERR_EXPLAIN("Invalid packet received. Size too small.");
ERR_FAIL_COND(p_offset >= p_packet_len);
- // Check that remote can call the RSET on this node
+ // Check that remote can call the RSET on this node.
RPCMode rset_mode = RPC_MODE_DISABLED;
const Map<StringName, RPCMode>::Element *E = p_node->get_node_rset_mode(p_name);
if (E) {
@@ -311,10 +327,15 @@ void MultiplayerAPI::_process_rset(Node *p_node, const StringName &p_name, int p
} else if (p_node->get_script_instance()) {
rset_mode = p_node->get_script_instance()->get_rset_mode(p_name);
}
+
+ ERR_EXPLAIN("RSET '" + String(p_name) + "' is not allowed from: " + itos(p_from) + ". Mode is " + itos((int)rset_mode) + ", master is " + itos(p_node->get_network_master()) + ".");
ERR_FAIL_COND(!_can_call_mode(p_node, rset_mode, p_from));
Variant value;
- decode_variant(value, &p_packet[p_offset], p_packet_len - p_offset);
+ Error err = decode_variant(value, &p_packet[p_offset], p_packet_len - p_offset);
+
+ ERR_EXPLAIN("Invalid packet received. Unable to decode RSET value.");
+ ERR_FAIL_COND(err != OK);
bool valid;
@@ -327,6 +348,7 @@ void MultiplayerAPI::_process_rset(Node *p_node, const StringName &p_name, int p
void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len) {
+ ERR_EXPLAIN("Invalid packet received. Size too small.");
ERR_FAIL_COND(p_packet_len < 5);
int id = decode_uint32(&p_packet[1]);
@@ -345,9 +367,7 @@ void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet,
path_get_cache[p_from].nodes[id] = ni;
- //send ack
-
- //encode path
+ // Encode path to send ack.
CharString pname = String(path).utf8();
int len = encode_cstring(pname.get_data(), NULL);
@@ -364,6 +384,7 @@ void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet,
void MultiplayerAPI::_process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len) {
+ ERR_EXPLAIN("Invalid packet received. Size too small.");
ERR_FAIL_COND(p_packet_len < 2);
String paths;
@@ -372,31 +393,33 @@ void MultiplayerAPI::_process_confirm_path(int p_from, const uint8_t *p_packet,
NodePath path = paths;
PathSentCache *psc = path_send_cache.getptr(path);
+ ERR_EXPLAIN("Invalid packet received. Tries to confirm a path which was not found in cache.");
ERR_FAIL_COND(!psc);
Map<int, bool>::Element *E = psc->confirmed_peers.find(p_from);
+ ERR_EXPLAIN("Invalid packet received. Source peer was not found in cache for the given path.");
ERR_FAIL_COND(!E);
E->get() = true;
}
bool MultiplayerAPI::_send_confirm_path(NodePath p_path, PathSentCache *psc, int p_target) {
bool has_all_peers = true;
- List<int> peers_to_add; //if one is missing, take note to add it
+ List<int> peers_to_add; // If one is missing, take note to add it.
for (Set<int>::Element *E = connected_peers.front(); E; E = E->next()) {
if (p_target < 0 && E->get() == -p_target)
- continue; //continue, excluded
+ continue; // Continue, excluded.
if (p_target > 0 && E->get() != p_target)
- continue; //continue, not for this peer
+ continue; // Continue, not for this peer.
Map<int, bool>::Element *F = psc->confirmed_peers.find(E->get());
- if (!F || F->get() == false) {
- //path was not cached, or was cached but is unconfirmed
+ if (!F || !F->get()) {
+ // Path was not cached, or was cached but is unconfirmed.
if (!F) {
- //not cached at all, take note
+ // Not cached at all, take note.
peers_to_add.push_back(E->get());
}
@@ -404,11 +427,11 @@ bool MultiplayerAPI::_send_confirm_path(NodePath p_path, PathSentCache *psc, int
}
}
- //those that need to be added, send a message for this
+ // Those that need to be added, send a message for this.
for (List<int>::Element *E = peers_to_add.front(); E; E = E->next()) {
- //encode function name
+ // Encode function name.
CharString pname = String(p_path).utf8();
int len = encode_cstring(pname.get_data(), NULL);
@@ -419,11 +442,11 @@ bool MultiplayerAPI::_send_confirm_path(NodePath p_path, PathSentCache *psc, int
encode_uint32(psc->id, &packet.write[1]);
encode_cstring(pname.get_data(), &packet.write[5]);
- network_peer->set_target_peer(E->get()); //to all of you
+ network_peer->set_target_peer(E->get()); // To all of you.
network_peer->set_transfer_mode(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE);
network_peer->put_packet(packet.ptr(), packet.size());
- psc->confirmed_peers.insert(E->get(), false); //insert into confirmed, but as false since it was not confirmed
+ psc->confirmed_peers.insert(E->get(), false); // Insert into confirmed, but as false since it was not confirmed.
}
return has_all_peers;
@@ -462,35 +485,36 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p
}
NodePath from_path = (root_node->get_path()).rel_path_to(p_from->get_path());
+ ERR_EXPLAIN("Unable to send RPC. Relative path is empty. THIS IS LIKELY A BUG IN THE ENGINE!");
ERR_FAIL_COND(from_path.is_empty());
- //see if the path is cached
+ // See if the path is cached.
PathSentCache *psc = path_send_cache.getptr(from_path);
if (!psc) {
- //path is not cached, create
+ // Path is not cached, create.
path_send_cache[from_path] = PathSentCache();
psc = path_send_cache.getptr(from_path);
psc->id = last_send_cache_id++;
}
- //create base packet, lots of hardcode because it must be tight
+ // Create base packet, lots of hardcode because it must be tight.
int ofs = 0;
#define MAKE_ROOM(m_amount) \
if (packet_cache.size() < m_amount) packet_cache.resize(m_amount);
- //encode type
+ // Encode type.
MAKE_ROOM(1);
packet_cache.write[0] = p_set ? NETWORK_COMMAND_REMOTE_SET : NETWORK_COMMAND_REMOTE_CALL;
ofs += 1;
- //encode ID
+ // Encode ID.
MAKE_ROOM(ofs + 4);
encode_uint32(psc->id, &(packet_cache.write[ofs]));
ofs += 4;
- //encode function name
+ // Encode function name.
CharString name = String(p_name).utf8();
int len = encode_cstring(name.get_data(), NULL);
MAKE_ROOM(ofs + len);
@@ -498,20 +522,22 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p
ofs += len;
if (p_set) {
- //set argument
+ // Set argument.
Error err = encode_variant(*p_arg[0], NULL, len);
+ ERR_EXPLAIN("Unable to encode RSET value. THIS IS LIKELY A BUG IN THE ENGINE!");
ERR_FAIL_COND(err != OK);
MAKE_ROOM(ofs + len);
encode_variant(*p_arg[0], &(packet_cache.write[ofs]), len);
ofs += len;
} else {
- //call arguments
+ // Call arguments.
MAKE_ROOM(ofs + 1);
packet_cache.write[ofs] = p_argcount;
ofs += 1;
for (int i = 0; i < p_argcount; i++) {
Error err = encode_variant(*p_arg[i], NULL, len);
+ ERR_EXPLAIN("Unable to encode RPC argument. THIS IS LIKELY A BUG IN THE ENGINE!");
ERR_FAIL_COND(err != OK);
MAKE_ROOM(ofs + len);
encode_variant(*p_arg[i], &(packet_cache.write[ofs]), len);
@@ -519,21 +545,21 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p
}
}
- //see if all peers have cached path (is so, call can be fast)
+ // See if all peers have cached path (is so, call can be fast).
bool has_all_peers = _send_confirm_path(from_path, psc, p_to);
- //take chance and set transfer mode, since all send methods will use it
+ // Take chance and set transfer mode, since all send methods will use it.
network_peer->set_transfer_mode(p_unreliable ? NetworkedMultiplayerPeer::TRANSFER_MODE_UNRELIABLE : NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE);
if (has_all_peers) {
- //they all have verified paths, so send fast
- network_peer->set_target_peer(p_to); //to all of you
- network_peer->put_packet(packet_cache.ptr(), ofs); //a message with love
+ // They all have verified paths, so send fast.
+ network_peer->set_target_peer(p_to); // To all of you.
+ network_peer->put_packet(packet_cache.ptr(), ofs); // A message with love.
} else {
- //not all verified path, so send one by one
+ // Not all verified path, so send one by one.
- //apend path at the end, since we will need it for some packets
+ // Append path at the end, since we will need it for some packets.
CharString pname = String(from_path).utf8();
int path_len = encode_cstring(pname.get_data(), NULL);
MAKE_ROOM(ofs + path_len);
@@ -542,23 +568,23 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p
for (Set<int>::Element *E = connected_peers.front(); E; E = E->next()) {
if (p_to < 0 && E->get() == -p_to)
- continue; //continue, excluded
+ continue; // Continue, excluded.
if (p_to > 0 && E->get() != p_to)
- continue; //continue, not for this peer
+ continue; // Continue, not for this peer.
Map<int, bool>::Element *F = psc->confirmed_peers.find(E->get());
- ERR_CONTINUE(!F); //should never happen
+ ERR_CONTINUE(!F); // Should never happen.
- network_peer->set_target_peer(E->get()); //to this one specifically
+ network_peer->set_target_peer(E->get()); // To this one specifically.
- if (F->get() == true) {
- //this one confirmed path, so use id
+ if (F->get()) {
+ // This one confirmed path, so use id.
encode_uint32(psc->id, &(packet_cache.write[1]));
network_peer->put_packet(packet_cache.ptr(), ofs);
} else {
- //this one did not confirm path yet, so use entire path (sorry!)
- encode_uint32(0x80000000 | ofs, &(packet_cache.write[1])); //offset to path and flag
+ // This one did not confirm path yet, so use entire path (sorry!).
+ encode_uint32(0x80000000 | ofs, &(packet_cache.write[1])); // Offset to path and flag.
network_peer->put_packet(packet_cache.ptr(), ofs + path_len);
}
}
@@ -573,7 +599,7 @@ void MultiplayerAPI::_add_peer(int p_id) {
void MultiplayerAPI::_del_peer(int p_id) {
connected_peers.erase(p_id);
- path_get_cache.erase(p_id); //I no longer need your cache, sorry
+ path_get_cache.erase(p_id); // I no longer need your cache, sorry.
emit_signal("network_peer_disconnected", p_id);
}
@@ -594,8 +620,12 @@ void MultiplayerAPI::_server_disconnected() {
void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount) {
- ERR_FAIL_COND(!p_node->is_inside_tree());
+ ERR_EXPLAIN("Trying to call an RPC while no network peer is active.");
ERR_FAIL_COND(!network_peer.is_valid());
+ ERR_EXPLAIN("Trying to call an RPC on a node which is not inside SceneTree.");
+ ERR_FAIL_COND(!p_node->is_inside_tree());
+ ERR_EXPLAIN("Trying to call an RPC via a network peer which is not connected.");
+ ERR_FAIL_COND(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED);
int node_id = network_peer->get_unique_id();
bool skip_rpc = false;
@@ -604,7 +634,7 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const
bool is_master = p_node->is_network_master();
if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) {
- //check that send mode can use local call
+ // Check that send mode can use local call.
const Map<StringName, RPCMode>::Element *E = p_node->get_node_rpc_mode(p_method);
if (E) {
@@ -612,9 +642,9 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const
}
if (call_local_native) {
- // done below
+ // Done below.
} else if (p_node->get_script_instance()) {
- //attempt with script
+ // Attempt with script.
RPCMode rpc_mode = p_node->get_script_instance()->get_rpc_mode(p_method);
call_local_script = _should_call_local(rpc_mode, is_master, skip_rpc);
}
@@ -650,15 +680,19 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const
void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value) {
- ERR_FAIL_COND(!p_node->is_inside_tree());
+ ERR_EXPLAIN("Trying to RSET while no network peer is active.");
ERR_FAIL_COND(!network_peer.is_valid());
+ ERR_EXPLAIN("Trying to RSET on a node which is not inside SceneTree.");
+ ERR_FAIL_COND(!p_node->is_inside_tree());
+ ERR_EXPLAIN("Trying to send an RSET via a network peer which is not connected.");
+ ERR_FAIL_COND(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED);
int node_id = network_peer->get_unique_id();
bool is_master = p_node->is_network_master();
bool skip_rset = false;
if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) {
- //check that send mode can use local call
+ // Check that send mode can use local call.
bool set_local = false;
@@ -678,7 +712,7 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const
return;
}
} else if (p_node->get_script_instance()) {
- //attempt with script
+ // Attempt with script.
RPCMode rpc_mode = p_node->get_script_instance()->get_rset_mode(p_property);
set_local = _should_call_local(rpc_mode, is_master, skip_rset);
@@ -706,8 +740,11 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const
Error MultiplayerAPI::send_bytes(PoolVector<uint8_t> p_data, int p_to, NetworkedMultiplayerPeer::TransferMode p_mode) {
+ ERR_EXPLAIN("Trying to send an empty raw packet.");
ERR_FAIL_COND_V(p_data.size() < 1, ERR_INVALID_DATA);
+ ERR_EXPLAIN("Trying to send a raw packet while no network peer is active.");
ERR_FAIL_COND_V(!network_peer.is_valid(), ERR_UNCONFIGURED);
+ ERR_EXPLAIN("Trying to send a raw packet via a network peer which is not connected.");
ERR_FAIL_COND_V(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED, ERR_UNCONFIGURED);
MAKE_ROOM(p_data.size() + 1);
@@ -723,6 +760,7 @@ Error MultiplayerAPI::send_bytes(PoolVector<uint8_t> p_data, int p_to, Networked
void MultiplayerAPI::_process_raw(int p_from, const uint8_t *p_packet, int p_packet_len) {
+ ERR_EXPLAIN("Invalid packet received. Size too small.");
ERR_FAIL_COND(p_packet_len < 2);
PoolVector<uint8_t> out;
@@ -737,30 +775,36 @@ void MultiplayerAPI::_process_raw(int p_from, const uint8_t *p_packet, int p_pac
int MultiplayerAPI::get_network_unique_id() const {
+ ERR_EXPLAIN("No network peer is assigned. Unable to get unique network ID.");
ERR_FAIL_COND_V(!network_peer.is_valid(), 0);
return network_peer->get_unique_id();
}
bool MultiplayerAPI::is_network_server() const {
+ // XXX Maybe fail silently? Maybe should actually return true to make development of both local and online multiplayer easier?
+ ERR_EXPLAIN("No network peer is assigned. I can't be a server.");
ERR_FAIL_COND_V(!network_peer.is_valid(), false);
return network_peer->is_server();
}
void MultiplayerAPI::set_refuse_new_network_connections(bool p_refuse) {
+ ERR_EXPLAIN("No network peer is assigned. Unable to set 'refuse_new_connections'.");
ERR_FAIL_COND(!network_peer.is_valid());
network_peer->set_refuse_new_connections(p_refuse);
}
bool MultiplayerAPI::is_refusing_new_network_connections() const {
+ ERR_EXPLAIN("No network peer is assigned. Unable to get 'refuse_new_connections'.");
ERR_FAIL_COND_V(!network_peer.is_valid(), false);
return network_peer->is_refusing_new_connections();
}
Vector<int> MultiplayerAPI::get_network_connected_peers() const {
+ ERR_EXPLAIN("No network peer is assigned. Assume no peers are connected.");
ERR_FAIL_COND_V(!network_peer.is_valid(), Vector<int>());
Vector<int> ret;
@@ -803,12 +847,13 @@ void MultiplayerAPI::_bind_methods() {
BIND_ENUM_CONSTANT(RPC_MODE_DISABLED);
BIND_ENUM_CONSTANT(RPC_MODE_REMOTE);
- BIND_ENUM_CONSTANT(RPC_MODE_SYNC);
BIND_ENUM_CONSTANT(RPC_MODE_MASTER);
- BIND_ENUM_CONSTANT(RPC_MODE_SLAVE);
+ BIND_ENUM_CONSTANT(RPC_MODE_PUPPET);
+ BIND_ENUM_CONSTANT(RPC_MODE_SLAVE); // Deprecated.
BIND_ENUM_CONSTANT(RPC_MODE_REMOTESYNC);
+ BIND_ENUM_CONSTANT(RPC_MODE_SYNC); // Deprecated.
BIND_ENUM_CONSTANT(RPC_MODE_MASTERSYNC);
- BIND_ENUM_CONSTANT(RPC_MODE_SLAVESYNC);
+ BIND_ENUM_CONSTANT(RPC_MODE_PUPPETSYNC);
}
MultiplayerAPI::MultiplayerAPI() {
diff --git a/core/io/multiplayer_api.h b/core/io/multiplayer_api.h
index e47b1830e8..c86e76e91a 100644
--- a/core/io/multiplayer_api.h
+++ b/core/io/multiplayer_api.h
@@ -91,12 +91,13 @@ public:
RPC_MODE_DISABLED, // No rpc for this method, calls to this will be blocked (default)
RPC_MODE_REMOTE, // Using rpc() on it will call method / set property in all remote peers
- RPC_MODE_SYNC, // Using rpc() on it will call method / set property in all remote peers and locally
RPC_MODE_MASTER, // Using rpc() on it will call method on wherever the master is, be it local or remote
- RPC_MODE_SLAVE, // Using rpc() on it will call method for all slaves
- RPC_MODE_REMOTESYNC, // Same as RPC_MODE_SYNC, compatibility
+ RPC_MODE_PUPPET, // Using rpc() on it will call method for all puppets
+ RPC_MODE_SLAVE = RPC_MODE_PUPPET, // Deprecated, same as puppet
+ RPC_MODE_REMOTESYNC, // Using rpc() on it will call method / set property in all remote peers and locally
+ RPC_MODE_SYNC = RPC_MODE_REMOTESYNC, // Deprecated. Same as RPC_MODE_REMOTESYNC
RPC_MODE_MASTERSYNC, // Using rpc() on it will call method / set property in the master peer and locally
- RPC_MODE_SLAVESYNC, // Using rpc() on it will call method / set property in all slave peers and locally
+ RPC_MODE_PUPPETSYNC, // Using rpc() on it will call method / set property in all puppets peers and locally
};
void poll();
diff --git a/core/io/net_socket.cpp b/core/io/net_socket.cpp
new file mode 100644
index 0000000000..10bcf62eda
--- /dev/null
+++ b/core/io/net_socket.cpp
@@ -0,0 +1,42 @@
+/*************************************************************************/
+/* net_socket.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 "net_socket.h"
+
+NetSocket *(*NetSocket::_create)() = NULL;
+
+NetSocket *NetSocket::create() {
+
+ if (_create)
+ return _create();
+
+ ERR_PRINT("Unable to create network socket, platform not supported");
+ return NULL;
+}
diff --git a/core/io/net_socket.h b/core/io/net_socket.h
new file mode 100644
index 0000000000..0665bec9fd
--- /dev/null
+++ b/core/io/net_socket.h
@@ -0,0 +1,79 @@
+/*************************************************************************/
+/* net_socket.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 NET_SOCKET_H
+#define NET_SOCKET_H
+
+#include "core/io/ip.h"
+#include "core/reference.h"
+
+class NetSocket : public Reference {
+
+protected:
+ static NetSocket *(*_create)();
+
+public:
+ static NetSocket *create();
+
+ enum PollType {
+ POLL_TYPE_IN,
+ POLL_TYPE_OUT,
+ POLL_TYPE_IN_OUT
+ };
+
+ enum Type {
+ TYPE_NONE,
+ TYPE_TCP,
+ TYPE_UDP,
+ };
+
+ virtual Error open(Type p_type, IP::Type &ip_type) = 0;
+ virtual void close() = 0;
+ virtual Error bind(IP_Address p_addr, uint16_t p_port) = 0;
+ virtual Error listen(int p_max_pending) = 0;
+ virtual Error connect_to_host(IP_Address p_addr, uint16_t p_port) = 0;
+ virtual Error poll(PollType p_type, int timeout) const = 0;
+ virtual Error recv(uint8_t *p_buffer, int p_len, int &r_read) = 0;
+ virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port) = 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 Ref<NetSocket> accept(IP_Address &r_ip, uint16_t &r_port) = 0;
+
+ virtual bool is_open() const = 0;
+ virtual int get_available_bytes() const = 0;
+
+ virtual void set_broadcasting_enabled(bool p_enabled) = 0;
+ virtual void set_blocking_enabled(bool p_enabled) = 0;
+ virtual void set_ipv6_only_enabled(bool p_enabled) = 0;
+ virtual void set_tcp_no_delay_enabled(bool p_enabled) = 0;
+ virtual void set_reuse_address_enabled(bool p_enabled) = 0;
+};
+
+#endif // NET_SOCKET_H
diff --git a/core/io/networked_multiplayer_peer.h b/core/io/networked_multiplayer_peer.h
index 66089c27b9..8e83c528a0 100644
--- a/core/io/networked_multiplayer_peer.h
+++ b/core/io/networked_multiplayer_peer.h
@@ -31,7 +31,7 @@
#ifndef NETWORKED_MULTIPLAYER_PEER_H
#define NETWORKED_MULTIPLAYER_PEER_H
-#include "io/packet_peer.h"
+#include "core/io/packet_peer.h"
class NetworkedMultiplayerPeer : public PacketPeer {
diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp
index dc4997dfc2..b6dd4eaf6f 100644
--- a/core/io/packet_peer.cpp
+++ b/core/io/packet_peer.cpp
@@ -30,8 +30,9 @@
#include "packet_peer.h"
-#include "io/marshalls.h"
-#include "project_settings.h"
+#include "core/io/marshalls.h"
+#include "core/project_settings.h"
+
/* helpers / binders */
PacketPeer::PacketPeer() {
diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h
index b10152e96b..a6559df460 100644
--- a/core/io/packet_peer.h
+++ b/core/io/packet_peer.h
@@ -31,9 +31,10 @@
#ifndef PACKET_PEER_H
#define PACKET_PEER_H
-#include "io/stream_peer.h"
-#include "object.h"
-#include "ring_buffer.h"
+#include "core/io/stream_peer.h"
+#include "core/object.h"
+#include "core/ring_buffer.h"
+
class PacketPeer : public Reference {
GDCLASS(PacketPeer, Reference);
diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp
index bfbea15582..d33ba6f855 100644
--- a/core/io/packet_peer_udp.cpp
+++ b/core/io/packet_peer_udp.cpp
@@ -29,9 +29,8 @@
/*************************************************************************/
#include "packet_peer_udp.h"
-#include "io/ip.h"
-PacketPeerUDP *(*PacketPeerUDP::_create)() = NULL;
+#include "core/io/ip.h"
void PacketPeerUDP::set_blocking_mode(bool p_enable) {
@@ -58,6 +57,177 @@ Error PacketPeerUDP::_set_dest_address(const String &p_address, int p_port) {
return OK;
}
+int PacketPeerUDP::get_available_packet_count() const {
+
+ // TODO we should deprecate this, and expose poll instead!
+ Error err = const_cast<PacketPeerUDP *>(this)->_poll();
+ if (err != OK)
+ return -1;
+
+ return queue_count;
+}
+
+Error PacketPeerUDP::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
+
+ Error err = _poll();
+ if (err != OK)
+ return err;
+ if (queue_count == 0)
+ return ERR_UNAVAILABLE;
+
+ uint32_t size = 0;
+ uint8_t ipv6[16];
+ rb.read(ipv6, 16, true);
+ packet_ip.set_ipv6(ipv6);
+ rb.read((uint8_t *)&packet_port, 4, true);
+ rb.read((uint8_t *)&size, 4, true);
+ rb.read(packet_buffer, size, true);
+ --queue_count;
+ *r_buffer = packet_buffer;
+ r_buffer_size = size;
+ return OK;
+}
+
+Error PacketPeerUDP::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
+
+ ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE);
+ ERR_FAIL_COND_V(!peer_addr.is_valid(), ERR_UNCONFIGURED);
+
+ Error err;
+ int sent = -1;
+
+ if (!_sock->is_open()) {
+ IP::Type ip_type = peer_addr.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
+ err = _sock->open(NetSocket::TYPE_UDP, ip_type);
+ ERR_FAIL_COND_V(err != OK, err);
+ _sock->set_blocking_enabled(false);
+ }
+
+ do {
+ err = _sock->sendto(p_buffer, p_buffer_size, sent, peer_addr, peer_port);
+ if (err != OK) {
+ if (err != ERR_BUSY)
+ return FAILED;
+ else if (!blocking)
+ return ERR_BUSY;
+ // Keep trying to send full packet
+ continue;
+ }
+ return OK;
+
+ } while (sent != p_buffer_size);
+
+ return OK;
+}
+
+int PacketPeerUDP::get_max_packet_size() const {
+
+ return 512; // uhm maybe not
+}
+
+Error PacketPeerUDP::listen(int p_port, const IP_Address &p_bind_address, int p_recv_buffer_size) {
+
+ 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 (p_bind_address.is_valid())
+ ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
+
+ err = _sock->open(NetSocket::TYPE_UDP, ip_type);
+
+ if (err != OK)
+ return 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;
+ }
+ rb.resize(nearest_shift(p_recv_buffer_size));
+ return OK;
+}
+
+void PacketPeerUDP::close() {
+
+ if (_sock.is_valid())
+ _sock->close();
+ rb.resize(16);
+ queue_count = 0;
+}
+
+Error PacketPeerUDP::wait() {
+
+ ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE);
+ return _sock->poll(NetSocket::POLL_TYPE_IN, -1);
+}
+
+Error PacketPeerUDP::_poll() {
+
+ ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE);
+
+ if (!_sock->is_open()) {
+ return FAILED;
+ }
+
+ Error err;
+ int read;
+ IP_Address ip;
+ uint16_t port;
+
+ while (true) {
+ err = _sock->recvfrom(recv_buffer, sizeof(recv_buffer), read, ip, port);
+
+ if (err != OK) {
+ if (err == ERR_BUSY)
+ break;
+ return FAILED;
+ }
+
+ if (rb.space_left() < read + 24) {
+#ifdef TOOLS_ENABLED
+ WARN_PRINTS("Buffer full, dropping packets!");
+#endif
+ continue;
+ }
+
+ uint32_t port32 = port;
+ rb.write(ip.get_ipv6(), 16);
+ rb.write((uint8_t *)&port32, 4);
+ rb.write((uint8_t *)&read, 4);
+ rb.write(recv_buffer, read);
+ ++queue_count;
+ }
+
+ return OK;
+}
+bool PacketPeerUDP::is_listening() const {
+
+ return _sock.is_valid() && _sock->is_open();
+}
+
+IP_Address PacketPeerUDP::get_packet_address() const {
+
+ return packet_ip;
+}
+
+int PacketPeerUDP::get_packet_port() const {
+
+ return packet_port;
+}
+
+void PacketPeerUDP::set_dest_address(const IP_Address &p_address, int p_port) {
+
+ peer_addr = p_address;
+ peer_port = p_port;
+}
+
void PacketPeerUDP::_bind_methods() {
ClassDB::bind_method(D_METHOD("listen", "port", "bind_address", "recv_buf_size"), &PacketPeerUDP::listen, DEFVAL("*"), DEFVAL(65536));
@@ -65,26 +235,21 @@ void PacketPeerUDP::_bind_methods() {
ClassDB::bind_method(D_METHOD("wait"), &PacketPeerUDP::wait);
ClassDB::bind_method(D_METHOD("is_listening"), &PacketPeerUDP::is_listening);
ClassDB::bind_method(D_METHOD("get_packet_ip"), &PacketPeerUDP::_get_packet_ip);
- //ClassDB::bind_method(D_METHOD("get_packet_address"),&PacketPeerUDP::_get_packet_address);
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);
}
-Ref<PacketPeerUDP> PacketPeerUDP::create_ref() {
-
- if (!_create)
- return Ref<PacketPeerUDP>();
- return Ref<PacketPeerUDP>(_create());
-}
-
-PacketPeerUDP *PacketPeerUDP::create() {
+PacketPeerUDP::PacketPeerUDP() {
- if (!_create)
- return NULL;
- return _create();
+ _sock = Ref<NetSocket>(NetSocket::create());
+ blocking = true;
+ packet_port = 0;
+ queue_count = 0;
+ peer_port = 0;
+ rb.resize(16);
}
-PacketPeerUDP::PacketPeerUDP() {
+PacketPeerUDP::~PacketPeerUDP() {
- blocking = true;
+ close();
}
diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h
index 035f4ad1c9..4366b0eb82 100644
--- a/core/io/packet_peer_udp.h
+++ b/core/io/packet_peer_udp.h
@@ -31,37 +31,55 @@
#ifndef PACKET_PEER_UDP_H
#define PACKET_PEER_UDP_H
-#include "io/ip.h"
-#include "io/packet_peer.h"
+#include "core/io/ip.h"
+#include "core/io/net_socket.h"
+#include "core/io/packet_peer.h"
class PacketPeerUDP : public PacketPeer {
GDCLASS(PacketPeerUDP, PacketPeer);
protected:
+ enum {
+ PACKET_BUFFER_SIZE = 65536
+ };
+
+ RingBuffer<uint8_t> rb;
+ uint8_t recv_buffer[PACKET_BUFFER_SIZE];
+ uint8_t packet_buffer[PACKET_BUFFER_SIZE];
+ IP_Address packet_ip;
+ int packet_port;
+ int queue_count;
+
+ IP_Address peer_addr;
+ int peer_port;
bool blocking;
+ Ref<NetSocket> _sock;
- static PacketPeerUDP *(*_create)();
static void _bind_methods();
String _get_packet_ip() const;
Error _set_dest_address(const String &p_address, int p_port);
+ Error _poll();
public:
void set_blocking_mode(bool p_enable);
- virtual Error listen(int p_port, const IP_Address &p_bind_address = IP_Address("*"), int p_recv_buffer_size = 65536) = 0;
- virtual void close() = 0;
- virtual Error wait() = 0;
- virtual bool is_listening() const = 0;
- virtual IP_Address get_packet_address() const = 0;
- virtual int get_packet_port() const = 0;
- virtual void set_dest_address(const IP_Address &p_address, int p_port) = 0;
+ Error listen(int p_port, const IP_Address &p_bind_address = IP_Address("*"), int p_recv_buffer_size = 65536);
+ void close();
+ Error wait();
+ bool is_listening() const;
+ IP_Address get_packet_address() const;
+ int get_packet_port() const;
+ void set_dest_address(const IP_Address &p_address, int p_port);
- static Ref<PacketPeerUDP> create_ref();
- static PacketPeerUDP *create();
+ Error put_packet(const uint8_t *p_buffer, int p_buffer_size);
+ Error get_packet(const uint8_t **r_buffer, int &r_buffer_size);
+ int get_available_packet_count() const;
+ int get_max_packet_size() const;
PacketPeerUDP();
+ ~PacketPeerUDP();
};
#endif // PACKET_PEER_UDP_H
diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp
index 2fd73db27d..3df8c01760 100644
--- a/core/io/pck_packer.cpp
+++ b/core/io/pck_packer.cpp
@@ -29,8 +29,9 @@
/*************************************************************************/
#include "pck_packer.h"
+
#include "core/os/file_access.h"
-#include "version.h"
+#include "core/version.h"
static uint64_t _align(uint64_t p_n, int p_alignment) {
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 02c2c6ce1a..aa73d7bc5c 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -1309,7 +1309,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
case Variant::INT: {
int64_t val = p_property;
- if (val > 0x7FFFFFFF || val < -0x80000000) {
+ if (val > 0x7FFFFFFF || val < -(int64_t)0x80000000) {
f->store_32(VARIANT_INT64);
f->store_64(val);
@@ -1718,7 +1718,7 @@ void ResourceFormatSaverBinaryInstance::save_unicode_string(FileAccess *f, const
CharString utf8 = p_string.utf8();
if (p_bit_on_len) {
- f->store_32(utf8.length() + 1 | 0x80000000);
+ f->store_32((utf8.length() + 1) | 0x80000000);
} else {
f->store_32(utf8.length() + 1);
}
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index 021f7f6a2f..513252055f 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -31,9 +31,9 @@
#ifndef RESOURCE_FORMAT_BINARY_H
#define RESOURCE_FORMAT_BINARY_H
-#include "io/resource_loader.h"
-#include "io/resource_saver.h"
-#include "os/file_access.h"
+#include "core/io/resource_loader.h"
+#include "core/io/resource_saver.h"
+#include "core/os/file_access.h"
class ResourceInteractiveLoaderBinary : public ResourceInteractiveLoader {
@@ -119,7 +119,6 @@ class ResourceFormatSaverBinaryInstance {
bool skip_editor;
bool big_endian;
bool takeover_paths;
- int bin_meta_idx;
FileAccess *f;
String magic;
Set<RES> resource_set;
diff --git a/core/io/resource_import.cpp b/core/io/resource_import.cpp
index cfe6655504..ffea43b6bf 100644
--- a/core/io/resource_import.cpp
+++ b/core/io/resource_import.cpp
@@ -30,8 +30,8 @@
#include "resource_import.h"
-#include "os/os.h"
-#include "variant_parser.h"
+#include "core/os/os.h"
+#include "core/variant_parser.h"
Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndType &r_path_and_type, bool *r_valid) const {
diff --git a/core/io/resource_import.h b/core/io/resource_import.h
index 80e0743eda..53718bd789 100644
--- a/core/io/resource_import.h
+++ b/core/io/resource_import.h
@@ -31,7 +31,8 @@
#ifndef RESOURCE_IMPORT_H
#define RESOURCE_IMPORT_H
-#include "io/resource_loader.h"
+#include "core/io/resource_loader.h"
+
class ResourceImporter;
class ResourceFormatImporter : public ResourceFormatLoader {
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 66dc9730c5..71b01aa94a 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -29,14 +29,16 @@
/*************************************************************************/
#include "resource_loader.h"
-#include "io/resource_import.h"
-#include "os/file_access.h"
-#include "os/os.h"
-#include "path_remap.h"
-#include "print_string.h"
-#include "project_settings.h"
-#include "translation.h"
-#include "variant_parser.h"
+
+#include "core/io/resource_import.h"
+#include "core/os/file_access.h"
+#include "core/os/os.h"
+#include "core/path_remap.h"
+#include "core/print_string.h"
+#include "core/project_settings.h"
+#include "core/translation.h"
+#include "core/variant_parser.h"
+
ResourceFormatLoader *ResourceLoader::loader[MAX_LOADERS];
int ResourceLoader::loader_count = 0;
@@ -257,6 +259,10 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p
}
#endif
+ if (_loaded_callback) {
+ _loaded_callback(res, p_path);
+ }
+
return res;
}
@@ -633,6 +639,12 @@ void ResourceLoader::clear_path_remaps() {
path_remaps.clear();
}
+void ResourceLoader::set_load_callback(ResourceLoadedCallback p_callback) {
+ _loaded_callback = p_callback;
+}
+
+ResourceLoadedCallback ResourceLoader::_loaded_callback = NULL;
+
ResourceLoadErrorNotify ResourceLoader::err_notify = NULL;
void *ResourceLoader::err_notify_ud = NULL;
@@ -645,3 +657,5 @@ bool ResourceLoader::timestamp_on_load = false;
SelfList<Resource>::List ResourceLoader::remapped_list;
HashMap<String, Vector<String> > ResourceLoader::translation_remaps;
HashMap<String, String> ResourceLoader::path_remaps;
+
+ResourceLoaderImport ResourceLoader::import = NULL;
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index f78464ef0c..7ade4a2dfc 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -31,7 +31,7 @@
#ifndef RESOURCE_LOADER_H
#define RESOURCE_LOADER_H
-#include "resource.h"
+#include "core/resource.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
@@ -77,6 +77,9 @@ public:
typedef void (*ResourceLoadErrorNotify)(void *p_ud, const String &p_text);
typedef void (*DependencyErrorNotify)(void *p_ud, const String &p_loading, const String &p_which, const String &p_type);
+typedef Error (*ResourceLoaderImport)(const String &p_path);
+typedef void (*ResourceLoadedCallback)(RES p_resource, const String &p_path);
+
class ResourceLoader {
enum {
@@ -104,6 +107,8 @@ class ResourceLoader {
//internal load function
static RES _load(const String &p_path, const String &p_original_path, const String &p_type_hint, bool p_no_cache, Error *r_error);
+ static ResourceLoadedCallback _loaded_callback;
+
public:
static Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false, Error *r_error = NULL);
static RES load(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false, Error *r_error = NULL);
@@ -147,6 +152,9 @@ public:
static void reload_translation_remaps();
static void load_translation_remaps();
static void clear_translation_remaps();
+
+ static void set_load_callback(ResourceLoadedCallback p_callback);
+ static ResourceLoaderImport import;
};
#endif
diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp
index 3dcd94880a..097e81e308 100644
--- a/core/io/resource_saver.cpp
+++ b/core/io/resource_saver.cpp
@@ -29,10 +29,11 @@
/*************************************************************************/
#include "resource_saver.h"
-#include "os/file_access.h"
-#include "project_settings.h"
-#include "resource_loader.h"
-#include "script_language.h"
+
+#include "core/io/resource_loader.h"
+#include "core/os/file_access.h"
+#include "core/project_settings.h"
+#include "core/script_language.h"
ResourceFormatSaver *ResourceSaver::saver[MAX_SAVERS];
@@ -89,7 +90,7 @@ Error ResourceSaver::save(const String &p_path, const RES &p_resource, uint32_t
rwcopy->set_path(old_path);
if (save_callback && p_path.begins_with("res://"))
- save_callback(p_path);
+ save_callback(p_resource, p_path);
return OK;
} else {
diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h
index 396f37d414..6134d9db57 100644
--- a/core/io/resource_saver.h
+++ b/core/io/resource_saver.h
@@ -31,7 +31,7 @@
#ifndef RESOURCE_SAVER_H
#define RESOURCE_SAVER_H
-#include "resource.h"
+#include "core/resource.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
@@ -46,7 +46,7 @@ public:
virtual ~ResourceFormatSaver() {}
};
-typedef void (*ResourceSavedCallback)(const String &p_path);
+typedef void (*ResourceSavedCallback)(Ref<Resource> p_resource, const String &p_path);
class ResourceSaver {
diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp
index 3e0ee088c2..3f608b720c 100644
--- a/core/io/stream_peer.cpp
+++ b/core/io/stream_peer.cpp
@@ -29,7 +29,8 @@
/*************************************************************************/
#include "stream_peer.h"
-#include "io/marshalls.h"
+
+#include "core/io/marshalls.h"
Error StreamPeer::_put_data(const PoolVector<uint8_t> &p_data) {
@@ -208,6 +209,12 @@ void StreamPeer::put_double(double p_val) {
}
put_data(buf, 8);
}
+void StreamPeer::put_string(const String &p_string) {
+
+ CharString cs = p_string.ascii();
+ put_u32(cs.length());
+ put_data((const uint8_t *)cs.get_data(), cs.length());
+}
void StreamPeer::put_utf8_string(const String &p_string) {
CharString cs = p_string.utf8();
@@ -324,6 +331,8 @@ double StreamPeer::get_double() {
}
String StreamPeer::get_string(int p_bytes) {
+ if (p_bytes < 0)
+ p_bytes = get_u32();
ERR_FAIL_COND_V(p_bytes < 0, String());
Vector<char> buf;
@@ -336,6 +345,8 @@ String StreamPeer::get_string(int p_bytes) {
}
String StreamPeer::get_utf8_string(int p_bytes) {
+ if (p_bytes < 0)
+ p_bytes = get_u32();
ERR_FAIL_COND_V(p_bytes < 0, String());
Vector<uint8_t> buf;
@@ -385,6 +396,7 @@ void StreamPeer::_bind_methods() {
ClassDB::bind_method(D_METHOD("put_u64", "value"), &StreamPeer::put_u64);
ClassDB::bind_method(D_METHOD("put_float", "value"), &StreamPeer::put_float);
ClassDB::bind_method(D_METHOD("put_double", "value"), &StreamPeer::put_double);
+ ClassDB::bind_method(D_METHOD("put_string", "value"), &StreamPeer::put_string);
ClassDB::bind_method(D_METHOD("put_utf8_string", "value"), &StreamPeer::put_utf8_string);
ClassDB::bind_method(D_METHOD("put_var", "value"), &StreamPeer::put_var);
@@ -398,8 +410,8 @@ void StreamPeer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_u64"), &StreamPeer::get_u64);
ClassDB::bind_method(D_METHOD("get_float"), &StreamPeer::get_float);
ClassDB::bind_method(D_METHOD("get_double"), &StreamPeer::get_double);
- ClassDB::bind_method(D_METHOD("get_string", "bytes"), &StreamPeer::get_string);
- ClassDB::bind_method(D_METHOD("get_utf8_string", "bytes"), &StreamPeer::get_utf8_string);
+ ClassDB::bind_method(D_METHOD("get_string", "bytes"), &StreamPeer::get_string, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("get_utf8_string", "bytes"), &StreamPeer::get_utf8_string, DEFVAL(-1));
ClassDB::bind_method(D_METHOD("get_var"), &StreamPeer::get_var);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "big_endian"), "set_big_endian", "is_big_endian_enabled");
diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h
index 605b0a7980..f189960cbd 100644
--- a/core/io/stream_peer.h
+++ b/core/io/stream_peer.h
@@ -31,7 +31,7 @@
#ifndef STREAM_PEER_H
#define STREAM_PEER_H
-#include "reference.h"
+#include "core/reference.h"
class StreamPeer : public Reference {
GDCLASS(StreamPeer, Reference);
@@ -71,6 +71,7 @@ public:
void put_u64(uint64_t p_val);
void put_float(float p_val);
void put_double(double p_val);
+ void put_string(const String &p_string);
void put_utf8_string(const String &p_string);
void put_var(const Variant &p_variant);
@@ -84,8 +85,8 @@ public:
int64_t get_64();
float get_float();
double get_double();
- String get_string(int p_bytes);
- String get_utf8_string(int p_bytes);
+ String get_string(int p_bytes = -1);
+ String get_utf8_string(int p_bytes = -1);
Variant get_var();
StreamPeer() { big_endian = false; }
diff --git a/core/io/stream_peer_ssl.cpp b/core/io/stream_peer_ssl.cpp
index 25adb6a6ee..138f91301e 100644
--- a/core/io/stream_peer_ssl.cpp
+++ b/core/io/stream_peer_ssl.cpp
@@ -29,8 +29,11 @@
/*************************************************************************/
#include "stream_peer_ssl.h"
-#include "os/file_access.h"
-#include "project_settings.h"
+
+#include "core/io/certs_compressed.gen.h"
+#include "core/io/compression.h"
+#include "core/os/file_access.h"
+#include "core/project_settings.h"
StreamPeerSSL *(*StreamPeerSSL::_create)() = NULL;
@@ -41,13 +44,20 @@ StreamPeerSSL *StreamPeerSSL::create() {
StreamPeerSSL::LoadCertsFromMemory StreamPeerSSL::load_certs_func = NULL;
bool StreamPeerSSL::available = false;
-bool StreamPeerSSL::initialize_certs = true;
void StreamPeerSSL::load_certs_from_memory(const PoolByteArray &p_memory) {
if (load_certs_func)
load_certs_func(p_memory);
}
+void StreamPeerSSL::load_certs_from_file(String p_path) {
+ if (p_path != "") {
+ PoolByteArray certs = get_cert_file_as_array(p_path);
+ if (certs.size() > 0)
+ load_certs_func(certs);
+ }
+}
+
bool StreamPeerSSL::is_available() {
return available;
}
@@ -60,6 +70,25 @@ bool StreamPeerSSL::is_blocking_handshake_enabled() const {
return blocking_handshake;
}
+PoolByteArray StreamPeerSSL::get_cert_file_as_array(String p_path) {
+
+ PoolByteArray out;
+ FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
+ if (f) {
+ int flen = f->get_len();
+ out.resize(flen + 1);
+ PoolByteArray::Write w = out.write();
+ f->get_buffer(w.ptr(), flen);
+ w[flen] = 0; // Make sure it ends with string terminator
+ memdelete(f);
+#ifdef DEBUG_ENABLED
+ print_verbose(vformat("Loaded certs from '%s'.", p_path));
+#endif
+ }
+
+ return out;
+}
+
PoolByteArray StreamPeerSSL::get_project_cert_array() {
PoolByteArray out;
@@ -67,24 +96,21 @@ PoolByteArray StreamPeerSSL::get_project_cert_array() {
ProjectSettings::get_singleton()->set_custom_property_info("network/ssl/certificates", PropertyInfo(Variant::STRING, "network/ssl/certificates", PROPERTY_HINT_FILE, "*.crt"));
if (certs_path != "") {
-
- FileAccess *f = FileAccess::open(certs_path, FileAccess::READ);
- if (f) {
- int flen = f->get_len();
- out.resize(flen + 1);
- {
- PoolByteArray::Write w = out.write();
- f->get_buffer(w.ptr(), flen);
- w[flen] = 0; //end f string
- }
-
- memdelete(f);
-
+ // Use certs defined in project settings.
+ return get_cert_file_as_array(certs_path);
+ }
+#ifdef BUILTIN_CERTS_ENABLED
+ else {
+ // Use builtin certs only if user did not override it in project settings.
+ out.resize(_certs_uncompressed_size + 1);
+ PoolByteArray::Write w = out.write();
+ Compression::decompress(w.ptr(), _certs_uncompressed_size, _certs_compressed, _certs_compressed_size, Compression::MODE_DEFLATE);
+ w[_certs_uncompressed_size] = 0; // Make sure it ends with string terminator
#ifdef DEBUG_ENABLED
- print_verbose(vformat("Loaded certs from '%s'.", certs_path));
+ print_verbose("Loaded builtin certs");
#endif
- }
}
+#endif
return out;
}
@@ -102,6 +128,7 @@ void StreamPeerSSL::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "blocking_handshake"), "set_blocking_handshake_enabled", "is_blocking_handshake_enabled");
BIND_ENUM_CONSTANT(STATUS_DISCONNECTED);
+ BIND_ENUM_CONSTANT(STATUS_HANDSHAKING);
BIND_ENUM_CONSTANT(STATUS_CONNECTED);
BIND_ENUM_CONSTANT(STATUS_ERROR);
BIND_ENUM_CONSTANT(STATUS_ERROR_HOSTNAME_MISMATCH);
diff --git a/core/io/stream_peer_ssl.h b/core/io/stream_peer_ssl.h
index 870704e875..8ce36d7e7d 100644
--- a/core/io/stream_peer_ssl.h
+++ b/core/io/stream_peer_ssl.h
@@ -31,7 +31,7 @@
#ifndef STREAM_PEER_SSL_H
#define STREAM_PEER_SSL_H
-#include "io/stream_peer.h"
+#include "core/io/stream_peer.h"
class StreamPeerSSL : public StreamPeer {
GDCLASS(StreamPeerSSL, StreamPeer);
@@ -46,9 +46,6 @@ protected:
static LoadCertsFromMemory load_certs_func;
static bool available;
- friend class Main;
- static bool initialize_certs;
-
bool blocking_handshake;
public:
@@ -72,7 +69,9 @@ public:
static StreamPeerSSL *create();
+ static PoolByteArray get_cert_file_as_array(String p_path);
static PoolByteArray get_project_cert_array();
+ static void load_certs_from_file(String p_path);
static void load_certs_from_memory(const PoolByteArray &p_memory);
static bool is_available();
diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp
index 54ebb3ae0d..28561e8cbc 100644
--- a/core/io/stream_peer_tcp.cpp
+++ b/core/io/stream_peer_tcp.cpp
@@ -30,7 +30,294 @@
#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;
+ }
+
+ disconnect_from_host();
+ 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) {
+ status = STATUS_CONNECTED;
+ } else if (err == ERR_BUSY) {
+ status = STATUS_CONNECTING;
+ } else {
+ ERR_PRINT("Connection to remote host failed!");
+ disconnect_from_host();
+ return FAILED;
+ }
+
+ 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) {
+
+ disconnect_from_host();
+ 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();
+ } else if (status == STATUS_CONNECTED) {
+ Error err;
+ err = _sock->poll(NetSocket::POLL_TYPE_IN, 0);
+ if (err == OK) {
+ // FIN received
+ if (_sock->get_available_bytes() == 0) {
+ disconnect_from_host();
+ return status;
+ }
+ }
+ // Also poll write
+ err = _sock->poll(NetSocket::POLL_TYPE_IN_OUT, 0);
+ if (err != OK && err != ERR_BUSY) {
+ // Got an error
+ disconnect_from_host();
+ status = STATUS_ERROR;
+ }
+ }
+
+ 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 +349,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 8a16d820f2..de364915cd 100644
--- a/core/io/stream_peer_tcp.h
+++ b/core/io/stream_peer_tcp.h
@@ -31,10 +31,10 @@
#ifndef STREAM_PEER_TCP_H
#define STREAM_PEER_TCP_H
-#include "stream_peer.h"
-
-#include "io/ip.h"
-#include "ip_address.h"
+#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 {
@@ -51,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 a250e8b249..4c89197d9a 100644
--- a/core/io/tcp_server.h
+++ b/core/io/tcp_server.h
@@ -31,31 +31,32 @@
#ifndef TCP_SERVER_H
#define TCP_SERVER_H
-#include "io/ip.h"
-#include "io/stream_peer.h"
-#include "stream_peer_tcp.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"
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/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp
index 85c1fc5ddf..830c2b6694 100644
--- a/core/io/translation_loader_po.cpp
+++ b/core/io/translation_loader_po.cpp
@@ -29,8 +29,9 @@
/*************************************************************************/
#include "translation_loader_po.h"
-#include "os/file_access.h"
-#include "translation.h"
+
+#include "core/os/file_access.h"
+#include "core/translation.h"
RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const String &p_path) {
diff --git a/core/io/translation_loader_po.h b/core/io/translation_loader_po.h
index 33cf9bd8b4..670a9fdd7e 100644
--- a/core/io/translation_loader_po.h
+++ b/core/io/translation_loader_po.h
@@ -31,9 +31,10 @@
#ifndef TRANSLATION_LOADER_PO_H
#define TRANSLATION_LOADER_PO_H
-#include "io/resource_loader.h"
-#include "os/file_access.h"
-#include "translation.h"
+#include "core/io/resource_loader.h"
+#include "core/os/file_access.h"
+#include "core/translation.h"
+
class TranslationLoaderPO : public ResourceFormatLoader {
public:
static RES load_translation(FileAccess *f, Error *r_error, const String &p_path = String());
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index 33c9b56d5a..8c0cbd6e55 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -29,7 +29,9 @@
/*************************************************************************/
#include "xml_parser.h"
-#include "print_string.h"
+
+#include "core/print_string.h"
+
//#define DEBUG_XML
VARIANT_ENUM_CAST(XMLParser::NodeType);
diff --git a/core/io/xml_parser.h b/core/io/xml_parser.h
index 297b57ffdc..bbc7671a0e 100644
--- a/core/io/xml_parser.h
+++ b/core/io/xml_parser.h
@@ -31,10 +31,10 @@
#ifndef XML_PARSER_H
#define XML_PARSER_H
-#include "os/file_access.h"
-#include "reference.h"
-#include "ustring.h"
-#include "vector.h"
+#include "core/os/file_access.h"
+#include "core/reference.h"
+#include "core/ustring.h"
+#include "core/vector.h"
/*
Based on irrXML (see their zlib license). Added mainly for compatibility with their Collada loader.
diff --git a/core/io/zip_io.cpp b/core/io/zip_io.cpp
new file mode 100644
index 0000000000..b7f841b66f
--- /dev/null
+++ b/core/io/zip_io.cpp
@@ -0,0 +1,137 @@
+/*************************************************************************/
+/* zip_io.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 "zip_io.h"
+
+#include "core/os/copymem.h"
+
+void *zipio_open(void *data, const char *p_fname, int mode) {
+
+ FileAccess *&f = *(FileAccess **)data;
+
+ String fname;
+ fname.parse_utf8(p_fname);
+
+ if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
+ f = FileAccess::open(fname, FileAccess::WRITE);
+ } else {
+
+ f = FileAccess::open(fname, FileAccess::READ);
+ }
+
+ if (!f)
+ return NULL;
+
+ return data;
+}
+
+uLong zipio_read(void *data, void *fdata, void *buf, uLong size) {
+
+ FileAccess *f = *(FileAccess **)data;
+ return f->get_buffer((uint8_t *)buf, size);
+}
+
+uLong zipio_write(voidpf opaque, voidpf stream, const void *buf, uLong size) {
+
+ FileAccess *f = *(FileAccess **)opaque;
+ f->store_buffer((uint8_t *)buf, size);
+ return size;
+}
+
+long zipio_tell(voidpf opaque, voidpf stream) {
+
+ FileAccess *f = *(FileAccess **)opaque;
+ return f->get_position();
+}
+
+long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
+
+ FileAccess *f = *(FileAccess **)opaque;
+
+ int pos = offset;
+ switch (origin) {
+
+ case ZLIB_FILEFUNC_SEEK_CUR:
+ pos = f->get_position() + offset;
+ break;
+ case ZLIB_FILEFUNC_SEEK_END:
+ pos = f->get_len() + offset;
+ break;
+ default:
+ break;
+ };
+
+ f->seek(pos);
+ return 0;
+}
+
+int zipio_close(voidpf opaque, voidpf stream) {
+
+ FileAccess *&f = *(FileAccess **)opaque;
+ if (f) {
+ f->close();
+ f = NULL;
+ }
+ return 0;
+}
+
+int zipio_testerror(voidpf opaque, voidpf stream) {
+
+ FileAccess *f = *(FileAccess **)opaque;
+ return (f && f->get_error() != OK) ? 1 : 0;
+}
+
+voidpf zipio_alloc(voidpf opaque, uInt items, uInt size) {
+
+ voidpf ptr = memalloc(items * size);
+ zeromem(ptr, items * size);
+ return ptr;
+}
+
+void zipio_free(voidpf opaque, voidpf address) {
+
+ memfree(address);
+}
+
+zlib_filefunc_def zipio_create_io_from_file(FileAccess **p_file) {
+
+ zlib_filefunc_def io;
+ io.opaque = p_file;
+ io.zopen_file = zipio_open;
+ io.zread_file = zipio_read;
+ io.zwrite_file = zipio_write;
+ io.ztell_file = zipio_tell;
+ io.zseek_file = zipio_seek;
+ io.zclose_file = zipio_close;
+ io.zerror_file = zipio_testerror;
+ io.alloc_mem = zipio_alloc;
+ io.free_mem = zipio_free;
+ return io;
+}
diff --git a/core/io/zip_io.h b/core/io/zip_io.h
index 3a7fdb0302..bba7d67332 100644
--- a/core/io/zip_io.h
+++ b/core/io/zip_io.h
@@ -31,114 +31,28 @@
#ifndef ZIP_IO_H
#define ZIP_IO_H
-#include "os/copymem.h"
-#include "os/file_access.h"
+#include "core/os/file_access.h"
+// Not direclty used in this header, but assumed available in downstream users
+// like platform/*/export/export.cpp. Could be fixed, but probably better to have
+// thirdparty includes in as little headers as possible.
#include "thirdparty/minizip/unzip.h"
#include "thirdparty/minizip/zip.h"
-static void *zipio_open(void *data, const char *p_fname, int mode) {
+void *zipio_open(void *data, const char *p_fname, int mode);
+uLong zipio_read(void *data, void *fdata, void *buf, uLong size);
+uLong zipio_write(voidpf opaque, voidpf stream, const void *buf, uLong size);
- FileAccess *&f = *(FileAccess **)data;
+long zipio_tell(voidpf opaque, voidpf stream);
+long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin);
- String fname;
- fname.parse_utf8(p_fname);
+int zipio_close(voidpf opaque, voidpf stream);
- if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
- f = FileAccess::open(fname, FileAccess::WRITE);
- } else {
+int zipio_testerror(voidpf opaque, voidpf stream);
- f = FileAccess::open(fname, FileAccess::READ);
- }
+voidpf zipio_alloc(voidpf opaque, uInt items, uInt size);
+void zipio_free(voidpf opaque, voidpf address);
- if (!f)
- return NULL;
-
- return data;
-};
-
-static uLong zipio_read(void *data, void *fdata, void *buf, uLong size) {
-
- FileAccess *f = *(FileAccess **)data;
- return f->get_buffer((uint8_t *)buf, size);
-};
-
-static uLong zipio_write(voidpf opaque, voidpf stream, const void *buf, uLong size) {
-
- FileAccess *f = *(FileAccess **)opaque;
- f->store_buffer((uint8_t *)buf, size);
- return size;
-};
-
-static long zipio_tell(voidpf opaque, voidpf stream) {
-
- FileAccess *f = *(FileAccess **)opaque;
- return f->get_position();
-};
-
-static long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
-
- FileAccess *f = *(FileAccess **)opaque;
-
- int pos = offset;
- switch (origin) {
-
- case ZLIB_FILEFUNC_SEEK_CUR:
- pos = f->get_position() + offset;
- break;
- case ZLIB_FILEFUNC_SEEK_END:
- pos = f->get_len() + offset;
- break;
- default:
- break;
- };
-
- f->seek(pos);
- return 0;
-};
-
-static int zipio_close(voidpf opaque, voidpf stream) {
-
- FileAccess *&f = *(FileAccess **)opaque;
- if (f) {
- f->close();
- f = NULL;
- }
- return 0;
-};
-
-static int zipio_testerror(voidpf opaque, voidpf stream) {
-
- FileAccess *f = *(FileAccess **)opaque;
- return (f && f->get_error() != OK) ? 1 : 0;
-};
-
-static voidpf zipio_alloc(voidpf opaque, uInt items, uInt size) {
-
- voidpf ptr = memalloc(items * size);
- zeromem(ptr, items * size);
- return ptr;
-}
-
-static void zipio_free(voidpf opaque, voidpf address) {
-
- memfree(address);
-}
-
-static zlib_filefunc_def zipio_create_io_from_file(FileAccess **p_file) {
-
- zlib_filefunc_def io;
- io.opaque = p_file;
- io.zopen_file = zipio_open;
- io.zread_file = zipio_read;
- io.zwrite_file = zipio_write;
- io.ztell_file = zipio_tell;
- io.zseek_file = zipio_seek;
- io.zclose_file = zipio_close;
- io.zerror_file = zipio_testerror;
- io.alloc_mem = zipio_alloc;
- io.free_mem = zipio_free;
- return io;
-}
+zlib_filefunc_def zipio_create_io_from_file(FileAccess **p_file);
#endif // ZIP_IO_H