mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-19 18:45:52 +00:00
Add missing native BSD support for Beast
This commit is contained in:
@@ -52,6 +52,14 @@ env.ParseConfig('pkg-config --cflags --libs openssl')
|
||||
# Use protobuf
|
||||
env.ParseConfig('pkg-config --cflags --libs protobuf')
|
||||
|
||||
# Beast uses kvm on FreeBSD
|
||||
if FreeBSD:
|
||||
env.Append (
|
||||
LIBS = [
|
||||
'kvm'
|
||||
]
|
||||
)
|
||||
|
||||
# The required version of boost is documented in the README file.
|
||||
#
|
||||
# We whitelist platforms where the non -mt version is linked with pthreads.
|
||||
@@ -59,6 +67,7 @@ env.ParseConfig('pkg-config --cflags --libs protobuf')
|
||||
# If a threading library is included the platform can be whitelisted.
|
||||
#
|
||||
# FreeBSD and Ubuntu non-mt libs do link with pthreads.
|
||||
|
||||
if FreeBSD or Ubuntu:
|
||||
env.Append(
|
||||
LIBS = [
|
||||
|
||||
@@ -419,6 +419,22 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\native\beast_bsd_Files.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\native\beast_bsd_Network.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\native\beast_bsd_SystemStats.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\native\beast_bsd_Threads.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\native\beast_linux_Files.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
|
||||
@@ -952,5 +952,17 @@
|
||||
<ClCompile Include="..\..\modules\beast_basics\threads\beast_ThreadWithCallQueue.cpp">
|
||||
<Filter>beast_basics\threads</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\native\beast_bsd_SystemStats.cpp">
|
||||
<Filter>beast_core\native</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\native\beast_bsd_Files.cpp">
|
||||
<Filter>beast_core\native</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\native\beast_bsd_Network.cpp">
|
||||
<Filter>beast_core\native</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\native\beast_bsd_Threads.cpp">
|
||||
<Filter>beast_core\native</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -201,6 +201,13 @@ namespace beast
|
||||
#include "native/beast_linux_SystemStats.cpp"
|
||||
#include "native/beast_linux_Threads.cpp"
|
||||
|
||||
//==============================================================================
|
||||
#elif BEAST_BSD
|
||||
#include "native/beast_bsd_Files.cpp"
|
||||
#include "native/beast_bsd_Network.cpp"
|
||||
#include "native/beast_bsd_SystemStats.cpp"
|
||||
#include "native/beast_bsd_Threads.cpp"
|
||||
|
||||
//==============================================================================
|
||||
#elif BEAST_ANDROID
|
||||
#include "native/beast_android_Files.cpp"
|
||||
|
||||
@@ -188,8 +188,17 @@
|
||||
|
||||
#if BEAST_BSD
|
||||
#include <dirent.h>
|
||||
#include <kvm.h>
|
||||
#include <langinfo.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
// This has to be in the global namespace
|
||||
extern char** environ;
|
||||
|
||||
#else
|
||||
#include <sys/dir.h>
|
||||
#include <sys/vfs.h>
|
||||
|
||||
373
Subtrees/beast/modules/beast_core/native/beast_bsd_Files.cpp
Normal file
373
Subtrees/beast/modules/beast_core/native/beast_bsd_Files.cpp
Normal file
@@ -0,0 +1,373 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Portions of this file are from JUCE.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
Please visit http://www.juce.com
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
enum
|
||||
{
|
||||
U_ISOFS_SUPER_MAGIC = 0x9660, // linux/iso_fs.h
|
||||
U_MSDOS_SUPER_MAGIC = 0x4d44, // linux/msdos_fs.h
|
||||
U_NFS_SUPER_MAGIC = 0x6969, // linux/nfs_fs.h
|
||||
U_SMB_SUPER_MAGIC = 0x517B // linux/smb_fs.h
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
bool File::copyInternal (const File& dest) const
|
||||
{
|
||||
FileInputStream in (*this);
|
||||
|
||||
if (dest.deleteFile())
|
||||
{
|
||||
{
|
||||
FileOutputStream out (dest);
|
||||
|
||||
if (out.failedToOpen())
|
||||
return false;
|
||||
|
||||
if (out.writeFromInputStream (in, -1) == getSize())
|
||||
return true;
|
||||
}
|
||||
|
||||
dest.deleteFile();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void File::findFileSystemRoots (Array<File>& destArray)
|
||||
{
|
||||
destArray.add (File ("/"));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool File::isOnCDRomDrive() const
|
||||
{
|
||||
struct statfs buf;
|
||||
|
||||
return statfs (getFullPathName().toUTF8(), &buf) == 0
|
||||
&& buf.f_type == (short) U_ISOFS_SUPER_MAGIC;
|
||||
}
|
||||
|
||||
bool File::isOnHardDisk() const
|
||||
{
|
||||
struct statfs buf;
|
||||
|
||||
if (statfs (getFullPathName().toUTF8(), &buf) == 0)
|
||||
{
|
||||
switch (buf.f_type)
|
||||
{
|
||||
case U_ISOFS_SUPER_MAGIC: // CD-ROM
|
||||
case U_MSDOS_SUPER_MAGIC: // Probably floppy (but could be mounted FAT filesystem)
|
||||
case U_NFS_SUPER_MAGIC: // Network NFS
|
||||
case U_SMB_SUPER_MAGIC: // Network Samba
|
||||
return false;
|
||||
|
||||
default:
|
||||
// Assume anything else is a hard-disk (but note it could
|
||||
// be a RAM disk. There isn't a good way of determining
|
||||
// this for sure)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Assume so if this fails for some reason
|
||||
return true;
|
||||
}
|
||||
|
||||
bool File::isOnRemovableDrive() const
|
||||
{
|
||||
bassertfalse; // xxx not implemented for linux!
|
||||
return false;
|
||||
}
|
||||
|
||||
bool File::isHidden() const
|
||||
{
|
||||
return getFileName().startsWithChar ('.');
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
namespace
|
||||
{
|
||||
File beast_readlink (const String& file, const File& defaultFile)
|
||||
{
|
||||
const size_t size = 8192;
|
||||
HeapBlock<char> buffer;
|
||||
buffer.malloc (size + 4);
|
||||
|
||||
const size_t numBytes = readlink (file.toUTF8(), buffer, size);
|
||||
|
||||
if (numBytes > 0 && numBytes <= size)
|
||||
return File (file).getSiblingFile (String::fromUTF8 (buffer, (int) numBytes));
|
||||
|
||||
return defaultFile;
|
||||
}
|
||||
}
|
||||
|
||||
File File::getLinkedTarget() const
|
||||
{
|
||||
return beast_readlink (getFullPathName().toUTF8(), *this);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static File resolveXDGFolder (const char* const type, const char* const fallbackFolder)
|
||||
{
|
||||
StringArray confLines;
|
||||
File ("~/.config/user-dirs.dirs").readLines (confLines);
|
||||
|
||||
for (int i = 0; i < confLines.size(); ++i)
|
||||
{
|
||||
const String line (confLines[i].trimStart());
|
||||
|
||||
if (line.startsWith (type))
|
||||
{
|
||||
// eg. resolve XDG_MUSIC_DIR="$HOME/Music" to /home/user/Music
|
||||
const File f (line.replace ("$HOME", File ("~").getFullPathName())
|
||||
.fromFirstOccurrenceOf ("=", false, false)
|
||||
.trim().unquoted());
|
||||
|
||||
if (f.isDirectory())
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
return File (fallbackFolder);
|
||||
}
|
||||
|
||||
const char* const* beast_argv = nullptr;
|
||||
int beast_argc = 0;
|
||||
|
||||
File File::getSpecialLocation (const SpecialLocationType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case userHomeDirectory:
|
||||
{
|
||||
const char* homeDir = getenv ("HOME");
|
||||
|
||||
if (homeDir == nullptr)
|
||||
{
|
||||
struct passwd* const pw = getpwuid (getuid());
|
||||
if (pw != nullptr)
|
||||
homeDir = pw->pw_dir;
|
||||
}
|
||||
|
||||
return File (CharPointer_UTF8 (homeDir));
|
||||
}
|
||||
|
||||
case userDocumentsDirectory: return resolveXDGFolder ("XDG_DOCUMENTS_DIR", "~");
|
||||
case userMusicDirectory: return resolveXDGFolder ("XDG_MUSIC_DIR", "~");
|
||||
case userMoviesDirectory: return resolveXDGFolder ("XDG_VIDEOS_DIR", "~");
|
||||
case userPicturesDirectory: return resolveXDGFolder ("XDG_PICTURES_DIR", "~");
|
||||
case userDesktopDirectory: return resolveXDGFolder ("XDG_DESKTOP_DIR", "~/Desktop");
|
||||
case userApplicationDataDirectory: return File ("~");
|
||||
case commonApplicationDataDirectory: return File ("/var");
|
||||
case globalApplicationsDirectory: return File ("/usr");
|
||||
|
||||
case tempDirectory:
|
||||
{
|
||||
File tmp ("/var/tmp");
|
||||
|
||||
if (! tmp.isDirectory())
|
||||
{
|
||||
tmp = "/tmp";
|
||||
|
||||
if (! tmp.isDirectory())
|
||||
tmp = File::getCurrentWorkingDirectory();
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
case invokedExecutableFile:
|
||||
if (beast_argv != nullptr && beast_argc > 0)
|
||||
return File (CharPointer_UTF8 (beast_argv[0]));
|
||||
// deliberate fall-through...
|
||||
|
||||
case currentExecutableFile:
|
||||
case currentApplicationFile:
|
||||
return beast_getExecutableFile();
|
||||
|
||||
case hostApplicationPath:
|
||||
return beast_readlink ("/proc/self/exe", beast_getExecutableFile());
|
||||
|
||||
default:
|
||||
bassertfalse; // unknown type?
|
||||
break;
|
||||
}
|
||||
|
||||
return File::nonexistent;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
String File::getVersion() const
|
||||
{
|
||||
return String::empty; // xxx not yet implemented
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool File::moveToTrash() const
|
||||
{
|
||||
if (! exists())
|
||||
return true;
|
||||
|
||||
File trashCan ("~/.Trash");
|
||||
|
||||
if (! trashCan.isDirectory())
|
||||
trashCan = "~/.local/share/Trash/files";
|
||||
|
||||
if (! trashCan.isDirectory())
|
||||
return false;
|
||||
|
||||
return moveFileTo (trashCan.getNonexistentChildFile (getFileNameWithoutExtension(),
|
||||
getFileExtension()));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class DirectoryIterator::NativeIterator::Pimpl
|
||||
{
|
||||
public:
|
||||
Pimpl (const File& directory, const String& wildCard_)
|
||||
: parentDir (File::addTrailingSeparator (directory.getFullPathName())),
|
||||
wildCard (wildCard_),
|
||||
dir (opendir (directory.getFullPathName().toUTF8()))
|
||||
{
|
||||
}
|
||||
|
||||
~Pimpl()
|
||||
{
|
||||
if (dir != nullptr)
|
||||
closedir (dir);
|
||||
}
|
||||
|
||||
bool next (String& filenameFound,
|
||||
bool* const isDir, bool* const isHidden, int64* const fileSize,
|
||||
Time* const modTime, Time* const creationTime, bool* const isReadOnly)
|
||||
{
|
||||
if (dir != nullptr)
|
||||
{
|
||||
const char* wildcardUTF8 = nullptr;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
struct dirent* const de = readdir (dir);
|
||||
|
||||
if (de == nullptr)
|
||||
break;
|
||||
|
||||
if (wildcardUTF8 == nullptr)
|
||||
wildcardUTF8 = wildCard.toUTF8();
|
||||
|
||||
if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0)
|
||||
{
|
||||
filenameFound = CharPointer_UTF8 (de->d_name);
|
||||
|
||||
updateStatInfoForFile (parentDir + filenameFound, isDir, fileSize, modTime, creationTime, isReadOnly);
|
||||
|
||||
if (isHidden != nullptr)
|
||||
*isHidden = filenameFound.startsWithChar ('.');
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
String parentDir, wildCard;
|
||||
DIR* dir;
|
||||
|
||||
BEAST_DECLARE_NON_COPYABLE (Pimpl)
|
||||
};
|
||||
|
||||
DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildCard)
|
||||
: pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCard))
|
||||
{
|
||||
}
|
||||
|
||||
DirectoryIterator::NativeIterator::~NativeIterator()
|
||||
{
|
||||
}
|
||||
|
||||
bool DirectoryIterator::NativeIterator::next (String& filenameFound,
|
||||
bool* const isDir, bool* const isHidden, int64* const fileSize,
|
||||
Time* const modTime, Time* const creationTime, bool* const isReadOnly)
|
||||
{
|
||||
return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
static bool isFileExecutable (const String& filename)
|
||||
{
|
||||
beast_statStruct info;
|
||||
|
||||
return beast_stat (filename, info)
|
||||
&& S_ISREG (info.st_mode)
|
||||
&& access (filename.toUTF8(), X_OK) == 0;
|
||||
}
|
||||
|
||||
bool Process::openDocument (const String& fileName, const String& parameters)
|
||||
{
|
||||
String cmdString (fileName.replace (" ", "\\ ",false));
|
||||
cmdString << " " << parameters;
|
||||
|
||||
if (URL::isProbablyAWebsiteURL (fileName)
|
||||
|| cmdString.startsWithIgnoreCase ("file:")
|
||||
|| URL::isProbablyAnEmailAddress (fileName)
|
||||
|| File::createFileWithoutCheckingPath (fileName).isDirectory()
|
||||
|| ! isFileExecutable (fileName))
|
||||
{
|
||||
// create a command that tries to launch a bunch of likely browsers
|
||||
const char* const browserNames[] = { "xdg-open", "/etc/alternatives/x-www-browser", "firefox", "mozilla",
|
||||
"google-chrome", "chromium-browser", "opera", "konqueror" };
|
||||
StringArray cmdLines;
|
||||
|
||||
for (int i = 0; i < numElementsInArray (browserNames); ++i)
|
||||
cmdLines.add (String (browserNames[i]) + " " + cmdString.trim().quoted());
|
||||
|
||||
cmdString = cmdLines.joinIntoString (" || ");
|
||||
}
|
||||
|
||||
const char* const argv[4] = { "/bin/sh", "-c", cmdString.toUTF8(), 0 };
|
||||
|
||||
const int cpid = fork();
|
||||
|
||||
if (cpid == 0)
|
||||
{
|
||||
setsid();
|
||||
|
||||
// Child process
|
||||
execve (argv[0], (char**) argv, environ);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
return cpid >= 0;
|
||||
}
|
||||
|
||||
void File::revealToUser() const
|
||||
{
|
||||
if (isDirectory())
|
||||
startAsProcess();
|
||||
else if (getParentDirectory().exists())
|
||||
getParentDirectory().startAsProcess();
|
||||
}
|
||||
461
Subtrees/beast/modules/beast_core/native/beast_bsd_Network.cpp
Normal file
461
Subtrees/beast/modules/beast_core/native/beast_bsd_Network.cpp
Normal file
@@ -0,0 +1,461 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Portions of this file are from JUCE.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
Please visit http://www.juce.com
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
void MACAddress::findAllAddresses (Array<MACAddress>& result)
|
||||
{
|
||||
#if 1
|
||||
bassertfalse; // VFALCO TODO Implement for FreeBSD
|
||||
#else
|
||||
const int s = socket (AF_INET, SOCK_DGRAM, 0);
|
||||
if (s != -1)
|
||||
{
|
||||
char buf [1024];
|
||||
struct ifconf ifc;
|
||||
ifc.ifc_len = sizeof (buf);
|
||||
ifc.ifc_buf = buf;
|
||||
ioctl (s, SIOCGIFCONF, &ifc);
|
||||
|
||||
for (unsigned int i = 0; i < ifc.ifc_len / sizeof (struct ifreq); ++i)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
strcpy (ifr.ifr_name, ifc.ifc_req[i].ifr_name);
|
||||
|
||||
if (ioctl (s, SIOCGIFFLAGS, &ifr) == 0
|
||||
&& (ifr.ifr_flags & IFF_LOOPBACK) == 0
|
||||
&& ioctl (s, SIOCGIFHWADDR, &ifr) == 0)
|
||||
{
|
||||
result.addIfNotAlreadyThere (MACAddress ((const uint8*) ifr.ifr_hwaddr.sa_data));
|
||||
}
|
||||
}
|
||||
|
||||
close (s);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool Process::openEmailWithAttachments (const String& /* targetEmailAddress */,
|
||||
const String& /* emailSubject */,
|
||||
const String& /* bodyText */,
|
||||
const StringArray& /* filesToAttach */)
|
||||
{
|
||||
bassertfalse; // xxx todo
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class WebInputStream : public InputStream
|
||||
{
|
||||
public:
|
||||
WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_,
|
||||
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
|
||||
const String& headers_, int timeOutMs_, StringPairArray* responseHeaders)
|
||||
: socketHandle (-1), levelsOfRedirection (0),
|
||||
address (address_), headers (headers_), postData (postData_), position (0),
|
||||
finished (false), isPost (isPost_), timeOutMs (timeOutMs_)
|
||||
{
|
||||
createConnection (progressCallback, progressCallbackContext);
|
||||
|
||||
if (responseHeaders != nullptr && ! isError())
|
||||
{
|
||||
for (int i = 0; i < headerLines.size(); ++i)
|
||||
{
|
||||
const String& headersEntry = headerLines[i];
|
||||
const String key (headersEntry.upToFirstOccurrenceOf (": ", false, false));
|
||||
const String value (headersEntry.fromFirstOccurrenceOf (": ", false, false));
|
||||
const String previousValue ((*responseHeaders) [key]);
|
||||
responseHeaders->set (key, previousValue.isEmpty() ? value : (previousValue + "," + value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~WebInputStream()
|
||||
{
|
||||
closeSocket();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool isError() const { return socketHandle < 0; }
|
||||
bool isExhausted() { return finished; }
|
||||
int64 getPosition() { return position; }
|
||||
|
||||
int64 getTotalLength()
|
||||
{
|
||||
//xxx to do
|
||||
return -1;
|
||||
}
|
||||
|
||||
int read (void* buffer, int bytesToRead)
|
||||
{
|
||||
if (finished || isError())
|
||||
return 0;
|
||||
|
||||
fd_set readbits;
|
||||
FD_ZERO (&readbits);
|
||||
FD_SET (socketHandle, &readbits);
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = bmax (1, timeOutMs / 1000);
|
||||
tv.tv_usec = 0;
|
||||
|
||||
if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0)
|
||||
return 0; // (timeout)
|
||||
|
||||
const int bytesRead = bmax (0, (int) recv (socketHandle, buffer, bytesToRead, MSG_WAITALL));
|
||||
if (bytesRead == 0)
|
||||
finished = true;
|
||||
position += bytesRead;
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
bool setPosition (int64 wantedPos)
|
||||
{
|
||||
if (isError())
|
||||
return false;
|
||||
|
||||
if (wantedPos != position)
|
||||
{
|
||||
finished = false;
|
||||
|
||||
if (wantedPos < position)
|
||||
{
|
||||
closeSocket();
|
||||
position = 0;
|
||||
createConnection (0, 0);
|
||||
}
|
||||
|
||||
skipNextBytes (wantedPos - position);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
private:
|
||||
int socketHandle, levelsOfRedirection;
|
||||
StringArray headerLines;
|
||||
String address, headers;
|
||||
MemoryBlock postData;
|
||||
int64 position;
|
||||
bool finished;
|
||||
const bool isPost;
|
||||
const int timeOutMs;
|
||||
|
||||
void closeSocket()
|
||||
{
|
||||
if (socketHandle >= 0)
|
||||
close (socketHandle);
|
||||
|
||||
socketHandle = -1;
|
||||
levelsOfRedirection = 0;
|
||||
}
|
||||
|
||||
void createConnection (URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext)
|
||||
{
|
||||
closeSocket();
|
||||
|
||||
uint32 timeOutTime = Time::getMillisecondCounter();
|
||||
|
||||
if (timeOutMs == 0)
|
||||
timeOutTime += 60000;
|
||||
else if (timeOutMs < 0)
|
||||
timeOutTime = 0xffffffff;
|
||||
else
|
||||
timeOutTime += timeOutMs;
|
||||
|
||||
String hostName, hostPath;
|
||||
int hostPort;
|
||||
if (! decomposeURL (address, hostName, hostPath, hostPort))
|
||||
return;
|
||||
|
||||
String serverName, proxyName, proxyPath;
|
||||
int proxyPort = 0;
|
||||
int port = 0;
|
||||
|
||||
const String proxyURL (getenv ("http_proxy"));
|
||||
if (proxyURL.startsWithIgnoreCase ("http://"))
|
||||
{
|
||||
if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort))
|
||||
return;
|
||||
|
||||
serverName = proxyName;
|
||||
port = proxyPort;
|
||||
}
|
||||
else
|
||||
{
|
||||
serverName = hostName;
|
||||
port = hostPort;
|
||||
}
|
||||
|
||||
struct addrinfo hints;
|
||||
zerostruct (hints);
|
||||
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_NUMERICSERV;
|
||||
|
||||
struct addrinfo* result = nullptr;
|
||||
if (getaddrinfo (serverName.toUTF8(), String (port).toUTF8(), &hints, &result) != 0 || result == 0)
|
||||
return;
|
||||
|
||||
socketHandle = socket (result->ai_family, result->ai_socktype, 0);
|
||||
|
||||
if (socketHandle == -1)
|
||||
{
|
||||
freeaddrinfo (result);
|
||||
return;
|
||||
}
|
||||
|
||||
int receiveBufferSize = 16384;
|
||||
setsockopt (socketHandle, SOL_SOCKET, SO_RCVBUF, (char*) &receiveBufferSize, sizeof (receiveBufferSize));
|
||||
setsockopt (socketHandle, SOL_SOCKET, SO_KEEPALIVE, 0, 0);
|
||||
|
||||
#if BEAST_MAC
|
||||
setsockopt (socketHandle, SOL_SOCKET, SO_NOSIGPIPE, 0, 0);
|
||||
#endif
|
||||
|
||||
if (connect (socketHandle, result->ai_addr, result->ai_addrlen) == -1)
|
||||
{
|
||||
closeSocket();
|
||||
freeaddrinfo (result);
|
||||
return;
|
||||
}
|
||||
|
||||
freeaddrinfo (result);
|
||||
|
||||
{
|
||||
const MemoryBlock requestHeader (createRequestHeader (hostName, hostPort, proxyName, proxyPort,
|
||||
hostPath, address, headers, postData, isPost));
|
||||
|
||||
if (! sendHeader (socketHandle, requestHeader, timeOutTime, progressCallback, progressCallbackContext))
|
||||
{
|
||||
closeSocket();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
String responseHeader (readResponse (socketHandle, timeOutTime));
|
||||
|
||||
if (responseHeader.isNotEmpty())
|
||||
{
|
||||
headerLines = StringArray::fromLines (responseHeader);
|
||||
|
||||
const int statusCode = responseHeader.fromFirstOccurrenceOf (" ", false, false)
|
||||
.substring (0, 3).getIntValue();
|
||||
|
||||
//int contentLength = findHeaderItem (lines, "Content-Length:").getIntValue();
|
||||
//bool isChunked = findHeaderItem (lines, "Transfer-Encoding:").equalsIgnoreCase ("chunked");
|
||||
|
||||
String location (findHeaderItem (headerLines, "Location:"));
|
||||
|
||||
if (statusCode >= 300 && statusCode < 400 && location.isNotEmpty())
|
||||
{
|
||||
if (! location.startsWithIgnoreCase ("http://"))
|
||||
location = "http://" + location;
|
||||
|
||||
if (++levelsOfRedirection <= 3)
|
||||
{
|
||||
address = location;
|
||||
createConnection (progressCallback, progressCallbackContext);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
levelsOfRedirection = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
closeSocket();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static String readResponse (const int socketHandle, const uint32 timeOutTime)
|
||||
{
|
||||
int bytesRead = 0, numConsecutiveLFs = 0;
|
||||
MemoryBlock buffer (1024, true);
|
||||
|
||||
while (numConsecutiveLFs < 2 && bytesRead < 32768
|
||||
&& Time::getMillisecondCounter() <= timeOutTime)
|
||||
{
|
||||
fd_set readbits;
|
||||
FD_ZERO (&readbits);
|
||||
FD_SET (socketHandle, &readbits);
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = bmax (1, (int) (timeOutTime - Time::getMillisecondCounter()) / 1000);
|
||||
tv.tv_usec = 0;
|
||||
|
||||
if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0)
|
||||
return String::empty; // (timeout)
|
||||
|
||||
buffer.ensureSize (bytesRead + 8, true);
|
||||
char* const dest = (char*) buffer.getData() + bytesRead;
|
||||
|
||||
if (recv (socketHandle, dest, 1, 0) == -1)
|
||||
return String::empty;
|
||||
|
||||
const char lastByte = *dest;
|
||||
++bytesRead;
|
||||
|
||||
if (lastByte == '\n')
|
||||
++numConsecutiveLFs;
|
||||
else if (lastByte != '\r')
|
||||
numConsecutiveLFs = 0;
|
||||
}
|
||||
|
||||
const String header (CharPointer_UTF8 ((const char*) buffer.getData()));
|
||||
|
||||
if (header.startsWithIgnoreCase ("HTTP/"))
|
||||
return header.trimEnd();
|
||||
|
||||
return String::empty;
|
||||
}
|
||||
|
||||
static void writeValueIfNotPresent (MemoryOutputStream& dest, const String& headers, const String& key, const String& value)
|
||||
{
|
||||
if (! headers.containsIgnoreCase (key))
|
||||
dest << "\r\n" << key << ' ' << value;
|
||||
}
|
||||
|
||||
static void writeHost (MemoryOutputStream& dest, const bool isPost, const String& path, const String& host, const int port)
|
||||
{
|
||||
dest << (isPost ? "POST " : "GET ") << path << " HTTP/1.0\r\nHost: " << host;
|
||||
|
||||
if (port > 0)
|
||||
dest << ':' << port;
|
||||
}
|
||||
|
||||
static MemoryBlock createRequestHeader (const String& hostName, const int hostPort,
|
||||
const String& proxyName, const int proxyPort,
|
||||
const String& hostPath, const String& originalURL,
|
||||
const String& userHeaders, const MemoryBlock& postData,
|
||||
const bool isPost)
|
||||
{
|
||||
MemoryOutputStream header;
|
||||
|
||||
if (proxyName.isEmpty())
|
||||
writeHost (header, isPost, hostPath, hostName, hostPort);
|
||||
else
|
||||
writeHost (header, isPost, originalURL, proxyName, proxyPort);
|
||||
|
||||
writeValueIfNotPresent (header, userHeaders, "User-Agent:", "BEAST/" BEAST_STRINGIFY(BEAST_MAJOR_VERSION)
|
||||
"." BEAST_STRINGIFY(BEAST_MINOR_VERSION)
|
||||
"." BEAST_STRINGIFY(BEAST_BUILDNUMBER));
|
||||
writeValueIfNotPresent (header, userHeaders, "Connection:", "Close");
|
||||
|
||||
if (isPost)
|
||||
writeValueIfNotPresent (header, userHeaders, "Content-Length:", String ((int) postData.getSize()));
|
||||
|
||||
header << "\r\n" << userHeaders
|
||||
<< "\r\n" << postData;
|
||||
|
||||
return header.getMemoryBlock();
|
||||
}
|
||||
|
||||
static bool sendHeader (int socketHandle, const MemoryBlock& requestHeader, const uint32 timeOutTime,
|
||||
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext)
|
||||
{
|
||||
size_t totalHeaderSent = 0;
|
||||
|
||||
while (totalHeaderSent < requestHeader.getSize())
|
||||
{
|
||||
if (Time::getMillisecondCounter() > timeOutTime)
|
||||
return false;
|
||||
|
||||
const int numToSend = bmin (1024, (int) (requestHeader.getSize() - totalHeaderSent));
|
||||
|
||||
if (send (socketHandle, static_cast <const char*> (requestHeader.getData()) + totalHeaderSent, numToSend, 0) != numToSend)
|
||||
return false;
|
||||
|
||||
totalHeaderSent += numToSend;
|
||||
|
||||
if (progressCallback != nullptr && ! progressCallback (progressCallbackContext, totalHeaderSent, requestHeader.getSize()))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool decomposeURL (const String& url, String& host, String& path, int& port)
|
||||
{
|
||||
if (! url.startsWithIgnoreCase ("http://"))
|
||||
return false;
|
||||
|
||||
const int nextSlash = url.indexOfChar (7, '/');
|
||||
int nextColon = url.indexOfChar (7, ':');
|
||||
if (nextColon > nextSlash && nextSlash > 0)
|
||||
nextColon = -1;
|
||||
|
||||
if (nextColon >= 0)
|
||||
{
|
||||
host = url.substring (7, nextColon);
|
||||
|
||||
if (nextSlash >= 0)
|
||||
port = url.substring (nextColon + 1, nextSlash).getIntValue();
|
||||
else
|
||||
port = url.substring (nextColon + 1).getIntValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
port = 80;
|
||||
|
||||
if (nextSlash >= 0)
|
||||
host = url.substring (7, nextSlash);
|
||||
else
|
||||
host = url.substring (7);
|
||||
}
|
||||
|
||||
if (nextSlash >= 0)
|
||||
path = url.substring (nextSlash);
|
||||
else
|
||||
path = "/";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static String findHeaderItem (const StringArray& lines, const String& itemName)
|
||||
{
|
||||
for (int i = 0; i < lines.size(); ++i)
|
||||
if (lines[i].startsWithIgnoreCase (itemName))
|
||||
return lines[i].substring (itemName.length()).trim();
|
||||
|
||||
return String::empty;
|
||||
}
|
||||
|
||||
BEAST_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)
|
||||
};
|
||||
|
||||
InputStream* URL::createNativeStream (const String& address, bool isPost, const MemoryBlock& postData,
|
||||
OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
|
||||
const String& headers, const int timeOutMs, StringPairArray* responseHeaders)
|
||||
{
|
||||
ScopedPointer <WebInputStream> wi (new WebInputStream (address, isPost, postData,
|
||||
progressCallback, progressCallbackContext,
|
||||
headers, timeOutMs, responseHeaders));
|
||||
|
||||
return wi->isError() ? nullptr : wi.release();
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Portions of this file are from JUCE.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
Please visit http://www.juce.com
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
// sysinfo() from sysinfo-bsd
|
||||
// https://code.google.com/p/sysinfo-bsd/
|
||||
/*
|
||||
* Copyright (C) 2010 Kostas Petrikas, All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name(s) of the author(s) may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#define SI_LOAD_SHIFT 16
|
||||
struct sysinfo {
|
||||
long uptime; /* Seconds since boot */
|
||||
unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
|
||||
unsigned long totalram; /* Total usable main memory size */
|
||||
unsigned long freeram; /* Available memory size */
|
||||
unsigned long sharedram; /* Amount of shared memory */
|
||||
unsigned long bufferram; /* Memory used by buffers */
|
||||
unsigned long totalswap; /* Total swap space size */
|
||||
unsigned long freeswap; /* swap space still available */
|
||||
unsigned short procs; /* Number of current processes */
|
||||
unsigned short pad; /* leaving this for linux compatability */
|
||||
unsigned long totalhigh; /* Total high memory size */
|
||||
unsigned long freehigh; /* Available high memory size */
|
||||
unsigned int mem_unit; /* Memory unit size in bytes */
|
||||
char _f[20-2*sizeof(long)-sizeof(int)]; /* leaving this for linux compatability */
|
||||
};
|
||||
|
||||
#define NLOADS 3
|
||||
#define UNIT_S 1024 /*Kb*/
|
||||
#define R_IGNORE -1
|
||||
|
||||
/*the macros*/
|
||||
#define R_ERROR(_EC) {if(_EC > R_IGNORE)errno = _EC; return -1;}
|
||||
#define GETSYSCTL(name, var) getsysctl((char*)name, &(var), sizeof(var))
|
||||
#define PAGE_2_UNIT(_PAGE) (((double)_PAGE * page_s) / UNIT_S)
|
||||
|
||||
/*sysctl wrapper*/
|
||||
static int getsysctl(char *name, void *ptr, size_t len){
|
||||
size_t nlen = len;
|
||||
if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1)
|
||||
return -1;
|
||||
|
||||
if (nlen != len)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sysinfo(struct sysinfo *info){
|
||||
kvm_t *kvmh;
|
||||
double load_avg[NLOADS];
|
||||
int page_s = getpagesize();
|
||||
|
||||
if (info == NULL)
|
||||
R_ERROR(EFAULT);
|
||||
|
||||
memset(info, 0, sizeof(struct sysinfo));
|
||||
info -> mem_unit = UNIT_S;
|
||||
|
||||
/*kvm init*/
|
||||
if ((kvmh = kvm_open(NULL, "/dev/null", "/dev/null",
|
||||
O_RDONLY, "kvm_open")) == NULL)
|
||||
R_ERROR(0);
|
||||
|
||||
/*load averages*/
|
||||
if (kvm_getloadavg(kvmh, load_avg, NLOADS) == -1)
|
||||
R_ERROR(0);
|
||||
|
||||
info -> loads[0] = (u_long)((float)load_avg[0] * USHRT_MAX);
|
||||
info -> loads[1] = (u_long)((float)load_avg[1] * USHRT_MAX);
|
||||
info -> loads[2] = (u_long)((float)load_avg[2] * USHRT_MAX);
|
||||
|
||||
/*swap space*/
|
||||
struct kvm_swap k_swap;
|
||||
|
||||
if (kvm_getswapinfo(kvmh, &k_swap, 1, 0) == -1)
|
||||
R_ERROR(0);
|
||||
|
||||
info -> totalswap =
|
||||
(u_long)PAGE_2_UNIT(k_swap.ksw_total);
|
||||
info -> freeswap = info -> totalswap -
|
||||
(u_long)PAGE_2_UNIT(k_swap.ksw_used);
|
||||
|
||||
/*processes*/
|
||||
int n_procs;
|
||||
|
||||
if (kvm_getprocs(kvmh, KERN_PROC_ALL, 0, &n_procs) == NULL)
|
||||
R_ERROR(0);
|
||||
|
||||
info -> procs = (u_short)n_procs;
|
||||
|
||||
/*end of kvm session*/
|
||||
if (kvm_close(kvmh) == -1)
|
||||
R_ERROR(0);
|
||||
|
||||
/*uptime*/
|
||||
struct timespec ts;
|
||||
|
||||
if (clock_gettime(CLOCK_UPTIME, &ts) == -1)
|
||||
R_ERROR(R_IGNORE);
|
||||
|
||||
info -> uptime = (long)ts.tv_sec;
|
||||
|
||||
/*ram*/
|
||||
int total_pages,
|
||||
free_pages,
|
||||
active_pages,
|
||||
inactive_pages;
|
||||
u_long shmmax;
|
||||
|
||||
if (GETSYSCTL("vm.stats.vm.v_page_count", total_pages) == -1)
|
||||
R_ERROR(R_IGNORE);
|
||||
if (GETSYSCTL("vm.stats.vm.v_free_count", free_pages) == -1)
|
||||
R_ERROR(R_IGNORE);
|
||||
if (GETSYSCTL("vm.stats.vm.v_active_count", active_pages) == -1)
|
||||
R_ERROR(R_IGNORE);
|
||||
if (GETSYSCTL("vm.stats.vm.v_inactive_count", inactive_pages) == -1)
|
||||
R_ERROR(R_IGNORE);
|
||||
if (GETSYSCTL("kern.ipc.shmmax", shmmax) == -1)
|
||||
R_ERROR(R_IGNORE);
|
||||
|
||||
info -> totalram = (u_long)PAGE_2_UNIT(total_pages);
|
||||
info -> freeram = (u_long)PAGE_2_UNIT(free_pages);
|
||||
info -> bufferram = (u_long)PAGE_2_UNIT(active_pages);
|
||||
info -> sharedram = shmmax / UNIT_S;
|
||||
|
||||
/*high mem (todo)*/
|
||||
info -> totalhigh = 0; /*Does this supose to refer to HMA or reserved ram?*/
|
||||
info -> freehigh = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
void Logger::outputDebugString (const String& text)
|
||||
{
|
||||
std::cerr << text << std::endl;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
SystemStats::OperatingSystemType SystemStats::getOperatingSystemType()
|
||||
{
|
||||
return FreeBSD;
|
||||
}
|
||||
|
||||
String SystemStats::getOperatingSystemName()
|
||||
{
|
||||
return "FreeBSD";
|
||||
}
|
||||
|
||||
bool SystemStats::isOperatingSystem64Bit()
|
||||
|
||||
{
|
||||
#if BEAST_64BIT
|
||||
return true;
|
||||
#else
|
||||
//xxx not sure how to find this out?..
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
namespace BSDStatsHelpers
|
||||
{
|
||||
String getCpuInfo (const char* const key)
|
||||
{
|
||||
StringArray lines;
|
||||
File ("/proc/cpuinfo").readLines (lines);
|
||||
|
||||
for (int i = lines.size(); --i >= 0;) // (NB - it's important that this runs in reverse order)
|
||||
if (lines[i].startsWithIgnoreCase (key))
|
||||
return lines[i].fromFirstOccurrenceOf (":", false, false).trim();
|
||||
|
||||
return String::empty;
|
||||
}
|
||||
}
|
||||
|
||||
String SystemStats::getCpuVendor()
|
||||
{
|
||||
return BSDStatsHelpers::getCpuInfo ("vendor_id");
|
||||
}
|
||||
|
||||
int SystemStats::getCpuSpeedInMegaherz()
|
||||
{
|
||||
return roundToInt (BSDStatsHelpers::getCpuInfo ("cpu MHz").getFloatValue());
|
||||
}
|
||||
|
||||
int SystemStats::getMemorySizeInMegabytes()
|
||||
{
|
||||
struct sysinfo sysi;
|
||||
|
||||
if (sysinfo (&sysi) == 0)
|
||||
return (sysi.totalram * sysi.mem_unit / (1024 * 1024));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SystemStats::getPageSize()
|
||||
{
|
||||
return sysconf (_SC_PAGESIZE);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
String SystemStats::getLogonName()
|
||||
{
|
||||
const char* user = getenv ("USER");
|
||||
|
||||
if (user == nullptr)
|
||||
{
|
||||
struct passwd* const pw = getpwuid (getuid());
|
||||
if (pw != nullptr)
|
||||
user = pw->pw_name;
|
||||
}
|
||||
|
||||
return CharPointer_UTF8 (user);
|
||||
}
|
||||
|
||||
String SystemStats::getFullUserName()
|
||||
{
|
||||
return getLogonName();
|
||||
}
|
||||
|
||||
String SystemStats::getComputerName()
|
||||
{
|
||||
char name [256] = { 0 };
|
||||
if (gethostname (name, sizeof (name) - 1) == 0)
|
||||
return name;
|
||||
|
||||
return String::empty;
|
||||
}
|
||||
|
||||
String getLocaleValue (nl_item key)
|
||||
{
|
||||
const char* oldLocale = ::setlocale (LC_ALL, "");
|
||||
return String (const_cast <const char*> (nl_langinfo (key)));
|
||||
::setlocale (LC_ALL, oldLocale);
|
||||
}
|
||||
|
||||
String SystemStats::getUserLanguage()
|
||||
{
|
||||
return "Uknown user language";
|
||||
}
|
||||
|
||||
String SystemStats::getUserRegion()
|
||||
{
|
||||
return "Unknown user region";
|
||||
}
|
||||
|
||||
String SystemStats::getDisplayLanguage()
|
||||
{
|
||||
return getUserLanguage();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
SystemStats::CPUFlags::CPUFlags()
|
||||
{
|
||||
const String flags (BSDStatsHelpers::getCpuInfo ("flags"));
|
||||
hasMMX = flags.contains ("mmx");
|
||||
hasSSE = flags.contains ("sse");
|
||||
hasSSE2 = flags.contains ("sse2");
|
||||
has3DNow = flags.contains ("3dnow");
|
||||
|
||||
numCpus = BSDStatsHelpers::getCpuInfo ("processor").getIntValue() + 1;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
uint32 beast_millisecondsSinceStartup() noexcept
|
||||
{
|
||||
timespec t;
|
||||
clock_gettime (CLOCK_MONOTONIC, &t);
|
||||
|
||||
return t.tv_sec * 1000 + t.tv_nsec / 1000000;
|
||||
}
|
||||
|
||||
int64 Time::getHighResolutionTicks() noexcept
|
||||
{
|
||||
timespec t;
|
||||
clock_gettime (CLOCK_MONOTONIC, &t);
|
||||
|
||||
return (t.tv_sec * (int64) 1000000) + (t.tv_nsec / 1000);
|
||||
}
|
||||
|
||||
int64 Time::getHighResolutionTicksPerSecond() noexcept
|
||||
{
|
||||
return 1000000; // (microseconds)
|
||||
}
|
||||
|
||||
double Time::getMillisecondCounterHiRes() noexcept
|
||||
{
|
||||
return getHighResolutionTicks() * 0.001;
|
||||
}
|
||||
|
||||
bool Time::setSystemTimeToThisTime() const
|
||||
{
|
||||
timeval t;
|
||||
t.tv_sec = millisSinceEpoch / 1000;
|
||||
t.tv_usec = (millisSinceEpoch - t.tv_sec * 1000) * 1000;
|
||||
|
||||
return settimeofday (&t, 0) == 0;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Portions of this file are from JUCE.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
Please visit http://www.juce.com
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/*
|
||||
Note that a lot of methods that you'd expect to find in this file actually
|
||||
live in beast_posix_SharedCode.h!
|
||||
*/
|
||||
|
||||
//==============================================================================
|
||||
void Process::setPriority (const ProcessPriority prior)
|
||||
{
|
||||
const int policy = (prior <= NormalPriority) ? SCHED_OTHER : SCHED_RR;
|
||||
const int minp = sched_get_priority_min (policy);
|
||||
const int maxp = sched_get_priority_max (policy);
|
||||
|
||||
struct sched_param param;
|
||||
|
||||
switch (prior)
|
||||
{
|
||||
case LowPriority:
|
||||
case NormalPriority: param.sched_priority = 0; break;
|
||||
case HighPriority: param.sched_priority = minp + (maxp - minp) / 4; break;
|
||||
case RealtimePriority: param.sched_priority = minp + (3 * (maxp - minp) / 4); break;
|
||||
default: bassertfalse; break;
|
||||
}
|
||||
|
||||
pthread_setschedparam (pthread_self(), policy, ¶m);
|
||||
}
|
||||
|
||||
void Process::terminate()
|
||||
{
|
||||
exit (0);
|
||||
}
|
||||
|
||||
BEAST_API bool BEAST_CALLTYPE beast_isRunningUnderDebugger()
|
||||
{
|
||||
static char testResult = 0;
|
||||
|
||||
if (testResult == 0)
|
||||
{
|
||||
testResult = (char) ptrace (PT_TRACE_ME, 0, 0, 0);
|
||||
|
||||
if (testResult >= 0)
|
||||
{
|
||||
ptrace (PT_DETACH, 0, (caddr_t) 1, 0);
|
||||
testResult = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return testResult < 0;
|
||||
}
|
||||
|
||||
BEAST_API bool BEAST_CALLTYPE Process::isRunningUnderDebugger()
|
||||
{
|
||||
return beast_isRunningUnderDebugger();
|
||||
}
|
||||
|
||||
static void swapUserAndEffectiveUser()
|
||||
{
|
||||
(void) setreuid (geteuid(), getuid());
|
||||
(void) setregid (getegid(), getgid());
|
||||
}
|
||||
|
||||
void Process::raisePrivilege() { if (geteuid() != 0 && getuid() == 0) swapUserAndEffectiveUser(); }
|
||||
void Process::lowerPrivilege() { if (geteuid() == 0 && getuid() != 0) swapUserAndEffectiveUser(); }
|
||||
@@ -27,7 +27,7 @@
|
||||
//==============================================================================
|
||||
/** Current BEAST version number.
|
||||
|
||||
See also SystemStats::getBEASTVersion() for a string version.
|
||||
See also SystemStats::getBeastVersion() for a string version.
|
||||
*/
|
||||
#define BEAST_MAJOR_VERSION 0
|
||||
#define BEAST_MINOR_VERSION 0
|
||||
@@ -39,7 +39,7 @@
|
||||
Bits 8 to 16 = minor version.
|
||||
Bits 0 to 8 = point release.
|
||||
|
||||
See also SystemStats::getBEASTVersion() for a string version.
|
||||
See also SystemStats::getBeastVersion() for a string version.
|
||||
*/
|
||||
#define BEAST_VERSION ((BEAST_MAJOR_VERSION << 16) + (BEAST_MINOR_VERSION << 8) + BEAST_BUILDNUMBER)
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ const SystemStats::CPUFlags& SystemStats::getCPUFlags()
|
||||
return cpuFlags;
|
||||
}
|
||||
|
||||
String SystemStats::getBEASTVersion()
|
||||
String SystemStats::getBeastVersion()
|
||||
{
|
||||
// Some basic tests, to keep an eye on things and make sure these types work ok
|
||||
// on all platforms. Let me know if any of these assertions fail on your system!
|
||||
@@ -41,7 +41,7 @@ String SystemStats::getBEASTVersion()
|
||||
static_bassert (sizeof (int64) == 8);
|
||||
static_bassert (sizeof (uint64) == 8);
|
||||
|
||||
return "BEAST v" BEAST_STRINGIFY(BEAST_MAJOR_VERSION)
|
||||
return "Beast v" BEAST_STRINGIFY(BEAST_MAJOR_VERSION)
|
||||
"." BEAST_STRINGIFY(BEAST_MINOR_VERSION)
|
||||
"." BEAST_STRINGIFY(BEAST_BUILDNUMBER);
|
||||
}
|
||||
@@ -55,7 +55,7 @@ String SystemStats::getBEASTVersion()
|
||||
{
|
||||
BeastVersionPrinter()
|
||||
{
|
||||
DBG (SystemStats::getBEASTVersion());
|
||||
DBG (SystemStats::getBeastVersion());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
|
||||
#include "../text/beast_StringArray.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Contains methods for finding out about the current hardware and OS configuration.
|
||||
@@ -38,7 +37,7 @@ public:
|
||||
/** Returns the current version of BEAST,
|
||||
See also the BEAST_VERSION, BEAST_MAJOR_VERSION and BEAST_MINOR_VERSION macros.
|
||||
*/
|
||||
static String getBEASTVersion();
|
||||
static String getBeastVersion();
|
||||
|
||||
//==============================================================================
|
||||
/** The set of possible results of the getOperatingSystemType() method. */
|
||||
@@ -46,16 +45,16 @@ public:
|
||||
{
|
||||
UnknownOS = 0,
|
||||
|
||||
Linux = 0x2000,
|
||||
Android = 0x3000,
|
||||
iOS = 0x8000,
|
||||
|
||||
MacOSX_10_4 = 0x1004,
|
||||
MacOSX_10_5 = 0x1005,
|
||||
MacOSX_10_6 = 0x1006,
|
||||
MacOSX_10_7 = 0x1007,
|
||||
MacOSX_10_8 = 0x1008,
|
||||
|
||||
Linux = 0x2000,
|
||||
FreeBSD = 0x2001,
|
||||
Android = 0x3000,
|
||||
|
||||
Win2000 = 0x4105,
|
||||
WinXP = 0x4106,
|
||||
WinVista = 0x4107,
|
||||
@@ -64,6 +63,8 @@ public:
|
||||
|
||||
Windows = 0x4000, /**< To test whether any version of Windows is running,
|
||||
you can use the expression ((getOperatingSystemType() & Windows) != 0). */
|
||||
|
||||
iOS = 0x8000
|
||||
};
|
||||
|
||||
/** Returns the type of operating system we're running on.
|
||||
|
||||
Reference in New Issue
Block a user