summaryrefslogtreecommitdiffstats
path: root/xmrstak/jconf.cpp
diff options
context:
space:
mode:
authorpsychocrypt <psychocrypt@users.noreply.github.com>2017-09-29 20:32:31 +0200
committerpsychocrypt <psychocrypt@users.noreply.github.com>2017-09-30 23:46:08 +0200
commitcc429b68fadc502b981fd0acd64a5ff6e2ae1d15 (patch)
tree3fb23fc4db15dbdd08af4c7ea20134b9d82e58fd /xmrstak/jconf.cpp
parente5b0319d5a9f58762fa934ad700113908940cb31 (diff)
downloadxmr-stak-cc429b68fadc502b981fd0acd64a5ff6e2ae1d15.zip
xmr-stak-cc429b68fadc502b981fd0acd64a5ff6e2ae1d15.tar.gz
group files
- move source code to `src` - categorize files and move to group folder - change upper case class files to lower case - change C++ header to `*.hpp`
Diffstat (limited to 'xmrstak/jconf.cpp')
-rw-r--r--xmrstak/jconf.cpp412
1 files changed, 412 insertions, 0 deletions
diff --git a/xmrstak/jconf.cpp b/xmrstak/jconf.cpp
new file mode 100644
index 0000000..bfa2626
--- /dev/null
+++ b/xmrstak/jconf.cpp
@@ -0,0 +1,412 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Additional permission under GNU GPL version 3 section 7
+ *
+ * If you modify this Program, or any covered work, by linking or combining
+ * it with OpenSSL (or a modified version of that library), containing parts
+ * covered by the terms of OpenSSL License and SSLeay License, the licensors
+ * of this Program grant you additional permission to convey the resulting work.
+ *
+ */
+
+#include "jconf.h"
+#include "console.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _WIN32
+#define strcasecmp _stricmp
+#include <intrin.h>
+#else
+#include <cpuid.h>
+#endif
+
+#include "rapidjson/document.h"
+#include "rapidjson/error/en.h"
+#include "jext.h"
+#include "console.h"
+#include "Params.hpp"
+
+using namespace rapidjson;
+
+/*
+ * This enum needs to match index in oConfigValues, otherwise we will get a runtime error
+ */
+enum configEnum {
+ bTlsMode, bTlsSecureAlgo, sTlsFingerprint, sPoolAddr, sWalletAddr, sPoolPwd,
+ iCallTimeout, iNetRetry, iGiveUpLimit, iVerboseLevel, iAutohashTime,
+ bDaemonMode, sOutputFile, iHttpdPort, bPreferIpv4, bNiceHashMode, bAesOverride, sUseSlowMem };
+
+struct configVal {
+ configEnum iName;
+ const char* sName;
+ Type iType;
+};
+
+// Same order as in configEnum, as per comment above
+// kNullType means any type
+configVal oConfigValues[] = {
+ { bTlsMode, "use_tls", kTrueType },
+ { bTlsSecureAlgo, "tls_secure_algo", kTrueType },
+ { sTlsFingerprint, "tls_fingerprint", kStringType },
+ { sPoolAddr, "pool_address", kStringType },
+ { sWalletAddr, "wallet_address", kStringType },
+ { sPoolPwd, "pool_password", kStringType },
+ { iCallTimeout, "call_timeout", kNumberType },
+ { iNetRetry, "retry_time", kNumberType },
+ { iGiveUpLimit, "giveup_limit", kNumberType },
+ { iVerboseLevel, "verbose_level", kNumberType },
+ { iAutohashTime, "h_print_time", kNumberType },
+ { bDaemonMode, "daemon_mode", kTrueType },
+ { sOutputFile, "output_file", kStringType },
+ { iHttpdPort, "httpd_port", kNumberType },
+ { bPreferIpv4, "prefer_ipv4", kTrueType },
+ { bNiceHashMode, "nicehash_nonce", kTrueType },
+ { bAesOverride, "aes_override", kNullType },
+ { sUseSlowMem, "use_slow_memory", kStringType }
+};
+
+constexpr size_t iConfigCnt = (sizeof(oConfigValues)/sizeof(oConfigValues[0]));
+
+inline bool checkType(Type have, Type want)
+{
+ if(want == have)
+ return true;
+ else if(want == kNullType)
+ return true;
+ else if(want == kTrueType && have == kFalseType)
+ return true;
+ else if(want == kFalseType && have == kTrueType)
+ return true;
+ else
+ return false;
+}
+
+struct jconf::opaque_private
+{
+ Document jsonDoc;
+ const Value* configValues[iConfigCnt]; //Compile time constant
+
+ opaque_private()
+ {
+ }
+};
+
+jconf::jconf()
+{
+ prv = new opaque_private();
+}
+
+bool jconf::GetTlsSetting()
+{
+ return prv->configValues[bTlsMode]->GetBool();
+}
+
+bool jconf::TlsSecureAlgos()
+{
+ return prv->configValues[bTlsSecureAlgo]->GetBool();
+}
+
+const char* jconf::GetTlsFingerprint()
+{
+ return prv->configValues[sTlsFingerprint]->GetString();
+}
+
+const char* jconf::GetPoolAddress()
+{
+ auto& poolURL = xmrstak::Params::inst().poolURL;
+ if(poolURL.empty())
+ poolURL = prv->configValues[sPoolAddr]->GetString();
+ return poolURL.c_str();
+}
+
+const char* jconf::GetPoolPwd()
+{
+ auto& poolPasswd = xmrstak::Params::inst().poolPasswd;
+ if(poolPasswd.empty())
+ poolPasswd = prv->configValues[sPoolPwd]->GetString();
+ return poolPasswd.c_str();
+
+}
+
+const char* jconf::GetWalletAddress()
+{
+ auto& poolUsername = xmrstak::Params::inst().poolUsername;
+ if(poolUsername.empty())
+ poolUsername = prv->configValues[sWalletAddr]->GetString();
+ return poolUsername.c_str();
+}
+
+bool jconf::PreferIpv4()
+{
+ return prv->configValues[bPreferIpv4]->GetBool();
+}
+
+uint64_t jconf::GetCallTimeout()
+{
+ return prv->configValues[iCallTimeout]->GetUint64();
+}
+
+uint64_t jconf::GetNetRetry()
+{
+ return prv->configValues[iNetRetry]->GetUint64();
+}
+
+uint64_t jconf::GetGiveUpLimit()
+{
+ return prv->configValues[iGiveUpLimit]->GetUint64();
+}
+
+uint64_t jconf::GetVerboseLevel()
+{
+ return prv->configValues[iVerboseLevel]->GetUint64();
+}
+
+uint64_t jconf::GetAutohashTime()
+{
+ return prv->configValues[iAutohashTime]->GetUint64();
+}
+
+uint16_t jconf::GetHttpdPort()
+{
+ return prv->configValues[iHttpdPort]->GetUint();
+}
+
+bool jconf::DaemonMode()
+{
+ return prv->configValues[bDaemonMode]->GetBool();
+}
+
+const char* jconf::GetOutputFile()
+{
+ return prv->configValues[sOutputFile]->GetString();
+}
+
+bool jconf::NiceHashMode()
+{
+ return prv->configValues[bNiceHashMode]->GetBool();
+}
+
+
+void jconf::cpuid(uint32_t eax, int32_t ecx, int32_t val[4])
+{
+ memset(val, 0, sizeof(int32_t)*4);
+
+#ifdef _WIN32
+ __cpuidex(val, eax, ecx);
+#else
+ __cpuid_count(eax, ecx, val[0], val[1], val[2], val[3]);
+#endif
+}
+
+bool jconf::check_cpu_features()
+{
+ constexpr int AESNI_BIT = 1 << 25;
+ constexpr int SSE2_BIT = 1 << 26;
+ int32_t cpu_info[4];
+ bool bHaveSse2;
+
+ cpuid(1, 0, cpu_info);
+
+ bHaveAes = (cpu_info[2] & AESNI_BIT) != 0;
+ bHaveSse2 = (cpu_info[3] & SSE2_BIT) != 0;
+
+ return bHaveSse2;
+}
+
+jconf::slow_mem_cfg jconf::GetSlowMemSetting()
+{
+ const char* opt = prv->configValues[sUseSlowMem]->GetString();
+
+ if(strcasecmp(opt, "always") == 0)
+ return always_use;
+ else if(strcasecmp(opt, "no_mlck") == 0)
+ return no_mlck;
+ else if(strcasecmp(opt, "warn") == 0)
+ return print_warning;
+ else if(strcasecmp(opt, "never") == 0)
+ return never_use;
+ else
+ return unknown_value;
+}
+
+bool jconf::parse_config(const char* sFilename)
+{
+ FILE * pFile;
+ char * buffer;
+ size_t flen;
+
+ if(!check_cpu_features())
+ {
+ printer::inst()->print_msg(L0, "CPU support of SSE2 is required.");
+ return false;
+ }
+
+ pFile = fopen(sFilename, "rb");
+ if (pFile == NULL)
+ {
+ printer::inst()->print_msg(L0, "Failed to open config file %s.", sFilename);
+ return false;
+ }
+
+ fseek(pFile,0,SEEK_END);
+ flen = ftell(pFile);
+ rewind(pFile);
+
+ if(flen >= 64*1024)
+ {
+ fclose(pFile);
+ printer::inst()->print_msg(L0, "Oversized config file - %s.", sFilename);
+ return false;
+ }
+
+ if(flen <= 16)
+ {
+ fclose(pFile);
+ printer::inst()->print_msg(L0, "File is empty or too short - %s.", sFilename);
+ return false;
+ }
+
+ buffer = (char*)malloc(flen + 3);
+ if(fread(buffer+1, flen, 1, pFile) != 1)
+ {
+ free(buffer);
+ fclose(pFile);
+ printer::inst()->print_msg(L0, "Read error while reading %s.", sFilename);
+ return false;
+ }
+ fclose(pFile);
+
+ //Replace Unicode BOM with spaces - we always use UTF-8
+ unsigned char* ubuffer = (unsigned char*)buffer;
+ if(ubuffer[1] == 0xEF && ubuffer[2] == 0xBB && ubuffer[3] == 0xBF)
+ {
+ buffer[1] = ' ';
+ buffer[2] = ' ';
+ buffer[3] = ' ';
+ }
+
+ buffer[0] = '{';
+ buffer[flen] = '}';
+ buffer[flen + 1] = '\0';
+
+ prv->jsonDoc.Parse<kParseCommentsFlag|kParseTrailingCommasFlag>(buffer, flen+2);
+ free(buffer);
+
+ if(prv->jsonDoc.HasParseError())
+ {
+ printer::inst()->print_msg(L0, "JSON config parse error(offset %llu): %s",
+ int_port(prv->jsonDoc.GetErrorOffset()), GetParseError_En(prv->jsonDoc.GetParseError()));
+ return false;
+ }
+
+
+ if(!prv->jsonDoc.IsObject())
+ { //This should never happen as we created the root ourselves
+ printer::inst()->print_msg(L0, "Invalid config file. No root?\n");
+ return false;
+ }
+
+ for(size_t i = 0; i < iConfigCnt; i++)
+ {
+ if(oConfigValues[i].iName != i)
+ {
+ printer::inst()->print_msg(L0, "Code error. oConfigValues are not in order.");
+ return false;
+ }
+
+ prv->configValues[i] = GetObjectMember(prv->jsonDoc, oConfigValues[i].sName);
+
+ if(prv->configValues[i] == nullptr)
+ {
+ printer::inst()->print_msg(L0, "Invalid config file. Missing value \"%s\".", oConfigValues[i].sName);
+ return false;
+ }
+
+ if(!checkType(prv->configValues[i]->GetType(), oConfigValues[i].iType))
+ {
+ printer::inst()->print_msg(L0, "Invalid config file. Value \"%s\" has unexpected type.", oConfigValues[i].sName);
+ return false;
+ }
+ }
+
+ if(!prv->configValues[iCallTimeout]->IsUint64() ||
+ !prv->configValues[iNetRetry]->IsUint64() ||
+ !prv->configValues[iGiveUpLimit]->IsUint64())
+ {
+ printer::inst()->print_msg(L0,
+ "Invalid config file. call_timeout, retry_time and giveup_limit need to be positive integers.");
+ return false;
+ }
+
+ if(!prv->configValues[iVerboseLevel]->IsUint64() || !prv->configValues[iAutohashTime]->IsUint64())
+ {
+ printer::inst()->print_msg(L0,
+ "Invalid config file. verbose_level and h_print_time need to be positive integers.");
+ return false;
+ }
+
+ if(!prv->configValues[iHttpdPort]->IsUint() || prv->configValues[iHttpdPort]->GetUint() > 0xFFFF)
+ {
+ printer::inst()->print_msg(L0,
+ "Invalid config file. httpd_port has to be in the range 0 to 65535.");
+ return false;
+ }
+
+#ifdef CONF_NO_TLS
+ if(prv->configValues[bTlsMode]->GetBool())
+ {
+ printer::inst()->print_msg(L0,
+ "Invalid config file. TLS enabled while the application has been compiled without TLS support.");
+ return false;
+ }
+#endif // CONF_NO_TLS
+
+ /* \todo check in the cpu backend if we have more than 32 worker
+ * keep in mined that we have change the why how the nonce is calculated (reverse thread index)
+ if(NiceHashMode() && GetThreadCount() >= 32)
+ {
+ printer::inst()->print_msg(L0, "You need to use less than 32 threads in NiceHash mode.");
+ return false;
+ }
+ */
+
+ if(prv->configValues[bAesOverride]->IsBool())
+ bHaveAes = prv->configValues[bAesOverride]->GetBool();
+
+ if(!bHaveAes)
+ printer::inst()->print_msg(L0, "Your CPU doesn't support hardware AES. Don't expect high hashrates.");
+
+ printer::inst()->set_verbose_level(prv->configValues[iVerboseLevel]->GetUint64());
+
+ if(GetSlowMemSetting() == unknown_value)
+ {
+ printer::inst()->print_msg(L0,
+ "Invalid config file. use_slow_memory must be \"always\", \"no_mlck\", \"warn\" or \"never\"");
+ return false;
+ }
+
+#ifdef _WIN32
+ if(GetSlowMemSetting() == no_mlck)
+ {
+ printer::inst()->print_msg(L0, "On Windows large pages need mlock. Please use another option.");
+ return false;
+ }
+#endif // _WIN32
+
+ return true;
+}
OpenPOWER on IntegriCloud