Sfoglia il codice sorgente

Add NetworkFile and NetworkFilesystem

Daniele Bartolini 12 anni fa
parent
commit
c2f18ffdfd

+ 185 - 0
engine/core/filesystem/NetworkFile.cpp

@@ -0,0 +1,185 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+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 "JSONParser.h"
+#include "List.h"
+#include "Log.h"
+#include "MathUtils.h"
+#include "NetworkFile.h"
+#include "NetworkFilesystem.h"
+#include "StringStream.h"
+#include "StringUtils.h"
+#include "TempAllocator.h"
+#include "Types.h"
+#include "DynamicString.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+NetworkFile::NetworkFile(const NetAddress& addr, uint16_t port, const char* filename)
+	: File(FOM_READ)
+	, m_address(addr)
+	, m_port(port)
+	, m_position(0)
+{
+	string::strncpy(m_filename, filename, MAX_PATH_LENGTH);
+	m_socket.open(addr, port);
+}
+
+//-----------------------------------------------------------------------------
+NetworkFile::~NetworkFile()
+{
+	m_socket.close();
+}
+
+//-----------------------------------------------------------------------------
+void NetworkFile::seek(size_t position)
+{
+	m_position = position;
+}
+
+//-----------------------------------------------------------------------------
+void NetworkFile::seek_to_end()
+{
+	m_position = size();
+}
+
+//-----------------------------------------------------------------------------
+void NetworkFile::skip(size_t bytes)
+{
+	m_position += bytes;
+}
+
+//-----------------------------------------------------------------------------
+void NetworkFile::read(void* buffer, size_t size)
+{
+	TempAllocator1024 alloc;
+	StringStream command(alloc);
+
+	// Request the file
+	command << "{\"type\":\"filesystem\",\"filesystem\":\"read\",";
+	command << "\"file\":\"" << m_filename << "\",";
+	command << "\"position\":" << m_position << ",";
+	command << "\"size\":" << size << "}";
+
+	network_filesystem::send(m_socket, command.c_str());
+
+	// Wait for response
+	List<char> response(default_allocator());
+	network_filesystem::read_response(m_socket, response);
+
+	// Parse the response
+	JSONParser json(response.begin());
+	JSONElement root = json.root();
+
+	DynamicString data_base64;
+	root.key("data").string_value(data_base64);
+
+	size_t out_len = 0;
+	unsigned char* data = math::base64_decode(data_base64.c_str(), data_base64.length(), &out_len);
+	memcpy(buffer, data, sizeof(unsigned char) * out_len);
+	default_allocator().deallocate(data);
+}
+
+//-----------------------------------------------------------------------------
+void NetworkFile::write(const void* /*buffer*/, size_t /*size*/)
+{
+	CE_FATAL("Cannot write to a network file");
+}
+
+//-----------------------------------------------------------------------------
+bool NetworkFile::copy_to(File& file, size_t size)
+{
+	return true;
+}
+
+//-----------------------------------------------------------------------------
+bool NetworkFile::end_of_file()
+{
+	return position() == size();
+}
+
+//-----------------------------------------------------------------------------
+bool NetworkFile::is_valid()
+{
+	return true;
+}
+
+//-----------------------------------------------------------------------------
+void NetworkFile::flush()
+{
+	// Do nothing
+}
+
+//-----------------------------------------------------------------------------
+size_t NetworkFile::position()
+{
+	return m_position;
+}
+
+//-----------------------------------------------------------------------------
+size_t NetworkFile::size()
+{
+	TempAllocator1024 alloc;
+	StringStream command(alloc);
+
+	// Request the file
+	command << "{\"type\":\"filesystem\",\"filesystem\":\"size\",";
+	command << "\"file\":\"" << m_filename << "\"}";
+
+	network_filesystem::send(m_socket, command.c_str());
+
+	// Wait for response
+	List<char> response(default_allocator());
+	network_filesystem::read_response(m_socket, response);
+
+	JSONParser parser(response.begin());
+	JSONElement root = parser.root();
+
+	return (size_t) root.key("size").int_value();
+}
+
+//-----------------------------------------------------------------------------
+bool NetworkFile::can_read() const
+{
+	return true;
+}
+
+//-----------------------------------------------------------------------------
+bool NetworkFile::can_write() const
+{
+	return false;
+}
+
+//-----------------------------------------------------------------------------
+bool NetworkFile::can_seek() const
+{
+	return true;
+}
+
+} // namespace crown
+

+ 99 - 0
engine/core/filesystem/NetworkFile.h

@@ -0,0 +1,99 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+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.
+*/
+
+#pragma once
+
+#include "Assert.h"
+#include "File.h"
+#include "OsSocket.h"
+#include "File.h"
+#include "HeapAllocator.h"
+
+namespace crown
+{
+
+/// Access file on a remote file server.
+class NetworkFile: public File
+{
+public:
+
+	/// Reads the file named @a filename from the given @a socket.
+					NetworkFile(const NetAddress& addr, uint16_t port, const char* filename);
+	virtual			~NetworkFile();
+
+	/// @copydoc File::seek() 
+	void			seek(size_t position);
+
+	/// @copydoc File::seek_to_end() 
+	void			seek_to_end();
+
+	/// @copydoc File::skip() 
+	void			skip(size_t bytes);
+
+	/// @copydoc File::read() 
+	void			read(void* buffer, size_t size);
+
+	/// @copydoc File::write() 
+	void			write(const void* buffer, size_t size);
+
+	/// @copydoc File::copy_to() 
+	bool			copy_to(File& file, size_t size = 0);
+
+	/// @copydoc File::flush() 
+	void			flush();
+
+	/// @copydoc File::end_of_file() 
+	bool			end_of_file();
+
+	/// @copydoc File::is_valid() 
+	bool			is_valid();
+
+	/// @copydoc File::size() 
+	size_t			size();
+
+	/// @copydoc File::position() 
+	size_t			position();
+
+	/// @copydoc File::can_read() 
+	bool			can_read() const;
+
+	/// @copydoc File::can_write() 
+	bool			can_write() const;
+
+	/// @copydoc File::can_seek() 
+	bool			can_seek() const;
+
+private:
+
+	char			m_filename[MAX_PATH_LENGTH];
+	NetAddress		m_address;
+	uint16_t		m_port;
+	TCPSocket		m_socket;
+	size_t			m_position;
+};
+
+} // namespace crown
+

+ 114 - 0
engine/core/filesystem/NetworkFilesystem.cpp

@@ -0,0 +1,114 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+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 "JSONParser.h"
+#include "NetworkFile.h"
+#include "NetworkFilesystem.h"
+#include "OS.h"
+#include "StringUtils.h"
+#include "TempAllocator.h"
+#include "StringStream.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+NetworkFilesystem::NetworkFilesystem()
+{
+}
+
+//-----------------------------------------------------------------------------
+NetworkFilesystem::NetworkFilesystem(const NetAddress& addr, uint16_t port)
+	: m_address(addr)
+	, m_port(port)
+{
+}
+
+//-----------------------------------------------------------------------------
+File* NetworkFilesystem::open(const char* path, FileOpenMode mode)
+{
+	return CE_NEW(default_allocator(), NetworkFile)(m_address, m_port, path);
+}
+
+//-----------------------------------------------------------------------------
+void NetworkFilesystem::close(File* file)
+{
+	CE_ASSERT_NOT_NULL(file);
+	CE_DELETE(default_allocator(), file);
+}
+
+//-----------------------------------------------------------------------------
+bool NetworkFilesystem::is_directory(const char* path)
+{
+
+}
+
+//-----------------------------------------------------------------------------
+bool NetworkFilesystem::is_file(const char* path)
+{
+
+}
+
+//-----------------------------------------------------------------------------
+void NetworkFilesystem::create_directory(const char* /*path*/)
+{
+}
+
+//-----------------------------------------------------------------------------
+void NetworkFilesystem::delete_directory(const char* /*path*/)
+{
+}
+
+//-----------------------------------------------------------------------------
+void NetworkFilesystem::create_file(const char* /*path*/)
+{
+}
+
+//-----------------------------------------------------------------------------
+void NetworkFilesystem::delete_file(const char* /*path*/)
+{
+}
+
+//-----------------------------------------------------------------------------
+void NetworkFilesystem::list_files(const char* /*path*/, Vector<DynamicString>& /*files*/)
+{
+}
+
+//-----------------------------------------------------------------------------
+void NetworkFilesystem::get_absolute_path(const char* path, DynamicString& os_path)
+{
+
+}
+
+//-----------------------------------------------------------------------------
+TCPSocket NetworkFilesystem::new_connection()
+{
+	TCPSocket socket;
+	socket.open(m_address, m_port);
+	return socket;
+}
+
+} // namespace crown

+ 121 - 0
engine/core/filesystem/NetworkFilesystem.h

@@ -0,0 +1,121 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+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.
+*/
+
+#pragma once
+
+#include "Filesystem.h"
+#include "OsSocket.h"
+#include "OS.h" // For MAX_PATH_LENGTH
+#include "Log.h"
+
+namespace crown
+{
+namespace network_filesystem
+{
+	inline void read_response(TCPSocket socket, List<char>& response)
+	{
+		// Read message length
+		uint32_t msg_len = 0;
+		socket.read(&msg_len, 4);
+
+		response.resize(msg_len);
+		socket.read(response.begin(), msg_len);
+
+		// Ensure NUL-terminated
+		response.push_back('\0');
+	}
+
+	inline void send(TCPSocket socket, const char* msg)
+	{
+		uint32_t msg_len = string::strlen(msg);
+		socket.write(&msg_len, 4);
+		socket.write(msg, msg_len);
+	}
+} // namespace network_filesystem
+
+/// Access files on a remote file server.
+/// All the file paths can be either relative or absolute.
+/// When a relative path is given, it is automatically translated
+/// to its absolute counterpart based on the file server's root path.
+/// Accessing files using absolute path directly is also possible,
+/// but platform-specific and thus generally not recommended.
+class NetworkFilesystem : public Filesystem
+{
+public:
+
+	/// Sets the root path to the current working directory of
+	/// the engine executable.
+	NetworkFilesystem();
+
+	/// Sets the file server address and port.
+	/// @note
+	/// The @a root_path must be absolute.
+	NetworkFilesystem(const NetAddress& addr, uint16_t port);
+
+	/// Opens the file at the given @a path with the given @a mode.
+	File* open(const char* path, FileOpenMode mode);
+
+	/// Closes the given @a file.
+	void close(File* file);
+
+	/// Returns true if @a path is a directory.
+	bool is_directory(const char* path);
+
+	/// Returns true if @a path is a regular file.
+	bool is_file(const char* path);
+
+	/// Creates the directory at the given @a path.
+	void create_directory(const char* path);
+
+	/// Deletes the directory at the given @a path.
+	void delete_directory(const char* path);
+
+	/// Creates the file at the given @a path.
+	void create_file(const char* path);
+
+	/// Deletes the file at the given @a path.
+	void delete_file(const char* path);
+
+	/// Returns the relative file names in the given @a path.
+	void list_files(const char* path, Vector<DynamicString>& files);
+
+	/// Returns the absolute path of the given @a path based on
+	/// the root path of the file source. If @a path is absolute,
+	/// the given path is returned.
+	void get_absolute_path(const char* path, DynamicString& os_path);
+
+private:
+
+	// Returns a new connection to the file server
+	TCPSocket new_connection();
+
+private:
+
+	NetAddress m_address;
+	uint16_t m_port;
+};
+
+} // namespace crown