GODOT IS OPEN SOURCE

This commit is contained in:
Juan Linietsky
2014-02-09 22:10:30 -03:00
parent 0e49da1687
commit 0b806ee0fc
3138 changed files with 1294441 additions and 0 deletions

7
drivers/unix/SCsub Normal file
View File

@@ -0,0 +1,7 @@
Import('env')
env.add_source_files(env.drivers_sources,"*.cpp")
Export('env')

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

68
drivers/unix/ip_unix.cpp Normal file
View File

@@ -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

49
drivers/unix/ip_unix.h Normal file
View File

@@ -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

View File

@@ -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
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

410
drivers/unix/os_unix.cpp Normal file
View File

@@ -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

121
drivers/unix/os_unix.h Normal file
View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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