2014-02-10 01:10:30 +00:00
/*************************************************************************/
/* file_access_network.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 12:16:55 +00:00
/* https://godotengine.org */
2014-02-10 01:10:30 +00:00
/*************************************************************************/
2020-01-01 10:16:22 +00:00
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
2014-02-10 01:10:30 +00:00
/* */
/* 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. */
/*************************************************************************/
2018-01-04 23:50:27 +00:00
2014-02-10 01:10:30 +00:00
# include "file_access_network.h"
2018-09-11 16:13:45 +00:00
# include "core/io/ip.h"
# include "core/io/marshalls.h"
# include "core/os/os.h"
# include "core/project_settings.h"
2014-02-10 01:10:30 +00:00
2016-01-20 03:29:34 +00:00
//#define DEBUG_PRINT(m_p) print_line(m_p)
2014-02-10 01:10:30 +00:00
//#define DEBUG_TIME(m_what) printf("MS: %s - %lli\n",m_what,OS::get_singleton()->get_ticks_usec());
2016-01-20 03:29:34 +00:00
# define DEBUG_PRINT(m_p)
2014-02-10 01:10:30 +00:00
# define DEBUG_TIME(m_what)
void FileAccessNetworkClient : : lock_mutex ( ) {
mutex - > lock ( ) ;
lockcount + + ;
}
void FileAccessNetworkClient : : unlock_mutex ( ) {
lockcount - - ;
mutex - > unlock ( ) ;
}
void FileAccessNetworkClient : : put_32 ( int p_32 ) {
uint8_t buf [ 4 ] ;
2017-03-05 15:44:50 +00:00
encode_uint32 ( p_32 , buf ) ;
client - > put_data ( buf , 4 ) ;
DEBUG_PRINT ( " put32: " + itos ( p_32 ) ) ;
2014-02-10 01:10:30 +00:00
}
void FileAccessNetworkClient : : put_64 ( int64_t p_64 ) {
uint8_t buf [ 8 ] ;
2017-03-05 15:44:50 +00:00
encode_uint64 ( p_64 , buf ) ;
client - > put_data ( buf , 8 ) ;
DEBUG_PRINT ( " put64: " + itos ( p_64 ) ) ;
2014-02-10 01:10:30 +00:00
}
int FileAccessNetworkClient : : get_32 ( ) {
uint8_t buf [ 4 ] ;
2017-03-05 15:44:50 +00:00
client - > get_data ( buf , 4 ) ;
2014-02-10 01:10:30 +00:00
return decode_uint32 ( buf ) ;
}
int64_t FileAccessNetworkClient : : get_64 ( ) {
uint8_t buf [ 8 ] ;
2017-03-05 15:44:50 +00:00
client - > get_data ( buf , 8 ) ;
2014-02-10 01:10:30 +00:00
return decode_uint64 ( buf ) ;
}
void FileAccessNetworkClient : : _thread_func ( ) {
2018-01-30 15:22:15 +00:00
client - > set_no_delay ( true ) ;
2017-03-05 15:44:50 +00:00
while ( ! quit ) {
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
DEBUG_PRINT ( " SEM WAIT - " + itos ( sem - > get ( ) ) ) ;
2014-02-10 01:10:30 +00:00
Error err = sem - > wait ( ) ;
2017-09-02 20:32:31 +00:00
if ( err ! = OK )
ERR_PRINT ( " sem->wait() failed " ) ;
2014-02-10 01:10:30 +00:00
DEBUG_TIME ( " sem_unlock " ) ;
//DEBUG_PRINT("semwait returned "+itos(werr));
2017-03-05 15:44:50 +00:00
DEBUG_PRINT ( " MUTEX LOCK " + itos ( lockcount ) ) ;
2014-02-10 01:10:30 +00:00
lock_mutex ( ) ;
DEBUG_PRINT ( " MUTEX PASS " ) ;
blockrequest_mutex - > lock ( ) ;
2017-03-05 15:44:50 +00:00
while ( block_requests . size ( ) ) {
2014-02-10 01:10:30 +00:00
put_32 ( block_requests . front ( ) - > get ( ) . id ) ;
put_32 ( FileAccessNetwork : : COMMAND_READ_BLOCK ) ;
put_64 ( block_requests . front ( ) - > get ( ) . offset ) ;
put_32 ( block_requests . front ( ) - > get ( ) . size ) ;
block_requests . pop_front ( ) ;
}
blockrequest_mutex - > unlock ( ) ;
DEBUG_PRINT ( " THREAD ITER " ) ;
DEBUG_TIME ( " sem_read " ) ;
int id = get_32 ( ) ;
int response = get_32 ( ) ;
2017-03-05 15:44:50 +00:00
DEBUG_PRINT ( " GET RESPONSE: " + itos ( response ) ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
FileAccessNetwork * fa = NULL ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
if ( response ! = FileAccessNetwork : : RESPONSE_DATA ) {
2019-05-30 08:28:03 +00:00
if ( ! accesses . has ( id ) ) {
unlock_mutex ( ) ;
ERR_FAIL_COND ( ! accesses . has ( id ) ) ;
}
2014-02-10 01:10:30 +00:00
}
if ( accesses . has ( id ) )
2017-03-05 15:44:50 +00:00
fa = accesses [ id ] ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
switch ( response ) {
2014-02-10 01:10:30 +00:00
case FileAccessNetwork : : RESPONSE_OPEN : {
DEBUG_TIME ( " sem_open " ) ;
int status = get_32 ( ) ;
2017-03-05 15:44:50 +00:00
if ( status ! = OK ) {
fa - > _respond ( 0 , Error ( status ) ) ;
2014-02-10 01:10:30 +00:00
} else {
uint64_t len = get_64 ( ) ;
2017-03-05 15:44:50 +00:00
fa - > _respond ( len , Error ( status ) ) ;
2014-02-10 01:10:30 +00:00
}
fa - > sem - > post ( ) ;
} break ;
case FileAccessNetwork : : RESPONSE_DATA : {
int64_t offset = get_64 ( ) ;
uint32_t len = get_32 ( ) ;
Vector < uint8_t > block ;
block . resize ( len ) ;
2017-11-25 03:07:54 +00:00
client - > get_data ( block . ptrw ( ) , len ) ;
2014-02-10 01:10:30 +00:00
if ( fa ) //may have been queued
2017-03-05 15:44:50 +00:00
fa - > _set_block ( offset , block ) ;
2014-02-10 01:10:30 +00:00
} break ;
case FileAccessNetwork : : RESPONSE_FILE_EXISTS : {
int status = get_32 ( ) ;
2017-03-05 15:44:50 +00:00
fa - > exists_modtime = status ! = 0 ;
2014-02-10 01:10:30 +00:00
fa - > sem - > post ( ) ;
} break ;
case FileAccessNetwork : : RESPONSE_GET_MODTIME : {
uint64_t status = get_64 ( ) ;
2017-03-05 15:44:50 +00:00
fa - > exists_modtime = status ;
2014-02-10 01:10:30 +00:00
fa - > sem - > post ( ) ;
} break ;
}
unlock_mutex ( ) ;
}
}
void FileAccessNetworkClient : : _thread_func ( void * s ) {
2017-03-05 15:44:50 +00:00
FileAccessNetworkClient * self = ( FileAccessNetworkClient * ) s ;
2014-02-10 01:10:30 +00:00
self - > _thread_func ( ) ;
}
2017-03-05 15:44:50 +00:00
Error FileAccessNetworkClient : : connect ( const String & p_host , int p_port , const String & p_password ) {
2014-02-10 01:10:30 +00:00
IP_Address ip ;
if ( p_host . is_valid_ip_address ( ) ) {
2017-03-05 15:44:50 +00:00
ip = p_host ;
2014-02-10 01:10:30 +00:00
} else {
2017-03-05 15:44:50 +00:00
ip = IP : : get_singleton ( ) - > resolve_hostname ( p_host ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
DEBUG_PRINT ( " IP: " + String ( ip ) + " port " + itos ( p_port ) ) ;
Error err = client - > connect_to_host ( ip , p_port ) ;
2019-09-25 08:28:50 +00:00
ERR_FAIL_COND_V_MSG ( err ! = OK , err , " Cannot connect to host with IP: " + String ( ip ) + " and port: " + itos ( p_port ) ) ;
2017-03-05 15:44:50 +00:00
while ( client - > get_status ( ) = = StreamPeerTCP : : STATUS_CONNECTING ) {
//DEBUG_PRINT("trying to connect....");
2014-02-10 01:10:30 +00:00
OS : : get_singleton ( ) - > delay_usec ( 1000 ) ;
}
2017-03-05 15:44:50 +00:00
if ( client - > get_status ( ) ! = StreamPeerTCP : : STATUS_CONNECTED ) {
2014-02-10 01:10:30 +00:00
return ERR_CANT_CONNECT ;
}
2016-03-08 23:00:52 +00:00
CharString cs = p_password . utf8 ( ) ;
2014-02-10 01:10:30 +00:00
put_32 ( cs . length ( ) ) ;
2017-03-05 15:44:50 +00:00
client - > put_data ( ( const uint8_t * ) cs . ptr ( ) , cs . length ( ) ) ;
2014-02-10 01:10:30 +00:00
int e = get_32 ( ) ;
2017-03-05 15:44:50 +00:00
if ( e ! = OK ) {
2014-02-10 01:10:30 +00:00
return ERR_INVALID_PARAMETER ;
}
2017-03-05 15:44:50 +00:00
thread = Thread : : create ( _thread_func , this ) ;
2014-02-10 01:10:30 +00:00
return OK ;
}
2017-03-05 15:44:50 +00:00
FileAccessNetworkClient * FileAccessNetworkClient : : singleton = NULL ;
2014-02-10 01:10:30 +00:00
FileAccessNetworkClient : : FileAccessNetworkClient ( ) {
2017-03-05 15:44:50 +00:00
thread = NULL ;
2014-02-10 01:10:30 +00:00
mutex = Mutex : : create ( ) ;
blockrequest_mutex = Mutex : : create ( ) ;
2017-03-05 15:44:50 +00:00
quit = false ;
singleton = this ;
last_id = 0 ;
2018-09-02 04:36:45 +00:00
client . instance ( ) ;
2017-03-05 15:44:50 +00:00
sem = Semaphore : : create ( ) ;
lockcount = 0 ;
2014-02-10 01:10:30 +00:00
}
FileAccessNetworkClient : : ~ FileAccessNetworkClient ( ) {
if ( thread ) {
2017-03-05 15:44:50 +00:00
quit = true ;
2014-02-10 01:10:30 +00:00
sem - > post ( ) ;
Thread : : wait_to_finish ( thread ) ;
2015-04-20 22:38:02 +00:00
memdelete ( thread ) ;
2014-02-10 01:10:30 +00:00
}
memdelete ( blockrequest_mutex ) ;
memdelete ( mutex ) ;
memdelete ( sem ) ;
}
2017-08-31 21:30:35 +00:00
void FileAccessNetwork : : _set_block ( int p_offset , const Vector < uint8_t > & p_block ) {
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
int page = p_offset / page_size ;
ERR_FAIL_INDEX ( page , pages . size ( ) ) ;
if ( page < pages . size ( ) - 1 ) {
ERR_FAIL_COND ( p_block . size ( ) ! = page_size ) ;
2014-02-10 01:10:30 +00:00
} else {
2017-08-31 21:30:35 +00:00
ERR_FAIL_COND ( ( p_block . size ( ) ! = ( int ) ( total_size % page_size ) ) ) ;
2014-02-10 01:10:30 +00:00
}
buffer_mutex - > lock ( ) ;
2018-07-25 01:11:03 +00:00
pages . write [ page ] . buffer = p_block ;
pages . write [ page ] . queued = false ;
2014-02-10 01:10:30 +00:00
buffer_mutex - > unlock ( ) ;
2017-03-05 15:44:50 +00:00
if ( waiting_on_page = = page ) {
waiting_on_page = - 1 ;
2014-02-10 01:10:30 +00:00
page_sem - > post ( ) ;
}
}
2017-03-05 15:44:50 +00:00
void FileAccessNetwork : : _respond ( size_t p_len , Error p_status ) {
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
DEBUG_PRINT ( " GOT RESPONSE - len: " + itos ( p_len ) + " status: " + itos ( p_status ) ) ;
response = p_status ;
if ( response ! = OK )
2014-02-10 01:10:30 +00:00
return ;
2017-03-05 15:44:50 +00:00
opened = true ;
total_size = p_len ;
int pc = ( ( total_size - 1 ) / page_size ) + 1 ;
2014-02-10 01:10:30 +00:00
pages . resize ( pc ) ;
}
2017-03-05 15:44:50 +00:00
Error FileAccessNetwork : : _open ( const String & p_path , int p_mode_flags ) {
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
ERR_FAIL_COND_V ( p_mode_flags ! = READ , ERR_UNAVAILABLE ) ;
2014-02-10 01:10:30 +00:00
if ( opened )
close ( ) ;
FileAccessNetworkClient * nc = FileAccessNetworkClient : : singleton ;
2017-03-05 15:44:50 +00:00
DEBUG_PRINT ( " open: " + p_path ) ;
2014-02-10 01:10:30 +00:00
DEBUG_TIME ( " open_begin " ) ;
nc - > lock_mutex ( ) ;
nc - > put_32 ( id ) ;
2017-03-05 15:44:50 +00:00
nc - > accesses [ id ] = this ;
2014-02-10 01:10:30 +00:00
nc - > put_32 ( COMMAND_OPEN_FILE ) ;
2017-03-05 15:44:50 +00:00
CharString cs = p_path . utf8 ( ) ;
2014-02-10 01:10:30 +00:00
nc - > put_32 ( cs . length ( ) ) ;
2017-03-05 15:44:50 +00:00
nc - > client - > put_data ( ( const uint8_t * ) cs . ptr ( ) , cs . length ( ) ) ;
pos = 0 ;
eof_flag = false ;
last_page = - 1 ;
last_page_buff = NULL ;
2014-02-10 01:10:30 +00:00
2017-01-14 11:26:56 +00:00
//buffers.clear();
2014-02-10 01:10:30 +00:00
nc - > unlock_mutex ( ) ;
DEBUG_PRINT ( " OPEN POST " ) ;
DEBUG_TIME ( " open_post " ) ;
nc - > sem - > post ( ) ; //awaiting answer
DEBUG_PRINT ( " WAIT... " ) ;
sem - > wait ( ) ;
DEBUG_TIME ( " open_end " ) ;
DEBUG_PRINT ( " WAIT ENDED... " ) ;
return response ;
}
2017-03-05 15:44:50 +00:00
void FileAccessNetwork : : close ( ) {
2014-02-10 01:10:30 +00:00
if ( ! opened )
return ;
FileAccessNetworkClient * nc = FileAccessNetworkClient : : singleton ;
DEBUG_PRINT ( " CLOSE " ) ;
nc - > lock_mutex ( ) ;
nc - > put_32 ( id ) ;
nc - > put_32 ( COMMAND_CLOSE ) ;
pages . clear ( ) ;
2017-03-05 15:44:50 +00:00
opened = false ;
2014-02-10 01:10:30 +00:00
nc - > unlock_mutex ( ) ;
}
2017-03-05 15:44:50 +00:00
bool FileAccessNetwork : : is_open ( ) const {
2014-02-10 01:10:30 +00:00
return opened ;
}
2017-03-05 15:44:50 +00:00
void FileAccessNetwork : : seek ( size_t p_position ) {
2014-02-10 01:10:30 +00:00
2019-09-25 08:28:50 +00:00
ERR_FAIL_COND_MSG ( ! opened , " File must be opened before use. " ) ;
2017-03-05 15:44:50 +00:00
eof_flag = p_position > total_size ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
if ( p_position > = total_size ) {
p_position = total_size ;
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
pos = p_position ;
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
void FileAccessNetwork : : seek_end ( int64_t p_position ) {
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
seek ( total_size + p_position ) ;
2014-02-10 01:10:30 +00:00
}
2017-09-10 13:37:49 +00:00
size_t FileAccessNetwork : : get_position ( ) const {
2014-02-10 01:10:30 +00:00
2019-09-25 08:28:50 +00:00
ERR_FAIL_COND_V_MSG ( ! opened , 0 , " File must be opened before use. " ) ;
2014-02-10 01:10:30 +00:00
return pos ;
}
2017-03-05 15:44:50 +00:00
size_t FileAccessNetwork : : get_len ( ) const {
2014-02-10 01:10:30 +00:00
2019-09-25 08:28:50 +00:00
ERR_FAIL_COND_V_MSG ( ! opened , 0 , " File must be opened before use. " ) ;
2014-02-10 01:10:30 +00:00
return total_size ;
}
2017-03-05 15:44:50 +00:00
bool FileAccessNetwork : : eof_reached ( ) const {
2014-02-10 01:10:30 +00:00
2019-09-25 08:28:50 +00:00
ERR_FAIL_COND_V_MSG ( ! opened , false , " File must be opened before use. " ) ;
2014-02-10 01:10:30 +00:00
return eof_flag ;
}
2017-03-05 15:44:50 +00:00
uint8_t FileAccessNetwork : : get_8 ( ) const {
2014-02-10 01:10:30 +00:00
uint8_t v ;
2017-03-05 15:44:50 +00:00
get_buffer ( & v , 1 ) ;
2014-02-10 01:10:30 +00:00
return v ;
}
void FileAccessNetwork : : _queue_page ( int p_page ) const {
2017-03-05 15:44:50 +00:00
if ( p_page > = pages . size ( ) )
2014-02-10 01:10:30 +00:00
return ;
if ( pages [ p_page ] . buffer . empty ( ) & & ! pages [ p_page ] . queued ) {
FileAccessNetworkClient * nc = FileAccessNetworkClient : : singleton ;
nc - > blockrequest_mutex - > lock ( ) ;
FileAccessNetworkClient : : BlockRequest br ;
2017-03-05 15:44:50 +00:00
br . id = id ;
br . offset = size_t ( p_page ) * page_size ;
br . size = page_size ;
2014-02-10 01:10:30 +00:00
nc - > block_requests . push_back ( br ) ;
2018-07-25 01:11:03 +00:00
pages . write [ p_page ] . queued = true ;
2014-02-10 01:10:30 +00:00
nc - > blockrequest_mutex - > unlock ( ) ;
DEBUG_PRINT ( " QUEUE PAGE POST " ) ;
nc - > sem - > post ( ) ;
2017-03-05 15:44:50 +00:00
DEBUG_PRINT ( " queued " + itos ( p_page ) ) ;
2014-02-10 01:10:30 +00:00
}
}
2017-03-05 15:44:50 +00:00
int FileAccessNetwork : : get_buffer ( uint8_t * p_dst , int p_length ) const {
2014-02-10 01:10:30 +00:00
//bool eof=false;
2017-03-05 15:44:50 +00:00
if ( pos + p_length > total_size ) {
eof_flag = true ;
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
if ( pos + p_length > = total_size ) {
p_length = total_size - pos ;
2014-02-10 01:10:30 +00:00
}
2017-01-14 11:26:56 +00:00
//FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
uint8_t * buff = last_page_buff ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < p_length ; i + + ) {
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
int page = pos / page_size ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
if ( page ! = last_page ) {
2014-02-10 01:10:30 +00:00
buffer_mutex - > lock ( ) ;
if ( pages [ page ] . buffer . empty ( ) ) {
2017-03-05 15:44:50 +00:00
waiting_on_page = page ;
for ( int j = 0 ; j < read_ahead ; j + + ) {
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
_queue_page ( page + j ) ;
2014-02-10 01:10:30 +00:00
}
buffer_mutex - > unlock ( ) ;
DEBUG_PRINT ( " wait " ) ;
page_sem - > wait ( ) ;
DEBUG_PRINT ( " done " ) ;
} else {
2017-03-05 15:44:50 +00:00
for ( int j = 0 ; j < read_ahead ; j + + ) {
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
_queue_page ( page + j ) ;
2014-02-10 01:10:30 +00:00
}
//queue pages
buffer_mutex - > unlock ( ) ;
}
2018-07-25 01:11:03 +00:00
buff = pages . write [ page ] . buffer . ptrw ( ) ;
2017-03-05 15:44:50 +00:00
last_page_buff = buff ;
last_page = page ;
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
p_dst [ i ] = buff [ pos - uint64_t ( page ) * page_size ] ;
2014-02-10 01:10:30 +00:00
pos + + ;
}
return p_length ;
}
2017-03-05 15:44:50 +00:00
Error FileAccessNetwork : : get_error ( ) const {
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
return pos = = total_size ? ERR_FILE_EOF : OK ;
2014-02-10 01:10:30 +00:00
}
2017-09-22 05:56:02 +00:00
void FileAccessNetwork : : flush ( ) {
ERR_FAIL ( ) ;
}
2014-02-10 01:10:30 +00:00
void FileAccessNetwork : : store_8 ( uint8_t p_dest ) {
ERR_FAIL ( ) ;
}
2017-03-05 15:44:50 +00:00
bool FileAccessNetwork : : file_exists ( const String & p_path ) {
2014-02-10 01:10:30 +00:00
FileAccessNetworkClient * nc = FileAccessNetworkClient : : singleton ;
nc - > lock_mutex ( ) ;
nc - > put_32 ( id ) ;
nc - > put_32 ( COMMAND_FILE_EXISTS ) ;
2017-03-05 15:44:50 +00:00
CharString cs = p_path . utf8 ( ) ;
2014-02-10 01:10:30 +00:00
nc - > put_32 ( cs . length ( ) ) ;
2017-03-05 15:44:50 +00:00
nc - > client - > put_data ( ( const uint8_t * ) cs . ptr ( ) , cs . length ( ) ) ;
2014-02-10 01:10:30 +00:00
nc - > unlock_mutex ( ) ;
DEBUG_PRINT ( " FILE EXISTS POST " ) ;
nc - > sem - > post ( ) ;
sem - > wait ( ) ;
2017-03-05 15:44:50 +00:00
return exists_modtime ! = 0 ;
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
uint64_t FileAccessNetwork : : _get_modified_time ( const String & p_file ) {
2014-02-10 01:10:30 +00:00
FileAccessNetworkClient * nc = FileAccessNetworkClient : : singleton ;
nc - > lock_mutex ( ) ;
nc - > put_32 ( id ) ;
nc - > put_32 ( COMMAND_GET_MODTIME ) ;
2017-03-05 15:44:50 +00:00
CharString cs = p_file . utf8 ( ) ;
2014-02-10 01:10:30 +00:00
nc - > put_32 ( cs . length ( ) ) ;
2017-03-05 15:44:50 +00:00
nc - > client - > put_data ( ( const uint8_t * ) cs . ptr ( ) , cs . length ( ) ) ;
2014-02-10 01:10:30 +00:00
nc - > unlock_mutex ( ) ;
DEBUG_PRINT ( " MODTIME POST " ) ;
nc - > sem - > post ( ) ;
sem - > wait ( ) ;
return exists_modtime ;
}
2019-04-07 18:46:52 +00:00
uint32_t FileAccessNetwork : : _get_unix_permissions ( const String & p_file ) {
2019-06-03 12:20:43 +00:00
ERR_PRINT ( " Getting UNIX permissions from network drives is not implemented yet " ) ;
2019-04-07 18:46:52 +00:00
return 0 ;
}
Error FileAccessNetwork : : _set_unix_permissions ( const String & p_file , uint32_t p_permissions ) {
2019-06-03 12:20:43 +00:00
ERR_PRINT ( " Setting UNIX permissions on network drives is not implemented yet " ) ;
return ERR_UNAVAILABLE ;
2019-04-07 18:46:52 +00:00
}
2017-01-05 12:16:00 +00:00
void FileAccessNetwork : : configure ( ) {
2017-03-05 15:44:50 +00:00
GLOBAL_DEF ( " network/remote_fs/page_size " , 65536 ) ;
2018-10-05 16:43:53 +00:00
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
2017-03-05 15:44:50 +00:00
GLOBAL_DEF ( " network/remote_fs/page_read_ahead " , 4 ) ;
2018-10-05 16:43:53 +00:00
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 " ) ) ;
2017-01-05 12:16:00 +00:00
}
2014-02-10 01:10:30 +00:00
FileAccessNetwork : : FileAccessNetwork ( ) {
2017-03-05 15:44:50 +00:00
eof_flag = false ;
opened = false ;
pos = 0 ;
sem = Semaphore : : create ( ) ;
page_sem = Semaphore : : create ( ) ;
buffer_mutex = Mutex : : create ( ) ;
2014-02-10 01:10:30 +00:00
FileAccessNetworkClient * nc = FileAccessNetworkClient : : singleton ;
nc - > lock_mutex ( ) ;
2017-03-05 15:44:50 +00:00
id = nc - > last_id + + ;
nc - > accesses [ id ] = this ;
2014-02-10 01:10:30 +00:00
nc - > unlock_mutex ( ) ;
2017-01-05 12:16:00 +00:00
page_size = GLOBAL_GET ( " network/remote_fs/page_size " ) ;
read_ahead = GLOBAL_GET ( " network/remote_fs/page_read_ahead " ) ;
2017-03-05 15:44:50 +00:00
last_activity_val = 0 ;
waiting_on_page = - 1 ;
last_page = - 1 ;
2014-02-10 01:10:30 +00:00
}
FileAccessNetwork : : ~ FileAccessNetwork ( ) {
close ( ) ;
memdelete ( sem ) ;
memdelete ( page_sem ) ;
memdelete ( buffer_mutex ) ;
FileAccessNetworkClient * nc = FileAccessNetworkClient : : singleton ;
nc - > lock_mutex ( ) ;
2017-03-05 15:44:50 +00:00
id = nc - > last_id + + ;
2014-02-10 01:10:30 +00:00
nc - > accesses . erase ( id ) ;
nc - > unlock_mutex ( ) ;
}