summaryrefslogtreecommitdiff
path: root/drivers/unix
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2014-02-09 22:10:30 -0300
committerJuan Linietsky <reduzio@gmail.com>2014-02-09 22:10:30 -0300
commit0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac (patch)
tree276c4d099e178eb67fbd14f61d77b05e3808e9e3 /drivers/unix
parent0e49da1687bc8192ed210947da52c9e5c5f301bb (diff)
GODOT IS OPEN SOURCE
Diffstat (limited to 'drivers/unix')
-rw-r--r--drivers/unix/SCsub7
-rw-r--r--drivers/unix/dir_access_unix.cpp312
-rw-r--r--drivers/unix/dir_access_unix.h88
-rw-r--r--drivers/unix/file_access_unix.cpp257
-rw-r--r--drivers/unix/file_access_unix.h81
-rw-r--r--drivers/unix/ip_unix.cpp68
-rw-r--r--drivers/unix/ip_unix.h49
-rw-r--r--drivers/unix/memory_pool_static_malloc.cpp419
-rw-r--r--drivers/unix/memory_pool_static_malloc.h82
-rw-r--r--drivers/unix/mutex_posix.cpp73
-rw-r--r--drivers/unix/mutex_posix.h61
-rw-r--r--drivers/unix/os_unix.cpp410
-rw-r--r--drivers/unix/os_unix.h121
-rw-r--r--drivers/unix/semaphore_posix.cpp89
-rw-r--r--drivers/unix/semaphore_posix.h62
-rw-r--r--drivers/unix/stream_peer_tcp_posix.cpp388
-rw-r--r--drivers/unix/stream_peer_tcp_posix.h89
-rw-r--r--drivers/unix/tcp_server_posix.cpp178
-rw-r--r--drivers/unix/tcp_server_posix.h57
-rw-r--r--drivers/unix/thread_posix.cpp99
-rw-r--r--drivers/unix/thread_posix.h75
21 files changed, 3065 insertions, 0 deletions
diff --git a/drivers/unix/SCsub b/drivers/unix/SCsub
new file mode 100644
index 0000000000..bcd231579c
--- /dev/null
+++ b/drivers/unix/SCsub
@@ -0,0 +1,7 @@
+Import('env')
+
+env.add_source_files(env.drivers_sources,"*.cpp")
+
+Export('env')
+
+
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp
new file mode 100644
index 0000000000..fff86c5a7e
--- /dev/null
+++ b/drivers/unix/dir_access_unix.cpp
@@ -0,0 +1,312 @@
+/*************************************************************************/
+/* dir_access_unix.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 "dir_access_unix.h"
+
+#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+
+#ifndef ANDROID_ENABLED
+#include <sys/statvfs.h>
+#endif
+
+#include <stdio.h>
+#include "os/memory.h"
+#include "print_string.h"
+#include <errno.h>
+
+DirAccess *DirAccessUnix::create_fs() {
+
+ return memnew( DirAccessUnix );
+}
+
+bool DirAccessUnix::list_dir_begin() {
+
+ list_dir_end(); //close any previous dir opening!
+
+
+// char real_current_dir_name[2048]; //is this enough?!
+ //getcwd(real_current_dir_name,2048);
+ //chdir(curent_path.utf8().get_data());
+ dir_stream = opendir(current_dir.utf8().get_data());
+ //chdir(real_current_dir_name);
+ if (!dir_stream)
+ return true; //error!
+
+ return false;
+}
+
+bool DirAccessUnix::file_exists(String p_file) {
+
+ GLOBAL_LOCK_FUNCTION
+
+
+ if (p_file.is_rel_path())
+ p_file=current_dir+"/"+p_file;
+ else
+ p_file=fix_path(p_file);
+
+ struct stat flags;
+ bool success = (stat(p_file.utf8().get_data(),&flags)==0);
+
+ if (success && S_ISDIR(flags.st_mode)) {
+ success=false;
+ }
+
+ return success;
+
+}
+
+uint64_t DirAccessUnix::get_modified_time(String p_file) {
+
+ if (p_file.is_rel_path())
+ p_file=current_dir+"/"+p_file;
+ else
+ p_file=fix_path(p_file);
+
+ struct stat flags;
+ bool success = (stat(p_file.utf8().get_data(),&flags)==0);
+
+ if (success) {
+ return flags.st_mtime;
+ } else {
+
+ ERR_FAIL_V(0);
+ };
+ return 0;
+};
+
+
+String DirAccessUnix::get_next() {
+
+ if (!dir_stream)
+ return "";
+ dirent *entry;
+
+ entry=readdir(dir_stream);
+
+ if (entry==NULL) {
+
+ list_dir_end();
+ return "";
+ }
+
+ //typedef struct stat Stat;
+ struct stat flags;
+
+ String fname;
+ if (fname.parse_utf8(entry->d_name))
+ fname=entry->d_name; //no utf8, maybe latin?
+
+ String f=current_dir+"/"+fname;
+
+ if (stat(f.utf8().get_data(),&flags)==0) {
+
+ if (S_ISDIR(flags.st_mode)) {
+
+ _cisdir=true;
+
+ } else {
+
+ _cisdir=false;
+ }
+
+ } else {
+
+ _cisdir=false;
+
+ }
+
+
+
+
+ return fname;
+
+}
+
+bool DirAccessUnix::current_is_dir() const {
+
+ return _cisdir;
+}
+
+
+void DirAccessUnix::list_dir_end() {
+
+ if (dir_stream)
+ closedir(dir_stream);
+ dir_stream=0;
+ _cisdir=false;
+}
+
+int DirAccessUnix::get_drive_count() {
+
+ return 0;
+}
+String DirAccessUnix::get_drive(int p_drive) {
+
+ return "";
+}
+
+Error DirAccessUnix::make_dir(String p_dir) {
+
+ GLOBAL_LOCK_FUNCTION
+
+ p_dir=fix_path(p_dir);
+
+ char real_current_dir_name[2048];
+ getcwd(real_current_dir_name,2048);
+ chdir(current_dir.utf8().get_data()); //ascii since this may be unicode or wathever the host os wants
+
+ bool success=(mkdir(p_dir.utf8().get_data(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)==0);
+ int err = errno;
+
+ chdir(real_current_dir_name);
+
+ if (success) {
+ return OK;
+ };
+
+ if (err == EEXIST) {
+ return ERR_ALREADY_EXISTS;
+ };
+
+ return ERR_CANT_CREATE;
+}
+
+
+Error DirAccessUnix::change_dir(String p_dir) {
+
+ GLOBAL_LOCK_FUNCTION
+ p_dir=fix_path(p_dir);
+
+
+ char real_current_dir_name[2048];
+ getcwd(real_current_dir_name,2048);
+ String prev_dir;
+ if (prev_dir.parse_utf8(real_current_dir_name))
+ prev_dir=real_current_dir_name; //no utf8, maybe latin?
+
+ chdir(current_dir.utf8().get_data()); //ascii since this may be unicode or wathever the host os wants
+ bool worked=(chdir(p_dir.utf8().get_data())==0); // we can only give this utf8
+#ifndef IPHONE_ENABLED
+ String base = _get_root_path();
+ if (base!="") {
+
+ getcwd(real_current_dir_name,2048);
+ String new_dir;
+ new_dir.parse_utf8(real_current_dir_name);
+ if (!new_dir.begins_with(base))
+ worked=false;
+ }
+#endif
+ if (worked) {
+
+ getcwd(real_current_dir_name,2048);
+ if (current_dir.parse_utf8(real_current_dir_name))
+ current_dir=real_current_dir_name; //no utf8, maybe latin?
+ }
+
+ chdir(prev_dir.utf8().get_data());
+ return worked?OK:ERR_INVALID_PARAMETER;
+
+}
+
+String DirAccessUnix::get_current_dir() {
+
+ String base = _get_root_path();
+ if (base!="") {
+
+ String bd = current_dir.replace_first(base,"");
+ if (bd.begins_with("/"))
+ return _get_root_string()+bd.substr(1,bd.length());
+ else
+ return _get_root_string()+bd;
+
+ }
+ return current_dir;
+}
+
+Error DirAccessUnix::rename(String p_path,String p_new_path) {
+
+ p_path=fix_path(p_path);
+ p_new_path=fix_path(p_new_path);
+
+ return ::rename(p_path.utf8().get_data(),p_new_path.utf8().get_data())==0?OK:FAILED;
+}
+Error DirAccessUnix::remove(String p_path) {
+
+ p_path=fix_path(p_path);
+
+ struct stat flags;
+ if ((stat(p_path.utf8().get_data(),&flags)!=0))
+ return FAILED;
+
+ if (S_ISDIR(flags.st_mode))
+ return ::rmdir(p_path.utf8().get_data())==0?OK:FAILED;
+ else
+ return ::unlink(p_path.utf8().get_data())==0?OK:FAILED;
+}
+
+
+size_t DirAccessUnix::get_space_left() {
+
+#ifndef NO_STATVFS
+ struct statvfs vfs;
+ if (statvfs(current_dir.utf8().get_data(), &vfs) != 0) {
+
+ return -1;
+ };
+
+ return vfs.f_bfree * vfs.f_bsize;
+#else
+#warning THIS IS BROKEN
+ return 0;
+#endif
+};
+
+
+
+DirAccessUnix::DirAccessUnix() {
+
+ dir_stream=0;
+ current_dir=".";
+ _cisdir=false;
+
+ /* determine drive count */
+
+ change_dir(current_dir);
+
+}
+
+
+DirAccessUnix::~DirAccessUnix() {
+
+ list_dir_end();
+}
+
+
+#endif //posix_enabled
diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h
new file mode 100644
index 0000000000..7ede4fc31c
--- /dev/null
+++ b/drivers/unix/dir_access_unix.h
@@ -0,0 +1,88 @@
+/*************************************************************************/
+/* dir_access_unix.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 DIR_ACCESS_UNIX_H
+#define DIR_ACCESS_UNIX_H
+
+#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+
+#include "os/dir_access.h"
+
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class DirAccessUnix : public DirAccess {
+
+ DIR *dir_stream;
+
+ static DirAccess *create_fs();
+
+ String current_dir;
+ bool _cisdir;
+
+public:
+
+ virtual bool list_dir_begin(); ///< This starts dir listing
+ virtual String get_next();
+ virtual bool current_is_dir() const;
+
+ virtual void list_dir_end(); ///<
+
+ virtual int get_drive_count();
+ virtual String get_drive(int p_drive);
+
+ virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
+ virtual String get_current_dir(); ///< return current dir location
+ virtual Error make_dir(String p_dir);
+
+ virtual bool file_exists(String p_file);
+ virtual uint64_t get_modified_time(String p_file);
+
+
+
+ virtual Error rename(String p_from, String p_to);
+ virtual Error remove(String p_name);
+
+ virtual size_t get_space_left();
+
+
+ DirAccessUnix();
+ ~DirAccessUnix();
+
+};
+
+
+
+#endif //UNIX ENABLED
+#endif
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
new file mode 100644
index 0000000000..239e41be4c
--- /dev/null
+++ b/drivers/unix/file_access_unix.cpp
@@ -0,0 +1,257 @@
+/*************************************************************************/
+/* file_access_unix.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 "file_access_unix.h"
+
+#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "print_string.h"
+#include "core/os/os.h"
+
+#ifndef ANDROID_ENABLED
+#include <sys/statvfs.h>
+#endif
+
+#ifdef MSVC
+ #define S_ISREG(m) ((m)&_S_IFREG)
+#endif
+#ifndef S_ISREG
+ #define S_ISREG(m) ((m) & S_IFREG)
+#endif
+
+void FileAccessUnix::check_errors() const {
+
+ ERR_FAIL_COND(!f);
+
+ if (feof(f)) {
+
+ last_error=ERR_FILE_EOF;
+ }
+
+}
+
+Error FileAccessUnix::_open(const String& p_path, int p_mode_flags) {
+
+ if (f)
+ fclose(f);
+ f=NULL;
+
+ String path=fix_path(p_path);
+ //printf("opening %ls\n", path.c_str());
+
+ ERR_FAIL_COND_V(f,ERR_ALREADY_IN_USE);
+ const char* mode_string;
+
+ if (p_mode_flags==READ)
+ mode_string="rb";
+ else if (p_mode_flags==WRITE)
+ mode_string="wb";
+ else if (p_mode_flags==READ_WRITE)
+ mode_string="wb+";
+ else
+ return ERR_INVALID_PARAMETER;
+
+ /* pretty much every implementation that uses fopen as primary
+ backend (unix-compatible mostly) supports utf8 encoding */
+
+ //printf("opening %s as %s\n", p_path.utf8().get_data(), path.utf8().get_data());
+ struct stat st;
+ if (stat(path.utf8().get_data(),&st) == 0) {
+
+ if (!S_ISREG(st.st_mode))
+ return ERR_FILE_CANT_OPEN;
+
+ };
+
+ if (is_backup_save_enabled() && p_mode_flags&WRITE && !(p_mode_flags&READ)) {
+ save_path=path;
+ path=path+".tmp";
+ //print_line("saving instead to "+path);
+ }
+
+ f=fopen(path.utf8().get_data(),mode_string);
+
+ if (f==NULL) {
+ last_error=ERR_FILE_CANT_OPEN;
+ return ERR_FILE_CANT_OPEN;
+ } else {
+ last_error=OK;
+ flags=p_mode_flags;
+ return OK;
+ }
+
+}
+void FileAccessUnix::close() {
+
+ if (!f)
+ return;
+ fclose(f);
+ f = NULL;
+ if (save_path!="") {
+
+ //unlink(save_path.utf8().get_data());
+ //print_line("renaming..");
+ int rename_error = rename((save_path+".tmp").utf8().get_data(),save_path.utf8().get_data());
+ save_path="";
+ ERR_FAIL_COND( rename_error != 0);
+ }
+
+
+}
+bool FileAccessUnix::is_open() const{
+
+ return (f!=NULL);
+}
+void FileAccessUnix::seek(size_t p_position) {
+
+ ERR_FAIL_COND(!f);
+
+ last_error=OK;
+ if ( fseek(f,p_position,SEEK_SET) )
+ check_errors();
+}
+void FileAccessUnix::seek_end(int64_t p_position) {
+
+ ERR_FAIL_COND(!f);
+ if ( fseek(f,p_position,SEEK_END) )
+ check_errors();
+}
+size_t FileAccessUnix::get_pos() const{
+
+
+ size_t aux_position=0;
+ if ( !(aux_position = ftell(f)) ) {
+ check_errors();
+ };
+ return aux_position;
+}
+size_t FileAccessUnix::get_len() const{
+
+
+ ERR_FAIL_COND_V(!f,0);
+
+ FileAccessUnix *fau = const_cast<FileAccessUnix*>(this);
+ int pos = fau->get_pos();
+ fau->seek_end();
+ int size = fau->get_pos();
+ fau->seek(pos);
+
+ return size;
+}
+
+bool FileAccessUnix::eof_reached() const{
+
+ return last_error==ERR_FILE_EOF;
+}
+
+uint8_t FileAccessUnix::get_8() const{
+
+ ERR_FAIL_COND_V(!f,0);
+ uint8_t b;
+ if (fread(&b,1,1,f) == 0) {
+ check_errors();
+ };
+
+ return b;
+}
+
+int FileAccessUnix::get_buffer(uint8_t *p_dst, int p_length) const {
+
+ ERR_FAIL_COND_V(!f,-1);
+ int read = fread(p_dst, 1, p_length, f);
+ check_errors();
+ return read;
+};
+
+Error FileAccessUnix::get_error() const{
+
+ return last_error;
+}
+
+void FileAccessUnix::store_8(uint8_t p_dest) {
+
+ ERR_FAIL_COND(!f);
+ fwrite(&p_dest,1,1,f);
+
+}
+
+
+bool FileAccessUnix::file_exists(const String &p_path) {
+
+ FILE *g;
+ //printf("opening file %s\n", p_fname.c_str());
+ String filename=fix_path(p_path);
+ g=fopen(filename.utf8().get_data(),"rb");
+ if (g==NULL) {
+
+ return false;
+ } else {
+
+ fclose(g);
+ return true;
+ }
+}
+
+uint64_t FileAccessUnix::_get_modified_time(const String &p_file) {
+
+ String file=fix_path(p_file);
+ struct stat flags;
+ bool success = (stat(file.utf8().get_data(),&flags)==0);
+
+ if (success) {
+ return flags.st_mtime;
+ } else {
+ print_line("ERROR IN: "+p_file);
+
+ ERR_FAIL_V(0);
+ };
+
+}
+
+FileAccess * FileAccessUnix::create_libc() {
+
+ return memnew( FileAccessUnix );
+}
+
+
+FileAccessUnix::FileAccessUnix() {
+
+ f=NULL;
+ flags=0;
+ last_error=OK;
+
+}
+FileAccessUnix::~FileAccessUnix() {
+
+ close();
+
+}
+
+#endif
diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h
new file mode 100644
index 0000000000..0dedfce6ac
--- /dev/null
+++ b/drivers/unix/file_access_unix.h
@@ -0,0 +1,81 @@
+/*************************************************************************/
+/* file_access_unix.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 FILE_ACCESS_UNIX_H
+#define FILE_ACCESS_UNIX_H
+
+#include "os/file_access.h"
+#include "os/memory.h"
+#include <stdio.h>
+
+#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class FileAccessUnix : public FileAccess {
+
+ FILE *f;
+ int flags;
+ void check_errors() const;
+ mutable Error last_error;
+ String save_path;
+
+ static FileAccess* create_libc();
+public:
+
+ virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
+ virtual void close(); ///< close a file
+ virtual bool is_open() const; ///< true when file is open
+
+ virtual void seek(size_t p_position); ///< seek to a given position
+ virtual void seek_end(int64_t p_position=0); ///< seek from the end of file
+ virtual size_t get_pos() const; ///< get position in the file
+ virtual size_t get_len() const; ///< get size of the file
+
+ virtual bool eof_reached() const; ///< reading passed EOF
+
+ virtual uint8_t get_8() const; ///< get a byte
+ virtual int get_buffer(uint8_t *p_dst, int p_length) const;
+
+ virtual Error get_error() const; ///< get last error
+
+ virtual void store_8(uint8_t p_dest); ///< store a byte
+
+ virtual bool file_exists(const String& p_path); ///< return true if a file exists
+
+ virtual uint64_t _get_modified_time(const String& p_file);
+
+ FileAccessUnix();
+ virtual ~FileAccessUnix();
+
+};
+
+
+#endif
+#endif
diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp
new file mode 100644
index 0000000000..c11426d356
--- /dev/null
+++ b/drivers/unix/ip_unix.cpp
@@ -0,0 +1,68 @@
+/*************************************************************************/
+/* ip_unix.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 "ip_unix.h"
+
+#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED)
+
+#ifdef WINDOWS_ENABLED
+#include <ws2tcpip.h>
+#include <winsock2.h>
+#include <windows.h>
+#else
+#include <netdb.h>
+#endif
+IP_Address IP_Unix::_resolve_hostname(const String& p_hostname) {
+
+ struct hostent *he;
+ if ((he=gethostbyname(p_hostname.utf8().get_data())) == NULL) { // get the host info
+ ERR_PRINT("gethostbyname failed!");
+ return IP_Address();
+ }
+ IP_Address ip;
+
+ ip.host= *((unsigned long*)he->h_addr);
+
+ return ip;
+
+}
+
+void IP_Unix::make_default() {
+
+ _create=_create_unix;
+}
+
+IP* IP_Unix::_create_unix() {
+
+ return memnew( IP_Unix );
+}
+
+IP_Unix::IP_Unix() {
+}
+
+#endif
diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h
new file mode 100644
index 0000000000..ec2d42c837
--- /dev/null
+++ b/drivers/unix/ip_unix.h
@@ -0,0 +1,49 @@
+/*************************************************************************/
+/* ip_unix.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 IP_UNIX_H
+#define IP_UNIX_H
+
+#include "io/ip.h"
+
+#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED)
+
+class IP_Unix : public IP {
+ OBJ_TYPE(IP_Unix, IP);
+
+ virtual IP_Address _resolve_hostname(const String& p_hostname);
+
+ static IP* _create_unix();
+public:
+
+ static void make_default();
+ IP_Unix();
+};
+
+#endif
+#endif // IP_UNIX_H
diff --git a/drivers/unix/memory_pool_static_malloc.cpp b/drivers/unix/memory_pool_static_malloc.cpp
new file mode 100644
index 0000000000..fa1266b2df
--- /dev/null
+++ b/drivers/unix/memory_pool_static_malloc.cpp
@@ -0,0 +1,419 @@
+/*************************************************************************/
+/* memory_pool_static_malloc.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 "memory_pool_static_malloc.h"
+#include "error_macros.h"
+#include "os/memory.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include "os/copymem.h"
+#include "os/os.h"
+
+/**
+ * NOTE NOTE NOTE NOTE
+ * in debug mode, this prepends the memory size to the allocated block
+ * so BE CAREFUL!
+ */
+
+
+void* MemoryPoolStaticMalloc::alloc(size_t p_bytes,const char *p_description) {
+
+ #if DFAULT_ALIGNMENT == 1
+
+ return _alloc(p_bytes, p_description);
+
+ #else
+
+ int total = p_bytes + DEFAULT_ALIGNMENT;
+ uint8_t* ptr = (uint8_t*)_alloc(total, p_description);
+ ERR_FAIL_COND_V( !ptr, ptr );
+ int ofs = (DEFAULT_ALIGNMENT - ((uintptr_t)ptr & (DEFAULT_ALIGNMENT - 1)));
+ ptr[ofs-1] = ofs;
+ return (void*)(ptr + ofs);
+ #endif
+};
+
+void* MemoryPoolStaticMalloc::_alloc(size_t p_bytes,const char *p_description) {
+
+ ERR_FAIL_COND_V(p_bytes==0,0);
+
+ MutexLock lock(mutex);
+
+#ifdef DEBUG_MEMORY_ENABLED
+ void *mem=malloc(p_bytes+sizeof(RingPtr)); /// add for size and ringlist
+
+ if (!mem) {
+ printf("**ERROR: out of memory while allocating %i bytes by %s?\n",(int) p_bytes, p_description);
+ printf("**ERROR: memory usage is %i\n", (int)get_total_usage());
+ };
+
+ ERR_FAIL_COND_V(!mem,0); //out of memory, or unreasonable request
+
+ /* setup the ringlist element */
+
+ RingPtr *ringptr = (RingPtr*)mem;
+
+ /* setup the ringlist element data (description and size ) */
+
+ ringptr->size = p_bytes;
+ ringptr->descr=p_description;
+
+ if (ringlist) { /* existing ringlist */
+
+ /* assign next */
+ ringptr->next = ringlist->next;
+ ringlist->next = ringptr;
+ /* assign prev */
+ ringptr->prev = ringlist;
+ ringptr->next->prev = ringptr;
+ } else { /* non existing ringlist */
+
+ ringptr->next=ringptr;
+ ringptr->prev=ringptr;
+ ringlist=ringptr;
+
+ }
+
+ total_mem+=p_bytes;
+
+ /* update statistics */
+ if (total_mem > max_mem )
+ max_mem = total_mem;
+
+ total_pointers++;
+
+ if (total_pointers > max_pointers)
+ max_pointers=total_pointers;
+
+ return ringptr + 1; /* return memory after ringptr */
+
+#else
+ void *mem=malloc(p_bytes);
+
+ ERR_FAIL_COND_V(!mem,0); //out of memory, or unreasonable request
+ return mem;
+#endif
+}
+
+
+void* MemoryPoolStaticMalloc::realloc(void *p_memory,size_t p_bytes) {
+
+ #if DFAULT_ALIGNMENT == 1
+
+ return _realloc(p_memory,p_bytes);
+ #else
+ if (!p_memory)
+ return alloc(p_bytes);
+
+ int total = p_bytes + DEFAULT_ALIGNMENT;
+ uint8_t* mem = (uint8_t*)p_memory;
+ int ofs = *(mem-1);
+ mem = mem - ofs;
+ uint8_t* ptr = (uint8_t*)_realloc(mem, total);
+ ERR_FAIL_COND_V(ptr == NULL, NULL);
+ int new_ofs = (DEFAULT_ALIGNMENT - ((uintptr_t)ptr & (DEFAULT_ALIGNMENT - 1)));
+ if (new_ofs != ofs) {
+
+ //printf("realloc moving %i bytes\n", p_bytes);
+ movemem((ptr + new_ofs), (ptr + ofs), p_bytes);
+ ptr[new_ofs-1] = new_ofs;
+ };
+ return ptr + new_ofs;
+ #endif
+};
+
+void* MemoryPoolStaticMalloc::_realloc(void *p_memory,size_t p_bytes) {
+
+ if (p_memory==NULL) {
+
+ return alloc( p_bytes );
+ }
+
+ if (p_bytes<=0) {
+
+ this->free(p_memory);
+ ERR_FAIL_COND_V( p_bytes < 0 , NULL );
+ return NULL;
+ }
+
+ MutexLock lock(mutex);
+
+#ifdef DEBUG_MEMORY_ENABLED
+
+
+ RingPtr *ringptr = (RingPtr*)p_memory;
+ ringptr--; /* go back an element to find the tingptr */
+
+ bool single_element = (ringptr->next == ringptr) && (ringptr->prev == ringptr);
+ bool is_list = ( ringlist == ringptr );
+
+
+ RingPtr *new_ringptr=(RingPtr*)::realloc(ringptr, p_bytes+sizeof(RingPtr));
+
+ ERR_FAIL_COND_V( new_ringptr == 0, NULL ); /// reallocation failed
+
+ /* actualize mem used */
+ total_mem -= new_ringptr->size;
+ new_ringptr->size = p_bytes;
+ total_mem += new_ringptr->size;
+
+ if (total_mem > max_mem ) //update statistics
+ max_mem = total_mem;
+
+ if (new_ringptr == ringptr )
+ return ringptr + 1; // block didn't move, don't do anything
+
+ if (single_element) {
+
+ new_ringptr->next=new_ringptr;
+ new_ringptr->prev=new_ringptr;
+ } else {
+
+ new_ringptr->next->prev=new_ringptr;
+ new_ringptr->prev->next=new_ringptr;
+ }
+
+ if (is_list)
+ ringlist=new_ringptr;
+
+
+ return new_ringptr + 1;
+
+#else
+ return ::realloc( p_memory, p_bytes );
+#endif
+}
+
+void MemoryPoolStaticMalloc::free(void *p_ptr) {
+
+ ERR_FAIL_COND( !MemoryPoolStatic::get_singleton());
+
+ #if DFAULT_ALIGNMENT == 1
+
+ _free(p_ptr);
+ #else
+
+ uint8_t* mem = (uint8_t*)p_ptr;
+ int ofs = *(mem-1);
+ mem = mem - ofs;
+
+ _free(mem);
+ #endif
+};
+
+
+void MemoryPoolStaticMalloc::_free(void *p_ptr) {
+
+ MutexLock lock(mutex);
+
+#ifdef DEBUG_MEMORY_ENABLED
+
+ if (p_ptr==0) {
+ printf("**ERROR: STATIC ALLOC: Attempted free of NULL pointer.\n");
+ return;
+ };
+
+ RingPtr *ringptr = (RingPtr*)p_ptr;
+
+ ringptr--; /* go back an element to find the ringptr */
+
+
+#if 0
+ { // check for existing memory on free.
+ RingPtr *p = ringlist;
+
+ bool found=false;
+
+ if (ringlist) {
+ do {
+ if (p==ringptr) {
+ found=true;
+ break;
+ }
+
+ p=p->next;
+ } while (p!=ringlist);
+ }
+
+ if (!found) {
+ printf("**ERROR: STATIC ALLOC: Attempted free of unknown pointer at %p\n",(ringptr+1));
+ return;
+ }
+
+ }
+#endif
+ /* proceed to erase */
+
+ bool single_element = (ringptr->next == ringptr) && (ringptr->prev == ringptr);
+ bool is_list = ( ringlist == ringptr );
+
+ if (single_element) {
+ /* just get rid of it */
+ ringlist=0;
+
+ } else {
+ /* auto-remove from ringlist */
+ if (is_list)
+ ringlist=ringptr->next;
+
+ ringptr->prev->next = ringptr->next;
+ ringptr->next->prev = ringptr->prev;
+ }
+
+ total_mem -= ringptr->size;
+ total_pointers--;
+ // catch more errors
+ zeromem(ringptr,sizeof(RingPtr)+ringptr->size);
+ ::free(ringptr); //just free that pointer
+
+#else
+ ERR_FAIL_COND(p_ptr==0);
+
+ ::free(p_ptr);
+#endif
+}
+
+
+size_t MemoryPoolStaticMalloc::get_available_mem() const {
+
+ return 0xffffffff;
+}
+
+size_t MemoryPoolStaticMalloc::get_total_usage() {
+
+#ifdef DEBUG_MEMORY_ENABLED
+
+ return total_mem;
+#else
+ return 0;
+#endif
+
+}
+
+size_t MemoryPoolStaticMalloc::get_max_usage() {
+
+ return max_mem;
+}
+
+/* Most likely available only if memory debugger was compiled in */
+int MemoryPoolStaticMalloc::get_alloc_count() {
+
+ return 0;
+}
+void * MemoryPoolStaticMalloc::get_alloc_ptr(int p_alloc_idx) {
+
+ return 0;
+}
+const char* MemoryPoolStaticMalloc::get_alloc_description(int p_alloc_idx) {
+
+
+ return "";
+}
+size_t MemoryPoolStaticMalloc::get_alloc_size(int p_alloc_idx) {
+
+ return 0;
+}
+
+void MemoryPoolStaticMalloc::dump_mem_to_file(const char* p_file) {
+
+#ifdef DEBUG_MEMORY_ENABLED
+
+ ERR_FAIL_COND( !ringlist ); /** WTF BUG !? */
+ RingPtr *p = ringlist;
+ FILE *f = fopen(p_file,"wb");
+
+ do {
+ fprintf(f,"%p-%i-%s\n", p+1, (int)p->size, (p->descr?p->descr:"") );
+ p=p->next;
+ } while (p!=ringlist);
+
+ fclose(f);
+#endif
+
+}
+
+MemoryPoolStaticMalloc::MemoryPoolStaticMalloc() {
+
+#ifdef DEBUG_MEMORY_ENABLED
+ total_mem=0;
+ total_pointers=0;
+ ringlist=0;
+ max_mem=0;
+ max_pointers=0;
+
+
+#endif
+
+ mutex=NULL;
+#ifndef NO_THREADS
+
+ mutex=Mutex::create(); // at this point, this should work
+#endif
+
+}
+
+
+MemoryPoolStaticMalloc::~MemoryPoolStaticMalloc() {
+
+ Mutex *old_mutex=mutex;
+ mutex=NULL;
+ if (old_mutex)
+ memdelete(old_mutex);
+
+#ifdef DEBUG_MEMORY_ENABLED
+
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ if (total_mem > 0 ) {
+ printf("**ERROR: STATIC ALLOC: ** MEMORY LEAKS DETECTED **\n");
+ printf("**ERROR: STATIC ALLOC: %i bytes of memory in use at exit.\n",(int)total_mem);
+
+ if (1){
+ printf("**ERROR: STATIC ALLOC: Following is the list of leaked allocations: \n");
+
+ ERR_FAIL_COND( !ringlist ); /** WTF BUG !? */
+ RingPtr *p = ringlist;
+
+ do {
+ printf("\t%p - %i bytes - %s\n", (RingPtr*)(p+1), (int)p->size, (p->descr?p->descr:"") );
+ p=p->next;
+ } while (p!=ringlist);
+
+ printf("**ERROR: STATIC ALLOC: End of Report.\n");
+ };
+
+ printf("mem - max %i, pointers %i, leaks %i.\n",(int)max_mem,max_pointers,(int)total_mem);
+ } else {
+
+ printf("INFO: mem - max %i, pointers %i, no leaks.\n",(int)max_mem,max_pointers);
+ }
+ }
+
+#endif
+}
+
+
diff --git a/drivers/unix/memory_pool_static_malloc.h b/drivers/unix/memory_pool_static_malloc.h
new file mode 100644
index 0000000000..626fec826e
--- /dev/null
+++ b/drivers/unix/memory_pool_static_malloc.h
@@ -0,0 +1,82 @@
+/*************************************************************************/
+/* memory_pool_static_malloc.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 MEMORY_POOL_STATIC_MALLOC_H
+#define MEMORY_POOL_STATIC_MALLOC_H
+
+#include "os/memory_pool_static.h"
+#include "os/mutex.h"
+/**
+ @author Juan Linietsky <red@lunatea>
+*/
+class MemoryPoolStaticMalloc : public MemoryPoolStatic {
+
+ struct RingPtr {
+
+ size_t size;
+ const char *descr; /* description of memory */
+ RingPtr *next;
+ RingPtr *prev;
+ };
+
+ RingPtr *ringlist;
+ size_t total_mem;
+ int total_pointers;
+
+ size_t max_mem;
+ int max_pointers;
+
+ Mutex *mutex;
+
+ void* _alloc(size_t p_bytes,const char *p_description=""); ///< Pointer in p_description shold be to a const char const like "hello"
+ void* _realloc(void *p_memory,size_t p_bytes); ///< Pointer in
+ void _free(void *p_ptr); ///< Pointer in p_description shold be to a const char const
+
+public:
+
+ virtual void* alloc(size_t p_bytes,const char *p_description=""); ///< Pointer in p_description shold be to a const char const like "hello"
+ virtual void free(void *p_ptr); ///< Pointer in p_description shold be to a const char const
+ virtual void* realloc(void *p_memory,size_t p_bytes); ///< Pointer in
+ virtual size_t get_available_mem() const;
+ virtual size_t get_total_usage();
+ virtual size_t get_max_usage();
+
+ /* Most likely available only if memory debugger was compiled in */
+ virtual int get_alloc_count();
+ virtual void * get_alloc_ptr(int p_alloc_idx);
+ virtual const char* get_alloc_description(int p_alloc_idx);
+ virtual size_t get_alloc_size(int p_alloc_idx);
+
+ void dump_mem_to_file(const char* p_file);
+
+ MemoryPoolStaticMalloc();
+ ~MemoryPoolStaticMalloc();
+
+};
+
+#endif
diff --git a/drivers/unix/mutex_posix.cpp b/drivers/unix/mutex_posix.cpp
new file mode 100644
index 0000000000..166dfa4b19
--- /dev/null
+++ b/drivers/unix/mutex_posix.cpp
@@ -0,0 +1,73 @@
+/*************************************************************************/
+/* mutex_posix.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 "mutex_posix.h"
+#include "os/memory.h"
+
+#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
+
+void MutexPosix::lock() {
+
+ pthread_mutex_lock(&mutex);
+
+}
+void MutexPosix::unlock() {
+
+ pthread_mutex_unlock(&mutex);
+}
+Error MutexPosix::try_lock() {
+
+ return (pthread_mutex_trylock(&mutex)==0)?OK:ERR_BUSY;
+}
+
+Mutex *MutexPosix::create_func_posix(bool p_recursive) {
+
+ return memnew( MutexPosix(p_recursive) );
+}
+
+void MutexPosix::make_default() {
+
+ create_func=create_func_posix;
+}
+
+MutexPosix::MutexPosix(bool p_recursive) {
+
+ pthread_mutexattr_init(&attr);
+ if (p_recursive)
+ pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&mutex,&attr);
+}
+
+
+MutexPosix::~MutexPosix() {
+
+ pthread_mutex_destroy(&mutex);
+}
+
+
+#endif
diff --git a/drivers/unix/mutex_posix.h b/drivers/unix/mutex_posix.h
new file mode 100644
index 0000000000..3496473688
--- /dev/null
+++ b/drivers/unix/mutex_posix.h
@@ -0,0 +1,61 @@
+/*************************************************************************/
+/* mutex_posix.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 MUTEX_POSIX_H
+#define MUTEX_POSIX_H
+
+#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
+
+#include <pthread.h>
+#include "os/mutex.h"
+
+class MutexPosix : public Mutex {
+
+ pthread_mutexattr_t attr;
+ pthread_mutex_t mutex;
+
+ static Mutex *create_func_posix(bool p_recursive);
+
+public:
+
+ virtual void lock();
+ virtual void unlock();
+ virtual Error try_lock();
+
+
+ static void make_default();
+
+ MutexPosix(bool p_recursive);
+
+ ~MutexPosix();
+
+};
+
+#endif
+
+#endif
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
new file mode 100644
index 0000000000..f684c63b3b
--- /dev/null
+++ b/drivers/unix/os_unix.cpp
@@ -0,0 +1,410 @@
+/*************************************************************************/
+/* os_unix.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 "os_unix.h"
+
+#ifdef UNIX_ENABLED
+
+#include "memory_pool_static_malloc.h"
+#include "os/memory_pool_dynamic_static.h"
+#include "thread_posix.h"
+#include "semaphore_posix.h"
+#include "mutex_posix.h"
+#include "core/os/thread_dummy.h"
+
+//#include "core/io/file_access_buffered_fa.h"
+#include "file_access_unix.h"
+#include "dir_access_unix.h"
+#include "tcp_server_posix.h"
+#include "stream_peer_tcp_posix.h"
+
+
+#include <stdarg.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <poll.h>
+#include <errno.h>
+#include <assert.h>
+#include "globals.h"
+void OS_Unix::print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type) {
+
+ if (p_rationale && p_rationale[0]) {
+
+ print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_rationale);
+ print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
+
+ } else {
+ print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_code);
+ print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
+
+ }
+}
+
+
+void OS_Unix::debug_break() {
+
+ assert(false);
+};
+
+int OS_Unix::get_audio_driver_count() const {
+
+ return 1;
+
+}
+const char * OS_Unix::get_audio_driver_name(int p_driver) const {
+
+ return "dummy";
+}
+
+int OS_Unix::unix_initialize_audio(int p_audio_driver) {
+
+ return 0;
+}
+
+static MemoryPoolStaticMalloc *mempool_static=NULL;
+static MemoryPoolDynamicStatic *mempool_dynamic=NULL;
+
+
+void OS_Unix::initialize_core() {
+
+#ifdef NO_PTHREADS
+ ThreadDummy::make_default();
+ SemaphoreDummy::make_default();
+ MutexDummy::make_default();
+#else
+ ThreadPosix::make_default();
+ SemaphorePosix::make_default();
+ MutexPosix::make_default();
+#endif
+ FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES);
+ FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
+ FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM);
+ //FileAccessBufferedFA<FileAccessUnix>::make_default();
+ DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_RESOURCES);
+ DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_USERDATA);
+ DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM);
+
+#ifndef NO_NETWORK
+ TCPServerPosix::make_default();
+ StreamPeerTCPPosix::make_default();
+ IP_Unix::make_default();
+#endif
+ mempool_static = new MemoryPoolStaticMalloc;
+ mempool_dynamic = memnew( MemoryPoolDynamicStatic );
+
+ ticks_start=0;
+ ticks_start=get_ticks_usec();
+}
+
+void OS_Unix::finalize_core() {
+
+
+ if (mempool_dynamic)
+ memdelete( mempool_dynamic );
+ if (mempool_static)
+ delete mempool_static;
+
+}
+
+
+void OS_Unix::vprint(const char* p_format, va_list p_list,bool p_stder) {
+
+ if (p_stder) {
+
+ vfprintf(stderr,p_format,p_list);
+ fflush(stderr);
+ } else {
+
+ vprintf(p_format,p_list);
+ fflush(stdout);
+ }
+}
+
+void OS_Unix::print(const char *p_format, ... ) {
+
+ va_list argp;
+ va_start(argp, p_format);
+ vprintf(p_format, argp );
+ va_end(argp);
+
+}
+void OS_Unix::alert(const String& p_alert,const String& p_title) {
+
+ fprintf(stderr,"ERROR: %s\n",p_alert.utf8().get_data());
+}
+
+static int has_data(FILE* p_fd, int timeout_usec = 0) {
+
+ fd_set readset;
+ int fd = fileno(p_fd);
+ FD_ZERO(&readset);
+ FD_SET(fd, &readset);
+ timeval time;
+ time.tv_sec = 0;
+ time.tv_usec = timeout_usec;
+ int res = 0;//select(fd + 1, &readset, NULL, NULL, &time);
+ return res > 0;
+};
+
+
+String OS_Unix::get_stdin_string(bool p_block) {
+
+ String ret;
+ if (p_block) {
+ char buff[1024];
+ ret = stdin_buf + fgets(buff,1024,stdin);
+ stdin_buf = "";
+ return ret;
+ };
+
+ while (has_data(stdin)) {
+
+ char ch;
+ read(fileno(stdin), &ch, 1);
+ if (ch == '\n') {
+ ret = stdin_buf;
+ stdin_buf = "";
+ return ret;
+ } else {
+ char str[2] = { ch, 0 };
+ stdin_buf += str;
+ };
+ };
+
+ return "";
+}
+
+String OS_Unix::get_name() {
+
+ return "Unix";
+}
+
+
+uint64_t OS_Unix::get_unix_time() const {
+
+ return time(NULL);
+};
+
+
+OS::Date OS_Unix::get_date() const {
+
+ time_t t=time(NULL);
+ struct tm *lt=localtime(&t);
+ Date ret;
+ ret.year=1900+lt->tm_year;
+ ret.month=(Month)lt->tm_mon;
+ ret.day=lt->tm_mday;
+ ret.weekday=(Weekday)lt->tm_wday;
+ ret.dst=lt->tm_isdst;
+
+ return ret;
+}
+OS::Time OS_Unix::get_time() const {
+
+ time_t t=time(NULL);
+ struct tm *lt=localtime(&t);
+ Time ret;
+ ret.hour=lt->tm_hour;
+ ret.min=lt->tm_min;
+ ret.sec=lt->tm_sec;
+ return ret;
+}
+
+void OS_Unix::delay_usec(uint32_t p_usec) const {
+
+ usleep(p_usec);
+}
+uint64_t OS_Unix::get_ticks_usec() const {
+
+ struct timeval tv_now;
+ gettimeofday(&tv_now,NULL);
+
+ uint64_t longtime = (uint64_t)tv_now.tv_usec + (uint64_t)tv_now.tv_sec*1000000L;
+ longtime-=ticks_start;
+
+ return longtime;
+}
+
+Error OS_Unix::execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id,String* r_pipe,int *r_exitcode) {
+
+
+ if (p_blocking && r_pipe) {
+
+
+ String argss;
+ argss="\""+p_path+"\"";
+
+ for(int i=0;i<p_arguments.size();i++) {
+
+ argss+=String(" \"")+p_arguments[i]+"\"";
+ }
+
+ argss+=" 2>/dev/null"; //silence stderr
+ FILE* f=popen(argss.utf8().get_data(),"r");
+
+ ERR_FAIL_COND_V(!f,ERR_CANT_OPEN);
+
+ char buf[65535];
+ while(fgets(buf,65535,f)) {
+
+ (*r_pipe)+=buf;
+ }
+
+ int rv = pclose(f);
+ if (r_exitcode)
+ *r_exitcode=rv;
+
+ return OK;
+ }
+
+
+ pid_t pid = fork();
+ ERR_FAIL_COND_V(pid<0,ERR_CANT_FORK);
+ //print("execute: %s\n",p_path.utf8().get_data());
+
+
+ if (pid==0) {
+ // is child
+ Vector<CharString> cs;
+ cs.push_back(p_path.utf8());
+ for(int i=0;i<p_arguments.size();i++)
+ cs.push_back(p_arguments[i].utf8());
+
+ Vector<char*> args;
+ for(int i=0;i<cs.size();i++)
+ args.push_back((char*)cs[i].get_data());// shitty C cast
+ args.push_back(0);
+
+ execv(p_path.utf8().get_data(),&args[0]);
+ // still alive? something failed..
+ fprintf(stderr,"**ERROR** OS_Unix::execute - Could not create child process while executing: %s\n",p_path.utf8().get_data());
+ abort();
+ }
+
+ if (p_blocking) {
+
+ int status;
+ pid_t rpid = waitpid(pid,&status,0);
+ if (r_exitcode)
+ *r_exitcode=WEXITSTATUS(status);
+
+ print("returned: %i, waiting for: %i\n",rpid,pid);
+ } else {
+
+ if (r_child_id)
+ *r_child_id=pid;
+ }
+
+ return OK;
+
+}
+
+Error OS_Unix::kill(const ProcessID& p_pid) {
+
+ int ret = ::kill(p_pid,SIGKILL);
+ return ret?ERR_INVALID_PARAMETER:OK;
+}
+
+bool OS_Unix::has_environment(const String& p_var) const {
+
+ return getenv(p_var.utf8().get_data())!=NULL;
+}
+
+String OS_Unix::get_locale() const {
+
+ if (!has_environment("LANG"))
+ return "en";
+
+ String locale = get_environment("LANG");
+ int tp = locale.find(".");
+ if (tp!=-1)
+ locale=locale.substr(0,tp);
+ return locale;
+}
+
+Error OS_Unix::set_cwd(const String& p_cwd) {
+
+ if (chdir(p_cwd.utf8().get_data())!=0)
+ return ERR_CANT_OPEN;
+
+ return OK;
+}
+
+
+String OS_Unix::get_environment(const String& p_var) const {
+
+ if (getenv(p_var.utf8().get_data()))
+ return getenv(p_var.utf8().get_data());
+ return "";
+}
+
+int OS_Unix::get_processor_count() const {
+
+ return sysconf(_SC_NPROCESSORS_CONF);
+}
+
+String OS_Unix::get_data_dir() const {
+
+ String an = Globals::get_singleton()->get("application/name");
+ if (an!="") {
+
+ if (has_environment("HOME")) {
+
+ return get_environment("HOME")+"/."+an;
+ }
+ }
+
+ return Globals::get_singleton()->get_resource_path();
+
+}
+
+String OS_Unix::get_executable_path() const {
+
+#ifdef __linux__
+ //fix for running from a symlink
+ char buf[256];
+ memset(buf,0,256);
+ readlink("/proc/self/exe", buf, sizeof(buf));
+ //print_line("Exec path is:"+String(buf));
+ String b = buf;
+ if (b=="") {
+ WARN_PRINT("Couldn't get executable path from /proc/self/exe, using argv[0]");
+ return OS::get_executable_path();
+ }
+ return b;
+#else
+ ERR_PRINT("Warning, don't know how to obtain executable path on this OS! Please override this function properly.");
+ return OS::get_executable_path();
+#endif
+}
+
+
+#endif
diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h
new file mode 100644
index 0000000000..72943ac25b
--- /dev/null
+++ b/drivers/unix/os_unix.h
@@ -0,0 +1,121 @@
+/*************************************************************************/
+/* os_unix.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 OS_UNIX_H
+#define OS_UNIX_H
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+#ifdef UNIX_ENABLED
+
+
+#include "os/os.h"
+#include "drivers/unix/ip_unix.h"
+
+
+class OS_Unix : public OS {
+
+ uint64_t ticks_start;
+protected:
+
+ // UNIX only handles the core functions.
+ // inheriting platforms under unix (eg. X11) should handle the rest
+
+ //virtual int get_video_driver_count() const;
+ //virtual const char * get_video_driver_name(int p_driver) const;
+ //virtual VideoMode get_default_video_mode() const;
+
+ virtual int get_audio_driver_count() const;
+ virtual const char * get_audio_driver_name(int p_driver) const;
+
+ virtual void initialize_core();
+ virtual int unix_initialize_audio(int p_audio_driver);
+ //virtual void initialize(int p_video_driver,int p_audio_driver);
+
+ //virtual void finalize();
+ virtual void finalize_core();
+
+ String stdin_buf;
+
+public:
+
+
+ virtual void print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type=ERR_ERROR);
+
+ virtual void print(const char *p_format, ... );
+ virtual void vprint(const char* p_format, va_list p_list,bool p_stderr=false);
+ virtual void alert(const String& p_alert,const String& p_title="ALERT!");
+ virtual String get_stdin_string(bool p_block);
+
+ //virtual void set_mouse_show(bool p_show);
+ //virtual void set_mouse_grab(bool p_grab);
+ //virtual bool is_mouse_grab_enabled() const = 0;
+ //virtual void get_mouse_pos(int &x, int &y) const;
+ //virtual void set_window_title(const String& p_title);
+
+ //virtual void set_video_mode(const VideoMode& p_video_mode);
+ //virtual VideoMode get_video_mode() const;
+ //virtual void get_fullscreen_mode_list(List<VideoMode> *p_list) const;
+
+ virtual Error set_cwd(const String& p_cwd);
+
+ virtual String get_name();
+
+ virtual Date get_date() const;
+ virtual Time get_time() const;
+
+ virtual uint64_t get_unix_time() const;
+
+ virtual void delay_usec(uint32_t p_usec) const;
+ virtual uint64_t get_ticks_usec() const;
+
+ virtual Error execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id=NULL,String* r_pipe=NULL,int *r_exitcode=NULL);
+ virtual Error kill(const ProcessID& p_pid);
+
+ virtual bool has_environment(const String& p_var) const;
+ virtual String get_environment(const String& p_var) const;
+ virtual String get_locale() const;
+
+ virtual int get_processor_count() const;
+
+
+ virtual void debug_break();
+
+ virtual String get_executable_path() const;
+ virtual String get_data_dir() const;
+
+ //virtual void run( MainLoop * p_main_loop );
+
+
+};
+
+#endif
+
+#endif
diff --git a/drivers/unix/semaphore_posix.cpp b/drivers/unix/semaphore_posix.cpp
new file mode 100644
index 0000000000..6f1b8931f9
--- /dev/null
+++ b/drivers/unix/semaphore_posix.cpp
@@ -0,0 +1,89 @@
+/*************************************************************************/
+/* semaphore_posix.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 "semaphore_posix.h"
+
+#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
+
+#include "os/memory.h"
+#include <errno.h>
+#include <stdio.h>
+
+Error SemaphorePosix::wait() {
+
+
+ while(sem_wait(&sem)) {
+ if (errno==EINTR) {
+ errno=0;
+ continue;
+ } else {
+perror("sem waiting");
+ return ERR_BUSY;
+ }
+ }
+ return OK;
+}
+
+Error SemaphorePosix::post() {
+
+ return (sem_post(&sem)==0)?OK:ERR_BUSY;
+}
+int SemaphorePosix::get() const {
+
+ int val;
+ sem_getvalue(&sem, &val);
+
+ return val;
+}
+
+
+Semaphore *SemaphorePosix::create_semaphore_posix() {
+
+ return memnew( SemaphorePosix );
+}
+
+void SemaphorePosix::make_default() {
+
+ create_func=create_semaphore_posix;
+}
+
+SemaphorePosix::SemaphorePosix() {
+
+ int r = sem_init(&sem,0,0);
+ if (r != 0)
+ perror("sem creating");
+}
+
+
+SemaphorePosix::~SemaphorePosix() {
+
+ sem_destroy(&sem);
+}
+
+
+#endif
diff --git a/drivers/unix/semaphore_posix.h b/drivers/unix/semaphore_posix.h
new file mode 100644
index 0000000000..de563c28c4
--- /dev/null
+++ b/drivers/unix/semaphore_posix.h
@@ -0,0 +1,62 @@
+/*************************************************************************/
+/* semaphore_posix.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 SEMAPHORE_POSIX_H
+#define SEMAPHORE_POSIX_H
+
+
+
+#include "os/semaphore.h"
+
+#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
+
+#include <semaphore.h>
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class SemaphorePosix : public Semaphore {
+
+ mutable sem_t sem;
+
+ static Semaphore *create_semaphore_posix();
+
+public:
+
+ virtual Error wait();
+ virtual Error post();
+ virtual int get() const;
+
+ static void make_default();
+ SemaphorePosix();
+
+ ~SemaphorePosix();
+
+};
+
+#endif
+#endif
diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp
new file mode 100644
index 0000000000..8d937d9ca8
--- /dev/null
+++ b/drivers/unix/stream_peer_tcp_posix.cpp
@@ -0,0 +1,388 @@
+/*************************************************************************/
+/* stream_peer_tcp_posix.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifdef UNIX_ENABLED
+
+#include "stream_peer_tcp_posix.h"
+
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <netdb.h>
+#include <sys/types.h>
+#ifndef NO_FCNTL
+#include <sys/fcntl.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <netinet/in.h>
+
+#include <sys/socket.h>
+#ifdef JAVASCRIPT_ENABLED
+#include <arpa/inet.h>
+#endif
+
+#include <netinet/tcp.h>
+
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ #define MSG_NOSIGNAL SO_NOSIGPIPE
+#endif
+
+static void set_addr_in(struct sockaddr_in& their_addr, const IP_Address& p_host, uint16_t p_port) {
+
+ their_addr.sin_family = AF_INET; // host byte order
+ their_addr.sin_port = htons(p_port); // short, network byte order
+ their_addr.sin_addr = *((struct in_addr*)&p_host.host);
+ memset(&(their_addr.sin_zero), '\0', 8);
+};
+
+StreamPeerTCP* StreamPeerTCPPosix::_create() {
+
+ return memnew(StreamPeerTCPPosix);
+};
+
+void StreamPeerTCPPosix::make_default() {
+
+ StreamPeerTCP::_create = StreamPeerTCPPosix::_create;
+};
+
+Error StreamPeerTCPPosix::_block(int p_sockfd, bool p_read, bool p_write) const {
+
+ struct pollfd pfd;
+ pfd.fd = p_sockfd;
+ pfd.events = 0;
+ if (p_read)
+ pfd.events |= POLLIN;
+ if (p_write)
+ pfd.events |= POLLOUT;
+ pfd.revents = 0;
+
+ int ret = poll(&pfd, 1, -1);
+ return ret < 0 ? FAILED : OK;
+};
+
+Error StreamPeerTCPPosix::_poll_connection(bool p_block) const {
+
+ ERR_FAIL_COND_V(status != STATUS_CONNECTING || sockfd == -1, FAILED);
+
+ if (p_block) {
+
+ _block(sockfd, false, true);
+ };
+
+ struct sockaddr_in their_addr;
+ set_addr_in(their_addr, peer_host, peer_port);
+ if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1) {
+
+ if (errno == EISCONN) {
+ status = STATUS_CONNECTED;
+ return OK;
+ };
+
+ return OK;
+ } else {
+
+ status = STATUS_CONNECTED;
+ return OK;
+ };
+
+ return OK;
+};
+
+void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port) {
+
+ sockfd = p_sockfd;
+#ifndef NO_FCNTL
+ fcntl(sockfd, F_SETFL, O_NONBLOCK);
+#else
+ int bval = 1;
+ ioctl(sockfd, FIONBIO, &bval);
+
+#endif
+ status = STATUS_CONNECTING;
+
+ peer_host = p_host;
+ peer_port = p_port;
+};
+
+Error StreamPeerTCPPosix::connect(const IP_Address& p_host, uint16_t p_port) {
+
+ ERR_FAIL_COND_V( p_host.host == 0, ERR_INVALID_PARAMETER);
+
+ if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+ ERR_PRINT("Socket creation failed!");
+ disconnect();
+ //perror("socket");
+ return FAILED;
+ };
+
+#ifndef NO_FCNTL
+ fcntl(sockfd, F_SETFL, O_NONBLOCK);
+#else
+ int bval = 1;
+ ioctl(sockfd, FIONBIO, &bval);
+#endif
+
+ struct sockaddr_in their_addr;
+ set_addr_in(their_addr, p_host, p_port);
+
+ errno = 0;
+ if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1 && errno != EINPROGRESS) {
+
+ ERR_PRINT("Connection to remote host failed!");
+ disconnect();
+ return FAILED;
+ };
+
+ if (errno == EINPROGRESS) {
+ status = STATUS_CONNECTING;
+ } else {
+ status = STATUS_CONNECTED;
+ };
+
+ peer_host = p_host;
+ peer_port = p_port;
+
+ return OK;
+};
+
+Error StreamPeerTCPPosix::write(const uint8_t* p_data,int p_bytes, int &r_sent, bool p_block) {
+
+ if (status == STATUS_NONE || status == STATUS_ERROR) {
+
+ return FAILED;
+ };
+
+ if (status != STATUS_CONNECTED) {
+
+ if (_poll_connection(p_block) != OK) {
+
+ return FAILED;
+ };
+
+ if (status != STATUS_CONNECTED) {
+ r_sent = 0;
+ return OK;
+ };
+ };
+
+ int data_to_send = p_bytes;
+ const uint8_t *offset = p_data;
+ if (sockfd == -1) return FAILED;
+ errno = 0;
+ int total_sent = 0;
+
+ while (data_to_send) {
+
+ int sent_amount = send(sockfd, offset, data_to_send, MSG_NOSIGNAL);
+ //printf("Sent TCP data of %d bytes, errno %d\n", sent_amount, errno);
+
+ if (sent_amount == -1) {
+
+ if (errno != EAGAIN) {
+
+ perror("shit?");
+ disconnect();
+ ERR_PRINT("Server disconnected!\n");
+ return FAILED;
+ };
+
+ if (!p_block) {
+ r_sent = total_sent;
+ return OK;
+ };
+
+ _block(sockfd, false, true);
+ } else {
+
+ data_to_send -= sent_amount;
+ offset += sent_amount;
+ total_sent += sent_amount;
+ };
+ }
+
+ r_sent = total_sent;
+
+ return OK;
+};
+
+Error StreamPeerTCPPosix::read(uint8_t* p_buffer, int p_bytes,int &r_received, bool p_block) {
+
+ if (!is_connected()) {
+
+ return FAILED;
+ };
+
+ if (status == STATUS_CONNECTING) {
+
+ if (_poll_connection(p_block) != OK) {
+
+ return FAILED;
+ };
+
+ if (status != STATUS_CONNECTED) {
+ r_received = 0;
+ return OK;
+ };
+ };
+
+ int to_read = p_bytes;
+ int total_read = 0;
+ errno = 0;
+
+ while (to_read) {
+
+ int read = recv(sockfd, p_buffer + total_read, to_read, 0);
+
+ if (read == -1) {
+
+ if (errno != EAGAIN) {
+
+ perror("shit?");
+ disconnect();
+ ERR_PRINT("Server disconnected!\n");
+ return FAILED;
+ };
+
+ if (!p_block) {
+
+ r_received = total_read;
+ return OK;
+ };
+ _block(sockfd, true, false);
+
+ } else if (read==0) {
+
+ sockfd=-1;
+ status = STATUS_NONE;
+ peer_port = 0;
+ peer_host = IP_Address();
+ return ERR_FILE_EOF;
+
+ } else {
+
+ to_read -= read;
+ total_read += read;
+ };
+ };
+
+ r_received = total_read;
+
+ return OK;
+};
+
+void StreamPeerTCPPosix::set_nodelay(bool p_enabled) {
+
+ ERR_FAIL_COND(!is_connected());
+ int flag=p_enabled?1:0;
+ setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(int));
+}
+
+bool StreamPeerTCPPosix::is_connected() const {
+
+ if (status == STATUS_NONE || status == STATUS_ERROR) {
+
+ return false;
+ };
+ if (status != STATUS_CONNECTED) {
+ return true;
+ };
+
+ return (sockfd!=-1);
+};
+
+StreamPeerTCP::Status StreamPeerTCPPosix::get_status() const {
+
+ if (status == STATUS_CONNECTING) {
+ _poll_connection(false);
+ };
+
+ return status;
+};
+
+
+void StreamPeerTCPPosix::disconnect() {
+
+ if (sockfd != -1)
+ close(sockfd);
+ sockfd=-1;
+
+ status = STATUS_NONE;
+ peer_port = 0;
+ peer_host = IP_Address();
+};
+
+
+Error StreamPeerTCPPosix::put_data(const uint8_t* p_data,int p_bytes) {
+
+ int total;
+ return write(p_data, p_bytes, total, true);
+};
+
+Error StreamPeerTCPPosix::put_partial_data(const uint8_t* p_data,int p_bytes, int &r_sent) {
+
+ return write(p_data, p_bytes, r_sent, false);
+};
+
+Error StreamPeerTCPPosix::get_data(uint8_t* p_buffer, int p_bytes) {
+
+ int total;
+ return read(p_buffer, p_bytes, total, true);
+};
+
+Error StreamPeerTCPPosix::get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received) {
+
+ return read(p_buffer, p_bytes, r_received, false);
+};
+
+IP_Address StreamPeerTCPPosix::get_connected_host() const {
+
+ return peer_host;
+};
+
+uint16_t StreamPeerTCPPosix::get_connected_port() const {
+
+ return peer_port;
+};
+
+StreamPeerTCPPosix::StreamPeerTCPPosix() {
+
+ sockfd = -1;
+ status = STATUS_NONE;
+ peer_port = 0;
+};
+
+StreamPeerTCPPosix::~StreamPeerTCPPosix() {
+
+ disconnect();
+};
+
+#endif
diff --git a/drivers/unix/stream_peer_tcp_posix.h b/drivers/unix/stream_peer_tcp_posix.h
new file mode 100644
index 0000000000..1259b46ff2
--- /dev/null
+++ b/drivers/unix/stream_peer_tcp_posix.h
@@ -0,0 +1,89 @@
+/*************************************************************************/
+/* stream_peer_tcp_posix.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifdef UNIX_ENABLED
+
+#ifndef STREAM_PEER_TCP_POSIX_H
+#define STREAM_PEER_TCP_POSIX_H
+
+#include "core/io/ip_address.h"
+#include "core/io/stream_peer_tcp.h"
+#include "error_list.h"
+
+#include "core/io/ip_address.h"
+
+class StreamPeerTCPPosix : public StreamPeerTCP {
+
+protected:
+
+ mutable Status status;
+
+ int sockfd;
+
+ Error _block(int p_sockfd, bool p_read, bool p_write) const;
+
+ Error _poll_connection(bool p_block) const;
+
+ IP_Address peer_host;
+ int peer_port;
+
+ Error write(const uint8_t* p_data,int p_bytes, int &r_sent, bool p_block);
+ Error read(uint8_t* p_buffer, int p_bytes,int &r_received, bool p_block);
+
+ static StreamPeerTCP* _create();
+
+public:
+
+ virtual Error connect(const IP_Address& p_host, uint16_t p_port);
+
+ virtual Error put_data(const uint8_t* p_data,int p_bytes);
+ virtual Error put_partial_data(const uint8_t* p_data,int p_bytes, int &r_sent);
+
+ virtual Error get_data(uint8_t* p_buffer, int p_bytes);
+ virtual Error get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received);
+
+ void set_socket(int p_sockfd, IP_Address p_host, int p_port);
+
+ virtual IP_Address get_connected_host() const;
+ virtual uint16_t get_connected_port() const;
+
+ virtual bool is_connected() const;
+ virtual Status get_status() const;
+ virtual void disconnect();
+
+ virtual void set_nodelay(bool p_enabled);
+
+ static void make_default();
+
+ StreamPeerTCPPosix();
+ ~StreamPeerTCPPosix();
+};
+
+#endif // TCP_CLIENT_POSIX_H
+
+#endif
diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp
new file mode 100644
index 0000000000..f91ad36ef9
--- /dev/null
+++ b/drivers/unix/tcp_server_posix.cpp
@@ -0,0 +1,178 @@
+/*************************************************************************/
+/* tcp_server_posix.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "tcp_server_posix.h"
+#include "stream_peer_tcp_posix.h"
+
+#ifdef UNIX_ENABLED
+
+#include <poll.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <netdb.h>
+#include <sys/types.h>
+#ifndef NO_FCNTL
+#include <sys/fcntl.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#ifdef JAVASCRIPT_ENABLED
+#include <arpa/inet.h>
+#endif
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <assert.h>
+TCP_Server* TCPServerPosix::_create() {
+
+ return memnew(TCPServerPosix);
+};
+
+void TCPServerPosix::make_default() {
+
+ TCP_Server::_create = TCPServerPosix::_create;
+};
+
+Error TCPServerPosix::listen(uint16_t p_port,const List<String> *p_accepted_hosts) {
+
+ printf("********* listening on port %i\n", p_port);
+ int sockfd;
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ ERR_FAIL_COND_V(sockfd == -1, FAILED);
+#ifndef NO_FCNTL
+ fcntl(sockfd, F_SETFL, O_NONBLOCK);
+#else
+ int bval = 1;
+ ioctl(sockfd, FIONBIO, &bval);
+#endif
+
+ int reuse=1;
+ if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) {
+
+ printf("REUSEADDR failed!");
+ }
+
+ struct sockaddr_in my_addr;
+ my_addr.sin_family = AF_INET; // host byte order
+ my_addr.sin_port = htons(p_port); // short, network byte order
+ my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP TODO: use p_accepted_hosts
+ memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero);
+
+ if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) != -1) {
+
+ if (::listen(sockfd, 1) == -1) {
+
+ close(sockfd);
+ ERR_FAIL_V(FAILED);
+ };
+ };
+
+ if (listen_sockfd != -1) {
+
+ printf("FAILED\n");
+ stop();
+ };
+
+ listen_sockfd = sockfd;
+
+ printf("OK! %i\n", listen_sockfd);
+ return OK;
+};
+
+bool TCPServerPosix::is_connection_available() const {
+
+ if (listen_sockfd == -1) {
+ return false;
+ };
+
+ struct pollfd pfd;
+ pfd.fd = listen_sockfd;
+ pfd.events = POLLIN;
+ pfd.revents = 0;
+
+ int ret = poll(&pfd, 1, 0);
+ ERR_FAIL_COND_V(ret < 0, FAILED);
+
+ if (ret && (pfd.revents & POLLIN)) {
+ printf("has connection!\n");
+ return true;
+ };
+
+ return false;
+};
+
+Ref<StreamPeerTCP> TCPServerPosix::take_connection() {
+
+ if (!is_connection_available()) {
+ return Ref<StreamPeerTCP>();
+ };
+
+ struct sockaddr_in their_addr;
+ socklen_t sin_size = sizeof(their_addr);
+ int fd = accept(listen_sockfd, (struct sockaddr *)&their_addr, &sin_size);
+ ERR_FAIL_COND_V(fd == -1, Ref<StreamPeerTCP>());
+#ifndef NO_FCNTL
+ fcntl(fd, F_SETFL, O_NONBLOCK);
+#else
+ int bval = 1;
+ ioctl(fd, FIONBIO, &bval);
+#endif
+
+ Ref<StreamPeerTCPPosix> conn = memnew(StreamPeerTCPPosix);
+ IP_Address ip;
+ ip.host = (uint32_t)their_addr.sin_addr.s_addr;
+ conn->set_socket(fd, ip, ntohs(their_addr.sin_port));
+
+ return conn;
+};
+
+void TCPServerPosix::stop() {
+
+ if (listen_sockfd != -1) {
+ print_line("CLOSING CONNECTION");
+ int ret = close(listen_sockfd);
+ ERR_FAIL_COND(ret!=0);
+ };
+
+ listen_sockfd = -1;
+};
+
+
+TCPServerPosix::TCPServerPosix() {
+
+ listen_sockfd = -1;
+};
+
+TCPServerPosix::~TCPServerPosix() {
+
+ stop();
+};
+#endif
diff --git a/drivers/unix/tcp_server_posix.h b/drivers/unix/tcp_server_posix.h
new file mode 100644
index 0000000000..053aba0d10
--- /dev/null
+++ b/drivers/unix/tcp_server_posix.h
@@ -0,0 +1,57 @@
+/*************************************************************************/
+/* tcp_server_posix.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef TCP_SERVER_POSIX_H
+#define TCP_SERVER_POSIX_H
+
+#ifdef UNIX_ENABLED
+#include "core/io/tcp_server.h"
+
+class TCPServerPosix : public TCP_Server {
+
+ int listen_sockfd;
+
+ static TCP_Server* _create();
+
+public:
+
+ virtual Error listen(uint16_t p_port,const List<String> *p_accepted_hosts=NULL);
+ virtual bool is_connection_available() const;
+ virtual Ref<StreamPeerTCP> take_connection();
+
+ virtual void stop();
+
+ static void make_default();
+
+ TCPServerPosix();
+ ~TCPServerPosix();
+};
+
+
+#endif // TCP_SERVER_POSIX_H
+#endif
diff --git a/drivers/unix/thread_posix.cpp b/drivers/unix/thread_posix.cpp
new file mode 100644
index 0000000000..b2f1e144bb
--- /dev/null
+++ b/drivers/unix/thread_posix.cpp
@@ -0,0 +1,99 @@
+/*************************************************************************/
+/* thread_posix.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 "thread_posix.h"
+
+#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
+
+#include "os/memory.h"
+
+Thread::ID ThreadPosix::get_ID() const {
+
+ return id;
+}
+
+Thread* ThreadPosix::create_thread_posix() {
+
+ return memnew( ThreadPosix );
+}
+
+void *ThreadPosix::thread_callback(void *userdata) {
+
+ ThreadPosix *t=reinterpret_cast<ThreadPosix*>(userdata);
+ t->callback(t->user);
+ t->id=(ID)pthread_self();
+ return NULL;
+}
+
+Thread* ThreadPosix::create_func_posix(ThreadCreateCallback p_callback,void *p_user,const Settings&) {
+
+ ThreadPosix *tr= memnew(ThreadPosix);
+ tr->callback=p_callback;
+ tr->user=p_user;
+ pthread_attr_init(&tr->pthread_attr);
+ pthread_attr_setdetachstate(&tr->pthread_attr, PTHREAD_CREATE_JOINABLE);
+
+ pthread_create(&tr->pthread, &tr->pthread_attr, thread_callback, tr);
+
+ return tr;
+}
+Thread::ID ThreadPosix::get_thread_ID_func_posix() {
+
+ return (ID)pthread_self();
+}
+void ThreadPosix::wait_to_finish_func_posix(Thread* p_thread) {
+
+ ThreadPosix *tp=static_cast<ThreadPosix*>(p_thread);
+ ERR_FAIL_COND(!tp);
+ ERR_FAIL_COND(tp->pthread==0);
+
+ pthread_join(tp->pthread,NULL);
+ tp->pthread=0;
+}
+
+
+void ThreadPosix::make_default() {
+
+ create_func=create_func_posix;
+ get_thread_ID_func=get_thread_ID_func_posix;
+ wait_to_finish_func=wait_to_finish_func_posix;
+
+}
+
+ThreadPosix::ThreadPosix() {
+
+ pthread=0;
+}
+
+
+ThreadPosix::~ThreadPosix() {
+
+}
+
+
+#endif
diff --git a/drivers/unix/thread_posix.h b/drivers/unix/thread_posix.h
new file mode 100644
index 0000000000..a088f1d5de
--- /dev/null
+++ b/drivers/unix/thread_posix.h
@@ -0,0 +1,75 @@
+/*************************************************************************/
+/* thread_posix.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 THREAD_POSIX_H
+#define THREAD_POSIX_H
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
+
+#include <sys/types.h>
+#include <pthread.h>
+#include "os/thread.h"
+
+class ThreadPosix : public Thread {
+
+ pthread_t pthread;
+ pthread_attr_t pthread_attr;
+ ThreadCreateCallback callback;
+ void *user;
+ ID id;
+
+ static Thread* create_thread_posix();
+
+
+ static void *thread_callback(void *userdata);
+
+ static Thread* create_func_posix(ThreadCreateCallback p_callback,void *,const Settings&);
+ static ID get_thread_ID_func_posix();
+ static void wait_to_finish_func_posix(Thread* p_thread);
+
+ ThreadPosix();
+public:
+
+
+ virtual ID get_ID() const;
+
+ static void make_default();
+
+
+ ~ThreadPosix();
+
+};
+
+
+#endif
+
+#endif