Unverified Commit 7f532eab authored by Stan Kladko's avatar Stan Kladko Committed by GitHub

Merge branch 'develop' into SKALE-2017-automatic-push

parents 9f9b63a9 1cff9656
......@@ -50,7 +50,7 @@
#include "RPCException.h"
#include "spdlog/spdlog.h"
int char2int(char _input) {
if (_input >= '0' && _input <= '9')
......@@ -187,7 +187,9 @@ char *encryptBLSKeyShare2Hex(int *errStatus, char *err_string, const char *_key)
status = encrypt_key(eid, errStatus, errMsg, keyArray, encryptedKey, &encryptedLen);
std::cerr << "errStatus is " << *errStatus << " errMsg is " << errMsg << std::endl;
if (DEBUG_PRINT) {
spdlog::info("errStatus is {}",*errStatus, " errMsg is ", errMsg );
}
if (status != SGX_SUCCESS) {
......
......@@ -11,6 +11,8 @@
#include <jsonrpccpp/server/connectors/httpserver.h>
#include "spdlog/spdlog.h"
CSRManagerServer *cs = nullptr;
jsonrpc::HttpServer *hs3 = nullptr;
......@@ -21,7 +23,7 @@ CSRManagerServer::CSRManagerServer(AbstractServerConnector &connector,
Json::Value GetUnsignedCSRsImpl(){
std::cerr << "Enter GetUnsignedCSRsImpl" << std::endl;
spdlog::info("Enter GetUnsignedCSRsImpl");
Json::Value result;
result["status"] = 0;
result["errorMessage"] = "";
......@@ -70,9 +72,9 @@ Json::Value SignByHashImpl(const std::string& hash, int status){
std::string signClientCert = "cd cert && ./create_client_cert " + hash;
if (system(signClientCert.c_str()) == 0) {
std::cerr << "CLIENT CERTIFICATE IS SUCCESSFULLY GENERATED" << std::endl;
spdlog::info("CLIENT CERTIFICATE IS SUCCESSFULLY GENERATED");
} else {
std::cerr << "CLIENT CERTIFICATE GENERATION FAILED" << std::endl;
spdlog::info("CLIENT CERTIFICATE GENERATION FAILED");
csrDb->deleteKey(csr_db_key);
std::string status_db_key = "CSR:HASH:" + hash + "STATUS:";
csrStatusDb->deleteKey(status_db_key);
......@@ -115,12 +117,11 @@ int init_csrmanager_server(){
cs = new CSRManagerServer(*hs3, JSONRPC_SERVER_V2); // server (json-rpc 2.0)
if (!cs->StartListening()) {
std::cerr << "CSR manager server could not start listening" << std::endl;
spdlog::info("CSR manager server could not start listening");
exit(-1);
}
else {
std::cerr << "CSR manager server started on port " << BASE_PORT + 2 << std::endl;
spdlog::info("CSR manager server started on port {}", BASE_PORT + 2);
}
std::cerr << "CSR manager inited" << std::endl;
return 0;
};
\ No newline at end of file
......@@ -34,6 +34,8 @@
//#include <libBLS/libff/libff/algebra/curves/alt_bn128/alt_bn128_pp.hpp>
#include <libff/algebra/curves/alt_bn128/alt_bn128_pp.hpp>
#include "spdlog/spdlog.h"
std::vector<std::string> SplitString(const char* koefs, const char symbol){
std::string str(koefs);
std::string delim;
......@@ -86,13 +88,13 @@ std::string gen_dkg_poly( int _t){
}
if (DEBUG_PRINT) {
std::cerr << "gen_dkg_secret, status " << err_status << " err msg " << errMsg << std::endl;
spdlog::info("gen_dkg_secret, status {}", err_status, " err msg ", errMsg);
/* std::cerr << "encr raw poly: " << std::endl;
for ( int i = 0 ; i < 3050; i++)
printf(" %d ", encrypted_dkg_secret[i] );*/
std::cerr << "in DKGCrypto encr len is " << enc_len << std::endl;
spdlog::info("in DKGCrypto encr len is {}", enc_len);
}
char *hexEncrPoly = (char *) calloc(DKG_MAX_SEALED_LEN * 2 + 1, 1);//(4*BUF_LEN, 1);
......@@ -116,7 +118,7 @@ std::vector <std::vector<std::string>> get_verif_vect(const char* encryptedPolyH
if (DEBUG_PRINT) {
// std::cerr << "got encr poly " << encryptedPolyHex << std::endl;
std::cerr << "got encr poly size " << strlen(encryptedPolyHex) << std::endl;
spdlog::info("got encr poly size {}", std::char_traits<char>::length(encryptedPolyHex));
}
char* public_shares = (char*)calloc(10000, 1);
......@@ -129,7 +131,7 @@ std::vector <std::vector<std::string>> get_verif_vect(const char* encryptedPolyH
}
if (DEBUG_PRINT) {
std::cerr << "enc len " << enc_len << std::endl;
spdlog::info("enc len {}", enc_len);
/*std::cerr << "encr raw poly: " << std::endl;
for ( int i = 0 ; i < 3050; i++)
printf(" %d ", encr_dkg_poly[i] );*/
......@@ -142,12 +144,14 @@ std::vector <std::vector<std::string>> get_verif_vect(const char* encryptedPolyH
}
if (DEBUG_PRINT) {
std::cerr << "err msg " << errMsg1 << std::endl;
std::cerr << "public_shares:" << std::endl;
std::cerr << public_shares << std::endl;
printf("\nget_public_shares status: %d error %s \n\n", err_status, errMsg1);
spdlog::info("err msg is {}", errMsg1);
spdlog::info("public_shares:");
spdlog::info("{}", public_shares);
// std::cerr << "public_shares:" << std::endl;
// std::cerr << public_shares << std::endl;
spdlog::info("get_public_shares status: {}", err_status);
//printf("\nget_public_shares status: %d error %s \n\n", err_status, errMsg1);
}
std::vector <std::string> G2_strings = SplitString( public_shares, ',');
......@@ -191,7 +195,7 @@ std::string get_secret_shares(const std::string& polyName, const char* encrypted
char s_shareG2[320];
std::string pub_keyB = publicKeys.at(i);//publicKeys.substr(128*i, 128*i + 128);
if (DEBUG_PRINT) {
std::cerr << "pub_keyB is " << pub_keyB << std::endl;
spdlog::info("pub_keyB is {}", pub_keyB);
}
char pubKeyB[129];
strncpy(pubKeyB, pub_keyB.c_str(), 128);
......@@ -206,24 +210,25 @@ std::string get_secret_shares(const std::string& polyName, const char* encrypted
//uint32_t enc_len = BUF_LEN;
if (DEBUG_PRINT) {
std::cerr << "dec len is " << dec_len << std::endl;
spdlog::info("dec len is {}", dec_len);
}
carray2Hex(encrypted_skey, dec_len, hexEncrKey);
std::string DHKey_name = "DKG_DH_KEY_" + polyName + "_" + std::to_string(i) + ":";
std::cerr << "name to write to db is " << DHKey_name << std::endl;
// std::cerr << "hexEncrKey: " << hexEncrKey << std::endl;
writeDataToDB(DHKey_name, hexEncrKey);
std::string shareG2_name = "shareG2_" + polyName + "_" + std::to_string(i) + ":";
if (DEBUG_PRINT) {
std::cerr << "name to write to db is " << shareG2_name << std::endl;
std::cerr << "s_shareG2: " << s_shareG2 << std::endl;
spdlog::info("name to write to db is {}", DHKey_name);
spdlog::info("name to write to db is {}", shareG2_name);
spdlog::info("s_shareG2: {}", s_shareG2);
}
writeDataToDB(shareG2_name, s_shareG2);
if (DEBUG_PRINT) {
std::cerr << errMsg1 << std::endl << std::endl;
spdlog::info("errMsg: {}", errMsg1);
// std::cerr << "iteration " << i <<" result length is " << result.length() << std::endl ;
// std::cerr << "iteration " << i <<" share length is " << strlen(cur_share) << std::endl;
// std::cerr << "iteration " << i <<" share is " << cur_share << std::endl;
......@@ -254,7 +259,7 @@ bool VerifyShares(const char* publicShares, const char* encr_sshare, const char
// std::cerr << "encr_sshare length is " << strlen(encr_sshare) << std::endl; std::cerr << "public shares " << publicShares << std::endl;
std::cerr << "publicShares length is " << std::char_traits<char>::length(publicShares)<<std::endl; //strlen(publicShares)<< std::endl;
spdlog::info("publicShares length is {}", std::char_traits<char>::length(publicShares));
}
char pshares[8193];
strncpy(pshares, publicShares, strlen(publicShares) + 1);
......@@ -267,8 +272,8 @@ bool VerifyShares(const char* publicShares, const char* encr_sshare, const char
}
if (DEBUG_PRINT) {
std::cerr << "errMsg1: " << errMsg1 << std::endl;
std::cerr << "result is " << result << std::endl;
spdlog::info("errMsg1: {}", errMsg1);
spdlog::info("result is: {}", result);
}
free(errMsg1);
......@@ -278,7 +283,7 @@ bool VerifyShares(const char* publicShares, const char* encr_sshare, const char
bool CreateBLSShare( const std::string& BLSKeyName, const char * s_shares, const char * encryptedKeyHex){
if (DEBUG_PRINT) {
std::cerr << "ENTER CreateBLSShare" << std::endl;
spdlog::info("ENTER CreateBLSShare");
}
char* errMsg1 = (char*) calloc(1024,1);
int err_status = 0;
......@@ -296,7 +301,7 @@ bool CreateBLSShare( const std::string& BLSKeyName, const char * s_shares, const
create_bls_key(eid, &err_status, errMsg1, s_shares, encr_key, dec_key_len, encr_bls_key, &enc_bls_len);
//std::cerr << "AFTER create_bls_key IN ENCLAVE er msg is " << errMsg1 << std::endl;
if ( err_status != 0){
std::cerr << "ERROR IN ENCLAVE" << std::endl;
spdlog::info("ERROR IN ENCLAVE");
throw RPCException(ERROR_IN_ENCLAVE, "Create BLS private key failed in enclave");
}
else {
......@@ -307,8 +312,8 @@ bool CreateBLSShare( const std::string& BLSKeyName, const char * s_shares, const
// std::cerr << "BEFORE WRITE BLS KEY TO DB" << std::endl;
writeDataToDB(BLSKeyName, hexBLSKey);
if (DEBUG_PRINT) {
std::cerr << "hexBLSKey length is " << strlen(hexBLSKey) << std::endl;
std::cerr << "bls key " << BLSKeyName << " is " << hexBLSKey << std::endl;
spdlog::info("hexBLSKey length is {}", std::char_traits<char>::length(hexBLSKey));
spdlog::info("bls key {}", BLSKeyName, " is ", hexBLSKey );
}
free(hexBLSKey);
return true;
......@@ -331,7 +336,7 @@ std::vector<std::string> GetBLSPubKey(const char * encryptedKeyHex){
char pub_key[320];
if (DEBUG_PRINT) {
std::cerr << "dec_key_len is " << dec_key_len << std::endl;
spdlog::info("dec_key_len is {}", dec_key_len);
}
get_bls_pub_key(eid, &err_status, errMsg1, encr_key, dec_key_len, pub_key);
if ( err_status != 0){
......@@ -340,10 +345,10 @@ std::vector<std::string> GetBLSPubKey(const char * encryptedKeyHex){
std::vector<std::string> pub_key_vect = SplitString(pub_key, ':');
if (DEBUG_PRINT) {
std::cerr << "errMsg1 is " << errMsg1 << std::endl;
std::cerr << "pub key is" << std::endl;
spdlog::info("errMsg1 is {}", errMsg1);
spdlog::info("pub key is ");
for (int i = 0; i < 4; i++)
std::cerr << pub_key_vect.at(i) << std::endl;
spdlog::info("{}", pub_key_vect.at(i));
}
return pub_key_vect;
}
......@@ -356,7 +361,7 @@ std::string decrypt_DHKey(const std::string& polyName, int ind){
std::string DH_key_name = polyName + "_" + std::to_string(ind) + ":";
std::shared_ptr<std::string> hexEncrKey_ptr = readFromDb(DH_key_name, "DKG_DH_KEY_");
if (DEBUG_PRINT) {
std::cerr << "encr DH key is " << hexEncrKey_ptr << std::endl;
spdlog::info("encr DH key is {}", *hexEncrKey_ptr);
}
char *hexEncrKey = (char *) calloc(2 * BUF_LEN, 1);
......
......@@ -2,6 +2,7 @@ FROM skalenetwork/sgxwallet_base:latest
WORKDIR /usr/src/sdk
RUN autoreconf -vif
RUN libtoolize --force
RUN aclocal
......
......@@ -31,6 +31,8 @@
#include <gmp.h>
#include <random>
#include "spdlog/spdlog.h"
static std::default_random_engine rand_gen((unsigned int) time(0));
......@@ -66,7 +68,7 @@ std::vector<std::string> gen_ecdsa_key(){
unsigned long seed = rand_gen();
if (DEBUG_PRINT) {
std::cerr << "seed is " << seed << std::endl;
spdlog::info("seed is {}", seed);
}
gmp_randstate_t state;
gmp_randinit_default(state);
......@@ -115,9 +117,9 @@ std::string get_ecdsa_pubkey(const char* encryptedKeyHex){
std::string pubKey = std::string(pub_key_x) + std::string(pub_key_y);//concatPubKeyWith0x(pub_key_x, pub_key_y);//
if (DEBUG_PRINT) {
std::cerr << "pubkey is " << pubKey << std::endl;
std::cerr << "pubkey length is " << pubKey.length() << std::endl;
std::cerr << "err str " << errMsg << std::endl;
spdlog::info("pubkey is {}", pubKey);
spdlog::info("pubkey length is {}", pubKey.length());
spdlog::info("err str is {}", errMsg);
}
free(errMsg);
......@@ -143,9 +145,9 @@ std::vector<std::string> ecdsa_sign_hash(const char* encryptedKeyHex, const char
}
if (DEBUG_PRINT) {
std::cerr << "encryptedKeyHex: " << encryptedKeyHex << std::endl;
std::cerr << "HASH: " << hashHex << std::endl;
std::cerr << "encrypted len" << dec_len << std::endl;
spdlog::info("encryptedKeyHex: {}", encryptedKeyHex);
spdlog::info("HASH: {}", hashHex);
spdlog::info("encrypted len: {}", dec_len);
}
status = ecdsa_sign1(eid, &err_status, errMsg, encr_key, ECDSA_ENCR_LEN, (unsigned char*)hashHex, signature_r, signature_s, &signature_v, base );
......@@ -154,12 +156,12 @@ std::vector<std::string> ecdsa_sign_hash(const char* encryptedKeyHex, const char
}
if (DEBUG_PRINT) {
std::cerr << "signature r in ecdsa_sign_hash " << signature_r << std::endl;
std::cerr << "signature s in ecdsa_sign_hash " << signature_s << std::endl;
spdlog::info("signature r in ecdsa_sign_hash: {}", signature_r);
spdlog::info("signature s in ecdsa_sign_hash: {}", signature_s);
}
if ( status != SGX_SUCCESS){
std::cerr << "failed to sign " << std::endl;
spdlog::info(" failed to sign ");
}
signature_vect.at(0) = std::to_string(signature_v);
if ( base == 16) {
......
......@@ -36,6 +36,8 @@
#include "ServerInit.h"
#include "spdlog/spdlog.h"
using namespace leveldb;
......@@ -60,11 +62,9 @@ std::shared_ptr<std::string> LevelDB::readString(const std::string &_key) {
auto status = db->Get(readOptions, _key, &*result);
// if (result == nullptr) {
// throw RPCException(KEY_SHARE_DOES_NOT_EXIST, "Data with this name does not exist");
// }
if (DEBUG_PRINT) {
std::cerr << "key to read from db: " << _key << std::endl;
spdlog::info("key to read from db: {}",_key );
//std::cerr << "key to read from db: " << _key << std::endl;
}
throwExceptionOnError(status);
......@@ -84,7 +84,8 @@ void LevelDB::writeString(const std::string &_key, const std::string &_value) {
throwExceptionOnError(status);
if (DEBUG_PRINT) {
std::cerr << "written key " << _key << std::endl;
spdlog::info("written key: {}",_key );
// std::cerr << "written key " << _key << std::endl;
}
}
......@@ -99,20 +100,10 @@ void LevelDB::deleteDHDKGKey (const std::string &_key) {
throwExceptionOnError(status);
std::cerr << "key deleted " << full_key << std::endl;
}
void LevelDB::deleteOlegKey (const std::string &_key) {
std::lock_guard<std::recursive_mutex> lock(mutex);
std::string full_key = "key" + _key;
auto status = db->Delete(writeOptions, Slice(_key));
throwExceptionOnError(status);
std::cerr << "key deleted " << full_key << std::endl;
if (DEBUG_PRINT) {
spdlog::info("key deleted: {}",full_key );
//std::cerr << "key deleted " << full_key << std::endl;
}
}
void LevelDB::deleteTempNEK(const std::string &_key){
......@@ -140,7 +131,8 @@ void LevelDB::deleteKey(const std::string &_key){
throwExceptionOnError(status);
if (DEBUG_PRINT) {
std::cerr << "key deleted " << _key << std::endl;
spdlog::info("key deleted: {}",_key );
// std::cerr << "key deleted " << _key << std::endl;
}
}
......@@ -221,12 +213,16 @@ void LevelDB::writeDataUnique(const std::string & Name, const std::string &value
auto key = Name;
if (readString(Name) != nullptr) {
std::cerr << "name " << Name << " already exists" << std::endl;
spdlog::info("name {}",Name, " already exists");
// std::cerr << "name " << Name << " already exists" << std::endl;
throw RPCException(KEY_SHARE_ALREADY_EXISTS, "Data with this name already exists");
}
writeString(key, value);
std::cerr << Name << " is written to db " << std::endl;
if (DEBUG_PRINT) {
spdlog::info("{}",Name, " is written to db");
//std::cerr << Name << " is written to db " << std::endl;
}
}
......
......@@ -61,8 +61,6 @@ public:
void deleteDHDKGKey (const std::string &_key);
void deleteOlegKey (const std::string &_key);
void deleteTempNEK (const std::string &_key);
void deleteKey(const std::string &_key);
......
......@@ -43,6 +43,8 @@
#include "SGXRegistrationServer.h"
#include "LevelDB.h"
#include "spdlog/spdlog.h"
int DEBUG_PRINT = 0;
int is_sgx_https = 1;
......@@ -66,7 +68,7 @@ Json::Value SignCertificateImpl(const std::string& csr, bool auto_sign = false){
result["status"] = 0;
result["errorMessage"] = "";
try{
std::cerr << " enter SignCertificateImpl " << std::endl;
spdlog::info("enter SignCertificateImpl");
std::string status = "1";
std::string hash = cryptlite::sha256::hash_hex(csr);
......@@ -87,11 +89,11 @@ Json::Value SignCertificateImpl(const std::string& csr, bool auto_sign = false){
std::string genCert = "cd cert && ./create_client_cert " + hash;
if (system(genCert.c_str()) == 0){
std::cerr << "CLIENT CERTIFICATE IS SUCCESSFULLY GENERATED" << std::endl;
spdlog::info("CLIENT CERTIFICATE IS SUCCESSFULLY GENERATED");
status = "0";
}
else{
std::cerr << "CLIENT CERTIFICATE GENERATION FAILED" << std::endl;
spdlog::info("CLIENT CERTIFICATE GENERATION FAILED");
std::string status_db_key = "CSR:HASH:" + hash + "STATUS:";
csrStatusDb->writeDataUnique(status_db_key, std::to_string(FAIL_TO_CREATE_CERTIFICATE));
throw RPCException(FAIL_TO_CREATE_CERTIFICATE, "CLIENT CERTIFICATE GENERATION FAILED");
......@@ -144,10 +146,12 @@ Json::Value GetSertificateImpl(const std::string& hash){
infile.close();
std::string remove_crt = "cd cert && rm -rf " + hash + ".crt && rm -rf " + hash + ".csr";
if(system(remove_crt.c_str()) == 0){
std::cerr << "cert removed" << std::endl;
//std::cerr << "cert removed" << std::endl;
spdlog::info(" cert removed ");
}
else{
std::cerr << "cert was not removed" << std::endl;
spdlog::info(" cert was not removed ");
}
}
......@@ -167,7 +171,7 @@ Json::Value GetSertificateImpl(const std::string& hash){
Json::Value SGXRegistrationServer::SignCertificate(const std::string& csr){
std::cerr << "Enter SignCertificate " << std::endl;
spdlog::info("Enter SignCertificate ");
lock_guard<recursive_mutex> lock(m);
return SignCertificateImpl(csr, cert_auto_sign);
}
......@@ -208,11 +212,11 @@ int init_registration_server(bool sign_automatically) {
JSONRPC_SERVER_V2, sign_automatically); // hybrid server (json-rpc 1.0 & 2.0)
if (!regs->StartListening()) {
cerr << "Registration server could not start listening" << endl;
spdlog::info("Registration server could not start listening");
exit(-1);
}
else {
cerr << "Registration Server started on port " << BASE_PORT + 1 << endl;
spdlog::info("Registration server started on port {}", BASE_PORT + 1);
}
......
This diff is collapsed.
......@@ -27,6 +27,8 @@
#include <iostream>
#include "spdlog/spdlog.h"
std::vector<std::string> SplitString(const std::string& str, const std::string& delim = ":"){
std::vector<std::string> tokens;
size_t prev = 0, pos = 0;
......@@ -44,15 +46,15 @@ std::vector<std::string> SplitString(const std::string& str, const std::string&
bool checkECDSAKeyName(const std::string& keyName) {
std::vector<std::string> parts = SplitString(keyName);
if (parts.size() != 2) {
std::cerr << "num parts != 2" << std::endl;
spdlog::info("ECDSAKeyName num parts != 2");
return false;
}
if (parts.at(0) != "NEK") {
std::cerr << "key doesn't start from NEK" << std::endl;
spdlog::info("key doesn't start from NEK");
return false;
}
if ( parts.at(1).length() > 64 || parts.at(1).length() < 1){
std::cerr << "wrong key length" << std::endl;
spdlog::info("wrong key length");
return false;
}
......@@ -87,36 +89,36 @@ bool checkHex(const std::string& hex, const uint32_t sizeInBytes){
bool checkName (const std::string& Name, const std::string& prefix){
std::vector<std::string> parts = SplitString(Name);
if ( parts.size() != 7) {
std::cerr << "parts.size() != 7" << std::endl;
spdlog::info("parts.size() != 7");
return false;
}
if ( parts.at(0) != prefix ) {
std::cerr << "parts.at(0) != prefix" << std::endl;
spdlog::info("parts.at(0) != prefix");
return false;
}
if ( parts.at(1) != "SCHAIN_ID"){
std::cerr << "parts.at(1) != SCHAIN_ID" << std::endl;
spdlog::info("parts.at(1) != SCHAIN_ID");
return false;
}
if ( parts.at(3) != "NODE_ID"){
std::cerr << "parts.at(3) != Node_ID" << std::endl;
spdlog::info("parts.at(3) != Node_ID");
return false;
}
if ( parts.at(5) != "DKG_ID"){
std::cerr << "parts.at(1) != DKG_ID" << std::endl;
spdlog::info("parts.at(1) != DKG_ID");
return false;
}
if ( parts.at(2).length() > 78 || parts.at(2).length() < 1){
std::cerr << "parts.at(2).length() > 78" << std::endl;
spdlog::info("parts.at(2).length() > 78");
return false;
}
if (parts.at(4).length() > 5 || parts.at(4).length() < 1){
std::cerr << "parts.at(4).length() > 5" << std::endl;
spdlog::info("parts.at(4).length() > 5");
return false;
}
if ( parts.at(6).length() > 78 || parts.at(6).length() < 1){
std::cerr << "parts.at(6).length() > 78" << std::endl;
spdlog::info("parts.at(6).length() > 78");
return false;
}
......@@ -125,7 +127,7 @@ bool checkName (const std::string& Name, const std::string& prefix){
if ( mpz_set_str(num, parts.at(2).c_str(), 10) == -1){
mpz_clear(num);
std::cerr << "parts.at(2) not num" << std::endl;
spdlog::info("parts.at(2) not num");
return false;
}
mpz_clear(num);
......@@ -133,7 +135,7 @@ bool checkName (const std::string& Name, const std::string& prefix){
if ( mpz_set_str(num, parts.at(4).c_str(), 10) == -1){
mpz_clear(num);
std::cerr << "parts.at(4) not num" << std::endl;
spdlog::info("parts.at(4) not num");
return false;
}
mpz_clear(num);
......@@ -141,7 +143,7 @@ bool checkName (const std::string& Name, const std::string& prefix){
if ( mpz_set_str(num, parts.at(6).c_str(),10) == -1){
mpz_clear(num);
std::cerr << "parts.at(6) not num" << std::endl;
spdlog::info("parts.at(6) not num");
return false;
}
mpz_clear(num);
......
......@@ -54,20 +54,42 @@
#include <iostream>
#include "spdlog/spdlog.h"
#include <sys/types.h>
#include <sys/stat.h>
//#include <system>
void init_daemon() {
libff::init_alt_bn128_params();
struct stat info;
if (stat("SGXData", &info) !=0 ){
spdlog::info("going to create SGXData folder");
if (system("mkdir SGXData") == 0){
spdlog::info("SGXData folder was created");
}
else{
spdlog::info("creating SGXData folder failed");
exit(-1);
}
}
static std::string dbName("./" WALLETDB_NAME);
levelDb = new LevelDB(dbName);
static std::string csr_dbname = "CSR_DB";
static std::string csr_dbname = "SGXData/CSR_DB";
csrDb = new LevelDB(csr_dbname);
static std::string csr_status_dbname = "CSR_STATUS_DB";
static std::string csr_status_dbname = "SGXData/CSR_STATUS_DB";
csrStatusDb = new LevelDB(csr_status_dbname);
std::shared_ptr<std::string> encr_SEK_ptr = levelDb->readString("SEK");
if (encr_SEK_ptr == nullptr){
spdlog::info("SEK was not created yet");
}
}
......@@ -87,7 +109,9 @@ void init_enclave() {
}
#endif
std::cerr << "SGX_DEBUG_FLAG = " << SGX_DEBUG_FLAG << std::endl;
if ( DEBUG_PRINT) {
spdlog::info("SGX_DEBUG_FLAG = {}", SGX_DEBUG_FLAG);
}
status = sgx_create_enclave_search(ENCLAVE_NAME, SGX_DEBUG_FLAG, &token,
&updated, &eid, 0);
......@@ -102,7 +126,8 @@ void init_enclave() {
exit(1);
}
fprintf(stderr, "Enclave launched\n");
//fprintf(stderr, "Enclave launched\n");
spdlog::info( "Enclave launched");
status = tgmp_init(eid);
if (status != SGX_SUCCESS) {
......@@ -110,14 +135,17 @@ void init_enclave() {
exit(1);
}
fprintf(stderr, "libtgmp initialized\n");
if (DEBUG_PRINT) {
spdlog::info("libtgmp initialized");
//fprintf(stderr, "libtgmp initialized\n");
}
}
int sgxServerInited = 0;
void init_all(bool check_cert, bool sign_automatically) {
//spdlog::set_pattern("%c");
if (sgxServerInited == 1)
return;
......@@ -132,6 +160,6 @@ void init_all(bool check_cert, bool sign_automatically) {
init_http_server();
}
init_enclave();
std::cerr << "enclave inited" << std::endl;
//std::cerr << "enclave inited" << std::endl;
init_daemon();
}
......@@ -30,6 +30,8 @@
#define EXTERNC
#endif
EXTERNC void init_all(bool check_cert, bool sign_automatically);
EXTERNC void init_daemon();
......
......@@ -50,7 +50,7 @@ include $(top_srcdir)/build-aux/sgx_enclave.am
ENCLAVE=secure_enclave
ENCLAVE_CONFIG=$(ENCLAVE).config.xml
ENCLAVE_KEY=$(ENCLAVE)_private.pem
ENCLAVE_KEY=test_insecure_private_key.pem #$(ENCLAVE)_private.pem
## Provide additional flags to sgx_sign when signing the enclave.
......
......@@ -343,7 +343,7 @@ CLEANFILES = $(ENCLAVE).signed.so secure_enclave_t.c \
@ENCLAVE_RELEASE_SIGN_FALSE@nodist_signed_enclave_debug_SOURCES = signed_enclave_debug.c
ENCLAVE = secure_enclave
ENCLAVE_CONFIG = $(ENCLAVE).config.xml
ENCLAVE_KEY = $(ENCLAVE)_private.pem
ENCLAVE_KEY = test_insecure_private_key.pem #$(ENCLAVE)_private.pem
secure_enclave_SOURCES = secure_enclave_t.c secure_enclave_t.h \
secure_enclave.c \
curves.c domain_parameters.c numbertheory.c point.c signature.c DH_dkg.c \
......
......@@ -894,5 +894,25 @@ void get_bls_pub_key(int *err_status, char* err_string, uint8_t* encrypted_key,
}
}
void generate_SEK(int *err_status, char *err_string,
uint8_t *encrypted_SEK, uint32_t *enc_len){
unsigned char* rand_char = (unsigned char*)malloc(16);
sgx_read_rand( rand_char, 16);
uint32_t sealedLen = sgx_calc_sealed_data_size(0, 32);
sgx_status_t status = sgx_seal_data(0, NULL, 32, (uint8_t *)rand_char, sealedLen,(sgx_sealed_data_t*)encrypted_SEK);
if( status != SGX_SUCCESS) {
snprintf(err_string, BUF_LEN,"seal SEK failed");
*err_status = status;
return;
}
*enc_len = sealedLen;
free(rand_char);
}
......@@ -157,6 +157,12 @@ enclave {
uint8_t _t,
uint8_t _n,
uint8_t ind1);
public void generate_SEK(
[user_check] int *err_status,
[out, count = 1024] char *err_string,
[in, count = 1024] uint8_t *encrypted_SEK,
[user_check] uint32_t *enc_len);
};
......
......@@ -68,8 +68,8 @@ int main(int argc, char *argv[]) {
if (strlen(argv[1]) == 2 ) {
fprintf(stderr, "-c client certificate will not be checked\n");
fprintf(stderr, "-s client certificate will be signed automatically\n");
printf(stderr, "-d turn on debug output\n");
printf(stderr, "-0 SGXWalletServer will be launched on http (not https)\n");
fprintf(stderr, "-d turn on debug output\n");
fprintf(stderr, "-0 SGXWalletServer will be launched on http (not https)\n");
exit(0);
} else {
fprintf(stderr, "unknown flag %s\n", argv[1]);
......
......@@ -33,6 +33,8 @@
#include <stdbool.h>
extern int DEBUG_PRINT;
extern int is_sgx_https;
......@@ -90,7 +92,7 @@ extern int is_sgx_https;
#define BASE_PORT 1026
#define WALLETDB_NAME "sgxwallet.db"//"test_sgxwallet.db"//
#define WALLETDB_NAME "SGXData/sgxwallet.db"//"test_sgxwallet.db"//
#define ENCLAVE_NAME "secure_enclave.signed.so"
......
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
//
// Async logging using global thread pool
// All loggers created here share same global thread pool.
// Each log message is pushed to a queue along with a shared pointer to the
// logger.
// If a logger deleted while having pending messages in the queue, it's actual
// destruction will defer
// until all its messages are processed by the thread pool.
// This is because each message in the queue holds a shared_ptr to the
// originating logger.
#include <spdlog/async_logger.h>
#include <spdlog/details/registry.h>
#include <spdlog/details/thread_pool.h>
#include <memory>
#include <mutex>
#include <functional>
namespace spdlog {
namespace details {
static const size_t default_async_q_size = 8192;
}
// async logger factory - creates async loggers backed with thread pool.
// if a global thread pool doesn't already exist, create it with default queue
// size of 8192 items and single thread.
template<async_overflow_policy OverflowPolicy = async_overflow_policy::block>
struct async_factory_impl
{
template<typename Sink, typename... SinkArgs>
static std::shared_ptr<async_logger> create(std::string logger_name, SinkArgs &&... args)
{
auto &registry_inst = details::registry::instance();
// create global thread pool if not already exists..
auto &mutex = registry_inst.tp_mutex();
std::lock_guard<std::recursive_mutex> tp_lock(mutex);
auto tp = registry_inst.get_tp();
if (tp == nullptr)
{
tp = std::make_shared<details::thread_pool>(details::default_async_q_size, 1);
registry_inst.set_tp(tp);
}
auto sink = std::make_shared<Sink>(std::forward<SinkArgs>(args)...);
auto new_logger = std::make_shared<async_logger>(std::move(logger_name), std::move(sink), std::move(tp), OverflowPolicy);
registry_inst.initialize_logger(new_logger);
return new_logger;
}
};
using async_factory = async_factory_impl<async_overflow_policy::block>;
using async_factory_nonblock = async_factory_impl<async_overflow_policy::overrun_oldest>;
template<typename Sink, typename... SinkArgs>
inline std::shared_ptr<spdlog::logger> create_async(std::string logger_name, SinkArgs &&... sink_args)
{
return async_factory::create<Sink>(std::move(logger_name), std::forward<SinkArgs>(sink_args)...);
}
template<typename Sink, typename... SinkArgs>
inline std::shared_ptr<spdlog::logger> create_async_nb(std::string logger_name, SinkArgs &&... sink_args)
{
return async_factory_nonblock::create<Sink>(std::move(logger_name), std::forward<SinkArgs>(sink_args)...);
}
// set global thread pool.
inline void init_thread_pool(size_t q_size, size_t thread_count, std::function<void()> on_thread_start)
{
auto tp = std::make_shared<details::thread_pool>(q_size, thread_count, on_thread_start);
details::registry::instance().set_tp(std::move(tp));
}
// set global thread pool.
inline void init_thread_pool(size_t q_size, size_t thread_count)
{
init_thread_pool(q_size, thread_count, [] {});
}
// get the global thread pool.
inline std::shared_ptr<spdlog::details::thread_pool> thread_pool()
{
return details::registry::instance().get_tp();
}
} // namespace spdlog
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include <spdlog/async_logger.h>
#endif
#include <spdlog/sinks/sink.h>
#include <spdlog/details/thread_pool.h>
#include <memory>
#include <string>
SPDLOG_INLINE spdlog::async_logger::async_logger(
std::string logger_name, sinks_init_list sinks_list, std::weak_ptr<details::thread_pool> tp, async_overflow_policy overflow_policy)
: async_logger(std::move(logger_name), sinks_list.begin(), sinks_list.end(), std::move(tp), overflow_policy)
{}
SPDLOG_INLINE spdlog::async_logger::async_logger(
std::string logger_name, sink_ptr single_sink, std::weak_ptr<details::thread_pool> tp, async_overflow_policy overflow_policy)
: async_logger(std::move(logger_name), {std::move(single_sink)}, std::move(tp), overflow_policy)
{}
// send the log message to the thread pool
SPDLOG_INLINE void spdlog::async_logger::sink_it_(const details::log_msg &msg)
{
if (auto pool_ptr = thread_pool_.lock())
{
pool_ptr->post_log(shared_from_this(), msg, overflow_policy_);
}
else
{
SPDLOG_THROW(spdlog_ex("async log: thread pool doesn't exist anymore"));
}
}
// send flush request to the thread pool
SPDLOG_INLINE void spdlog::async_logger::flush_()
{
if (auto pool_ptr = thread_pool_.lock())
{
pool_ptr->post_flush(shared_from_this(), overflow_policy_);
}
else
{
SPDLOG_THROW(spdlog_ex("async flush: thread pool doesn't exist anymore"));
}
}
//
// backend functions - called from the thread pool to do the actual job
//
SPDLOG_INLINE void spdlog::async_logger::backend_sink_it_(const details::log_msg &msg)
{
for (auto &sink : sinks_)
{
if (sink->should_log(msg.level))
{
SPDLOG_TRY
{
sink->log(msg);
}
SPDLOG_LOGGER_CATCH()
}
}
if (should_flush_(msg))
{
backend_flush_();
}
}
SPDLOG_INLINE void spdlog::async_logger::backend_flush_()
{
for (auto &sink : sinks_)
{
SPDLOG_TRY
{
sink->flush();
}
SPDLOG_LOGGER_CATCH()
}
}
SPDLOG_INLINE std::shared_ptr<spdlog::logger> spdlog::async_logger::clone(std::string new_name)
{
auto cloned = std::make_shared<spdlog::async_logger>(*this);
cloned->name_ = std::move(new_name);
return cloned;
}
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
// Fast asynchronous logger.
// Uses pre allocated queue.
// Creates a single back thread to pop messages from the queue and log them.
//
// Upon each log write the logger:
// 1. Checks if its log level is enough to log the message
// 2. Push a new copy of the message to a queue (or block the caller until
// space is available in the queue)
// Upon destruction, logs all remaining messages in the queue before
// destructing..
#include <spdlog/logger.h>
namespace spdlog {
// Async overflow policy - block by default.
enum class async_overflow_policy
{
block, // Block until message can be enqueued
overrun_oldest // Discard oldest message in the queue if full when trying to
// add new item.
};
namespace details {
class thread_pool;
}
class async_logger final : public std::enable_shared_from_this<async_logger>, public logger
{
friend class details::thread_pool;
public:
template<typename It>
async_logger(std::string logger_name, It begin, It end, std::weak_ptr<details::thread_pool> tp,
async_overflow_policy overflow_policy = async_overflow_policy::block)
: logger(std::move(logger_name), begin, end)
, thread_pool_(std::move(tp))
, overflow_policy_(overflow_policy)
{}
async_logger(std::string logger_name, sinks_init_list sinks_list, std::weak_ptr<details::thread_pool> tp,
async_overflow_policy overflow_policy = async_overflow_policy::block);
async_logger(std::string logger_name, sink_ptr single_sink, std::weak_ptr<details::thread_pool> tp,
async_overflow_policy overflow_policy = async_overflow_policy::block);
std::shared_ptr<logger> clone(std::string new_name) override;
protected:
void sink_it_(const details::log_msg &msg) override;
void flush_() override;
void backend_sink_it_(const details::log_msg &incoming_log_msg);
void backend_flush_();
private:
std::weak_ptr<details::thread_pool> thread_pool_;
async_overflow_policy overflow_policy_;
};
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
#include "async_logger-inl.h"
#endif
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include <spdlog/common.h>
#endif
namespace spdlog {
namespace level {
static string_view_t level_string_views[] SPDLOG_LEVEL_NAMES;
static const char *short_level_names[] SPDLOG_SHORT_LEVEL_NAMES;
SPDLOG_INLINE string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT
{
return level_string_views[l];
}
SPDLOG_INLINE const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT
{
return short_level_names[l];
}
SPDLOG_INLINE spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT
{
int level = 0;
for (const auto &level_str : level_string_views)
{
if (level_str == name)
{
return static_cast<level::level_enum>(level);
}
level++;
}
return level::off;
}
} // namespace level
SPDLOG_INLINE spdlog_ex::spdlog_ex(std::string msg)
: msg_(std::move(msg))
{}
SPDLOG_INLINE spdlog_ex::spdlog_ex(const std::string &msg, int last_errno)
{
memory_buf_t outbuf;
fmt::format_system_error(outbuf, last_errno, msg);
msg_ = fmt::to_string(outbuf);
}
SPDLOG_INLINE const char *spdlog_ex::what() const SPDLOG_NOEXCEPT
{
return msg_.c_str();
}
} // namespace spdlog
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include <spdlog/tweakme.h>
#include <spdlog/details/null_mutex.h>
#include <atomic>
#include <chrono>
#include <initializer_list>
#include <memory>
#include <exception>
#include <string>
#include <type_traits>
#include <functional>
#ifdef _WIN32
#ifndef NOMINMAX
#define NOMINMAX // prevent windows redefining min/max
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#endif //_WIN32
#ifdef SPDLOG_COMPILED_LIB
#undef SPDLOG_HEADER_ONLY
#define SPDLOG_INLINE
#else
#define SPDLOG_HEADER_ONLY
#define SPDLOG_INLINE inline
#endif
#include <spdlog/fmt/fmt.h>
// visual studio upto 2013 does not support noexcept nor constexpr
#if defined(_MSC_VER) && (_MSC_VER < 1900)
#define SPDLOG_NOEXCEPT _NOEXCEPT
#define SPDLOG_CONSTEXPR
#else
#define SPDLOG_NOEXCEPT noexcept
#define SPDLOG_CONSTEXPR constexpr
#endif
#if defined(__GNUC__) || defined(__clang__)
#define SPDLOG_DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER)
#define SPDLOG_DEPRECATED __declspec(deprecated)
#else
#define SPDLOG_DEPRECATED
#endif
// disable thread local on msvc 2013
#ifndef SPDLOG_NO_TLS
#if (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__cplusplus_winrt)
#define SPDLOG_NO_TLS 1
#endif
#endif
#ifndef SPDLOG_FUNCTION
#define SPDLOG_FUNCTION static_cast<const char *>(__FUNCTION__)
#endif
#ifdef SPDLOG_NO_EXCEPTIONS
#define SPDLOG_TRY
#define SPDLOG_THROW(ex) \
do \
{ \
printf("spdlog fatal error: %s\n", ex.what()); \
std::abort(); \
} while (0)
#define SPDLOG_CATCH_ALL()
#else
#define SPDLOG_TRY try
#define SPDLOG_THROW(ex) throw(ex)
#define SPDLOG_CATCH_ALL() catch (...)
#endif
namespace spdlog {
class formatter;
namespace sinks {
class sink;
}
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
using filename_t = std::wstring;
#define SPDLOG_FILENAME_T(s) L##s
#else
using filename_t = std::string;
#define SPDLOG_FILENAME_T(s) s
#endif
using log_clock = std::chrono::system_clock;
using sink_ptr = std::shared_ptr<sinks::sink>;
using sinks_init_list = std::initializer_list<sink_ptr>;
using err_handler = std::function<void(const std::string &err_msg)>;
using string_view_t = fmt::basic_string_view<char>;
using wstring_view_t = fmt::basic_string_view<wchar_t>;
using memory_buf_t = fmt::basic_memory_buffer<char, 250>;
#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
#ifndef _WIN32
#error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows
#else
template<typename T>
struct is_convertible_to_wstring_view : std::is_convertible<T, wstring_view_t>
{};
#endif // _WIN32
#else
template<typename>
struct is_convertible_to_wstring_view : std::false_type
{};
#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
#if defined(SPDLOG_NO_ATOMIC_LEVELS)
using level_t = details::null_atomic_int;
#else
using level_t = std::atomic<int>;
#endif
#define SPDLOG_LEVEL_TRACE 0
#define SPDLOG_LEVEL_DEBUG 1
#define SPDLOG_LEVEL_INFO 2
#define SPDLOG_LEVEL_WARN 3
#define SPDLOG_LEVEL_ERROR 4
#define SPDLOG_LEVEL_CRITICAL 5
#define SPDLOG_LEVEL_OFF 6
#if !defined(SPDLOG_ACTIVE_LEVEL)
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO
#endif
// Log level enum
namespace level {
enum level_enum
{
trace = SPDLOG_LEVEL_TRACE,
debug = SPDLOG_LEVEL_DEBUG,
info = SPDLOG_LEVEL_INFO,
warn = SPDLOG_LEVEL_WARN,
err = SPDLOG_LEVEL_ERROR,
critical = SPDLOG_LEVEL_CRITICAL,
off = SPDLOG_LEVEL_OFF,
};
#if !defined(SPDLOG_LEVEL_NAMES)
#define SPDLOG_LEVEL_NAMES \
{ \
"trace", "debug", "info", "warning", "error", "critical", "off" \
}
#endif
#if !defined(SPDLOG_SHORT_LEVEL_NAMES)
#define SPDLOG_SHORT_LEVEL_NAMES \
{ \
"T", "D", "I", "W", "E", "C", "O" \
}
#endif
string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT;
const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT;
spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT;
using level_hasher = std::hash<int>;
} // namespace level
//
// Color mode used by sinks with color support.
//
enum class color_mode
{
always,
automatic,
never
};
//
// Pattern time - specific time getting to use for pattern_formatter.
// local time by default
//
enum class pattern_time_type
{
local, // log localtime
utc // log utc
};
//
// Log exception
//
class spdlog_ex : public std::exception
{
public:
explicit spdlog_ex(std::string msg);
spdlog_ex(const std::string &msg, int last_errno);
const char *what() const SPDLOG_NOEXCEPT override;
private:
std::string msg_;
};
struct source_loc
{
SPDLOG_CONSTEXPR source_loc() = default;
SPDLOG_CONSTEXPR source_loc(const char *filename_in, int line_in, const char *funcname_in)
: filename{filename_in}
, line{line_in}
, funcname{funcname_in}
{}
SPDLOG_CONSTEXPR bool empty() const SPDLOG_NOEXCEPT
{
return line == 0;
}
const char *filename{nullptr};
int line{0};
const char *funcname{nullptr};
};
namespace details {
// make_unique support for pre c++14
#if __cplusplus >= 201402L // C++14 and beyond
using std::make_unique;
#else
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args &&... args)
{
static_assert(!std::is_array<T>::value, "arrays not supported");
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
#endif
} // namespace details
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
#include "common-inl.h"
#endif
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include <spdlog/details/backtracer.h>
#endif
namespace spdlog {
namespace details {
SPDLOG_INLINE backtracer::backtracer(const backtracer &other)
{
std::lock_guard<std::mutex> lock(other.mutex_);
enabled_ = other.enabled();
messages_ = other.messages_;
}
SPDLOG_INLINE backtracer::backtracer(backtracer &&other) SPDLOG_NOEXCEPT
{
std::lock_guard<std::mutex> lock(other.mutex_);
enabled_ = other.enabled();
messages_ = std::move(other.messages_);
}
SPDLOG_INLINE backtracer &backtracer::operator=(backtracer other)
{
std::lock_guard<std::mutex> lock(mutex_);
enabled_ = other.enabled();
messages_ = std::move(other.messages_);
return *this;
}
SPDLOG_INLINE void backtracer::enable(size_t size)
{
std::lock_guard<std::mutex> lock{mutex_};
enabled_.store(true, std::memory_order_relaxed);
messages_ = circular_q<log_msg_buffer>{size};
}
SPDLOG_INLINE void backtracer::disable()
{
std::lock_guard<std::mutex> lock{mutex_};
enabled_.store(false, std::memory_order_relaxed);
}
SPDLOG_INLINE bool backtracer::enabled() const
{
return enabled_.load(std::memory_order_relaxed);
}
SPDLOG_INLINE void backtracer::push_back(const log_msg &msg)
{
std::lock_guard<std::mutex> lock{mutex_};
messages_.push_back(log_msg_buffer{msg});
}
// pop all items in the q and apply the given fun on each of them.
SPDLOG_INLINE void backtracer::foreach_pop(std::function<void(const details::log_msg &)> fun)
{
std::lock_guard<std::mutex> lock{mutex_};
while (!messages_.empty())
{
auto &front_msg = messages_.front();
fun(front_msg);
messages_.pop_front();
}
}
} // namespace details
} // namespace spdlog
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include <spdlog/details/log_msg_buffer.h>
#include <spdlog/details/circular_q.h>
#include <atomic>
#include <mutex>
#include <functional>
// Store log messages in circular buffer.
// Useful for storing debug data in case of error/warning happens.
namespace spdlog {
namespace details {
class backtracer
{
mutable std::mutex mutex_;
std::atomic<bool> enabled_{false};
circular_q<log_msg_buffer> messages_;
public:
backtracer() = default;
backtracer(const backtracer &other);
backtracer(backtracer &&other) SPDLOG_NOEXCEPT;
backtracer &operator=(backtracer other);
void enable(size_t size);
void disable();
bool enabled() const;
void push_back(const log_msg &msg);
// pop all items in the q and apply the given fun on each of them.
void foreach_pop(std::function<void(const details::log_msg &)> fun);
};
} // namespace details
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
#include "backtracer-inl.h"
#endif
\ No newline at end of file
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
// circular q view of std::vector.
#pragma once
#include <vector>
#include <cassert>
namespace spdlog {
namespace details {
template<typename T>
class circular_q
{
size_t max_items_ = 0;
typename std::vector<T>::size_type head_ = 0;
typename std::vector<T>::size_type tail_ = 0;
size_t overrun_counter_ = 0;
std::vector<T> v_;
public:
using value_type = T;
// empty ctor - create a disabled queue with no elements allocated at all
circular_q() = default;
explicit circular_q(size_t max_items)
: max_items_(max_items + 1) // one item is reserved as marker for full q
, v_(max_items_)
{}
circular_q(const circular_q &) = default;
circular_q &operator=(const circular_q &) = default;
// move cannot be default,
// since we need to reset head_, tail_, etc to zero in the moved object
circular_q(circular_q &&other) SPDLOG_NOEXCEPT
{
copy_moveable(std::move(other));
}
circular_q &operator=(circular_q &&other) SPDLOG_NOEXCEPT
{
copy_moveable(std::move(other));
return *this;
}
// push back, overrun (oldest) item if no room left
void push_back(T &&item)
{
if (max_items_ > 0)
{
v_[tail_] = std::move(item);
tail_ = (tail_ + 1) % max_items_;
if (tail_ == head_) // overrun last item if full
{
head_ = (head_ + 1) % max_items_;
++overrun_counter_;
}
}
}
// Return reference to the front item.
// If there are no elements in the container, the behavior is undefined.
const T &front() const
{
return v_[head_];
}
T &front()
{
return v_[head_];
}
// Return number of elements actually stored
size_t size() const
{
if (tail_ >= head_)
{
return tail_ - head_;
}
else
{
return max_items_ - (head_ - tail_);
}
}
// Return const reference to item by index.
// If index is out of range 0…size()-1, the behavior is undefined.
const T &at(size_t i) const
{
assert(i < size());
return v_[(head_ + i) % max_items_];
}
// Pop item from front.
// If there are no elements in the container, the behavior is undefined.
void pop_front()
{
head_ = (head_ + 1) % max_items_;
}
bool empty() const
{
return tail_ == head_;
}
bool full() const
{
// head is ahead of the tail by 1
if (max_items_ > 0)
{
return ((tail_ + 1) % max_items_) == head_;
}
return false;
}
size_t overrun_counter() const
{
return overrun_counter_;
}
private:
// copy from other&& and reset it to disabled state
void copy_moveable(circular_q &&other) SPDLOG_NOEXCEPT
{
max_items_ = other.max_items_;
head_ = other.head_;
tail_ = other.tail_;
overrun_counter_ = other.overrun_counter_;
v_ = std::move(other.v_);
// put &&other in disabled, but valid state
other.max_items_ = 0;
other.head_ = other.tail_ = 0;
other.overrun_counter_ = 0;
}
};
} // namespace details
} // namespace spdlog
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include <spdlog/details/null_mutex.h>
#include <mutex>
namespace spdlog {
namespace details {
struct console_mutex
{
using mutex_t = std::mutex;
static mutex_t &mutex()
{
static mutex_t s_mutex;
return s_mutex;
}
};
struct console_nullmutex
{
using mutex_t = null_mutex;
static mutex_t &mutex()
{
static mutex_t s_mutex;
return s_mutex;
}
};
} // namespace details
} // namespace spdlog
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include <spdlog/details/file_helper.h>
#endif
#include <spdlog/details/os.h>
#include <spdlog/common.h>
#include <cerrno>
#include <chrono>
#include <cstdio>
#include <string>
#include <thread>
#include <tuple>
namespace spdlog {
namespace details {
SPDLOG_INLINE file_helper::~file_helper()
{
close();
}
SPDLOG_INLINE void file_helper::open(const filename_t &fname, bool truncate)
{
close();
filename_ = fname;
auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab");
for (int tries = 0; tries < open_tries_; ++tries)
{
// create containing folder if not exists already.
os::create_dir(os::dir_name(fname));
if (!os::fopen_s(&fd_, fname, mode))
{
return;
}
details::os::sleep_for_millis(open_interval_);
}
SPDLOG_THROW(spdlog_ex("Failed opening file " + os::filename_to_str(filename_) + " for writing", errno));
}
SPDLOG_INLINE void file_helper::reopen(bool truncate)
{
if (filename_.empty())
{
SPDLOG_THROW(spdlog_ex("Failed re opening file - was not opened before"));
}
this->open(filename_, truncate);
}
SPDLOG_INLINE void file_helper::flush()
{
std::fflush(fd_);
}
SPDLOG_INLINE void file_helper::close()
{
if (fd_ != nullptr)
{
std::fclose(fd_);
fd_ = nullptr;
}
}
SPDLOG_INLINE void file_helper::write(const memory_buf_t &buf)
{
size_t msg_size = buf.size();
auto data = buf.data();
if (std::fwrite(data, 1, msg_size, fd_) != msg_size)
{
SPDLOG_THROW(spdlog_ex("Failed writing to file " + os::filename_to_str(filename_), errno));
}
}
SPDLOG_INLINE size_t file_helper::size() const
{
if (fd_ == nullptr)
{
SPDLOG_THROW(spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(filename_)));
}
return os::filesize(fd_);
}
SPDLOG_INLINE const filename_t &file_helper::filename() const
{
return filename_;
}
//
// return file path and its extension:
//
// "mylog.txt" => ("mylog", ".txt")
// "mylog" => ("mylog", "")
// "mylog." => ("mylog.", "")
// "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt")
//
// the starting dot in filenames is ignored (hidden files):
//
// ".mylog" => (".mylog". "")
// "my_folder/.mylog" => ("my_folder/.mylog", "")
// "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt")
SPDLOG_INLINE std::tuple<filename_t, filename_t> file_helper::split_by_extension(const filename_t &fname)
{
auto ext_index = fname.rfind('.');
// no valid extension found - return whole path and empty string as
// extension
if (ext_index == filename_t::npos || ext_index == 0 || ext_index == fname.size() - 1)
{
return std::make_tuple(fname, filename_t());
}
// treat cases like "/etc/rc.d/somelogfile or "/abc/.hiddenfile"
auto folder_index = fname.rfind(details::os::folder_sep);
if (folder_index != filename_t::npos && folder_index >= ext_index - 1)
{
return std::make_tuple(fname, filename_t());
}
// finally - return a valid base and extension tuple
return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index));
}
} // namespace details
} // namespace spdlog
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include <spdlog/common.h>
#include <tuple>
namespace spdlog {
namespace details {
// Helper class for file sinks.
// When failing to open a file, retry several times(5) with a delay interval(10 ms).
// Throw spdlog_ex exception on errors.
class file_helper
{
public:
explicit file_helper() = default;
file_helper(const file_helper &) = delete;
file_helper &operator=(const file_helper &) = delete;
~file_helper();
void open(const filename_t &fname, bool truncate = false);
void reopen(bool truncate);
void flush();
void close();
void write(const memory_buf_t &buf);
size_t size() const;
const filename_t &filename() const;
//
// return file path and its extension:
//
// "mylog.txt" => ("mylog", ".txt")
// "mylog" => ("mylog", "")
// "mylog." => ("mylog.", "")
// "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt")
//
// the starting dot in filenames is ignored (hidden files):
//
// ".mylog" => (".mylog". "")
// "my_folder/.mylog" => ("my_folder/.mylog", "")
// "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt")
static std::tuple<filename_t, filename_t> split_by_extension(const filename_t &fname);
private:
const int open_tries_ = 5;
const int open_interval_ = 10;
std::FILE *fd_{nullptr};
filename_t filename_;
};
} // namespace details
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
#include "file_helper-inl.h"
#endif
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include <chrono>
#include <type_traits>
#include <spdlog/fmt/fmt.h>
#include <spdlog/common.h>
// Some fmt helpers to efficiently format and pad ints and strings
namespace spdlog {
namespace details {
namespace fmt_helper {
inline spdlog::string_view_t to_string_view(const memory_buf_t &buf) SPDLOG_NOEXCEPT
{
return spdlog::string_view_t{buf.data(), buf.size()};
}
inline void append_string_view(spdlog::string_view_t view, memory_buf_t &dest)
{
auto *buf_ptr = view.data();
if (buf_ptr != nullptr)
{
dest.append(buf_ptr, buf_ptr + view.size());
}
}
template<typename T>
inline void append_int(T n, memory_buf_t &dest)
{
fmt::format_int i(n);
dest.append(i.data(), i.data() + i.size());
}
template<typename T>
inline unsigned count_digits(T n)
{
using count_type = typename std::conditional<(sizeof(T) > sizeof(uint32_t)), uint64_t, uint32_t>::type;
return static_cast<unsigned>(fmt::internal::count_digits(static_cast<count_type>(n)));
}
inline void pad2(int n, memory_buf_t &dest)
{
if (n > 99)
{
append_int(n, dest);
}
else if (n > 9) // 10-99
{
dest.push_back(static_cast<char>('0' + n / 10));
dest.push_back(static_cast<char>('0' + n % 10));
}
else if (n >= 0) // 0-9
{
dest.push_back('0');
dest.push_back(static_cast<char>('0' + n));
}
else // negatives (unlikely, but just in case, let fmt deal with it)
{
fmt::format_to(dest, "{:02}", n);
}
}
template<typename T>
inline void pad_uint(T n, unsigned int width, memory_buf_t &dest)
{
static_assert(std::is_unsigned<T>::value, "pad_uint must get unsigned T");
auto digits = count_digits(n);
if (width > digits)
{
const char *zeroes = "0000000000000000000";
dest.append(zeroes, zeroes + width - digits);
}
append_int(n, dest);
}
template<typename T>
inline void pad3(T n, memory_buf_t &dest)
{
pad_uint(n, 3, dest);
}
template<typename T>
inline void pad6(T n, memory_buf_t &dest)
{
pad_uint(n, 6, dest);
}
template<typename T>
inline void pad9(T n, memory_buf_t &dest)
{
pad_uint(n, 9, dest);
}
// return fraction of a second of the given time_point.
// e.g.
// fraction<std::milliseconds>(tp) -> will return the millis part of the second
template<typename ToDuration>
inline ToDuration time_fraction(log_clock::time_point tp)
{
using std::chrono::duration_cast;
using std::chrono::seconds;
auto duration = tp.time_since_epoch();
auto secs = duration_cast<seconds>(duration);
return duration_cast<ToDuration>(duration) - duration_cast<ToDuration>(secs);
}
} // namespace fmt_helper
} // namespace details
} // namespace spdlog
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include <spdlog/details/log_msg.h>
#endif
#include <spdlog/details/os.h>
namespace spdlog {
namespace details {
SPDLOG_INLINE log_msg::log_msg(
spdlog::source_loc loc, string_view_t a_logger_name, spdlog::level::level_enum lvl, spdlog::string_view_t msg)
: logger_name(a_logger_name)
, level(lvl)
, time(os::now())
#ifndef SPDLOG_NO_THREAD_ID
, thread_id(os::thread_id())
#endif
, source(loc)
, payload(msg)
{}
SPDLOG_INLINE log_msg::log_msg(string_view_t a_logger_name, spdlog::level::level_enum lvl, spdlog::string_view_t msg)
: log_msg(source_loc{}, a_logger_name, lvl, msg)
{}
} // namespace details
} // namespace spdlog
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include <spdlog/common.h>
#include <string>
namespace spdlog {
namespace details {
struct log_msg
{
log_msg() = default;
log_msg(source_loc loc, string_view_t logger_name, level::level_enum lvl, string_view_t msg);
log_msg(string_view_t logger_name, level::level_enum lvl, string_view_t msg);
log_msg(const log_msg &other) = default;
string_view_t logger_name;
level::level_enum level{level::off};
log_clock::time_point time;
size_t thread_id{0};
// wrapping the formatted text with color (updated by pattern_formatter).
mutable size_t color_range_start{0};
mutable size_t color_range_end{0};
source_loc source;
string_view_t payload;
};
} // namespace details
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
#include "log_msg-inl.h"
#endif
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include <spdlog/details/log_msg_buffer.h>
#endif
namespace spdlog {
namespace details {
SPDLOG_INLINE log_msg_buffer::log_msg_buffer(const log_msg &orig_msg)
: log_msg{orig_msg}
{
buffer.append(logger_name.begin(), logger_name.end());
buffer.append(payload.begin(), payload.end());
update_string_views();
}
SPDLOG_INLINE log_msg_buffer::log_msg_buffer(const log_msg_buffer &other)
: log_msg{other}
{
buffer.append(logger_name.begin(), logger_name.end());
buffer.append(payload.begin(), payload.end());
update_string_views();
}
SPDLOG_INLINE log_msg_buffer::log_msg_buffer(log_msg_buffer &&other) SPDLOG_NOEXCEPT : log_msg{other}, buffer{std::move(other.buffer)}
{
update_string_views();
}
SPDLOG_INLINE log_msg_buffer &log_msg_buffer::operator=(const log_msg_buffer &other)
{
log_msg::operator=(other);
buffer.clear();
buffer.append(other.buffer.data(), other.buffer.data() + other.buffer.size());
update_string_views();
return *this;
}
SPDLOG_INLINE log_msg_buffer &log_msg_buffer::operator=(log_msg_buffer &&other) SPDLOG_NOEXCEPT
{
log_msg::operator=(other);
buffer = std::move(other.buffer);
update_string_views();
return *this;
}
SPDLOG_INLINE void log_msg_buffer::update_string_views()
{
logger_name = string_view_t{buffer.data(), logger_name.size()};
payload = string_view_t{buffer.data() + logger_name.size(), payload.size()};
}
} // namespace details
} // namespace spdlog
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include <spdlog/details/log_msg.h>
namespace spdlog {
namespace details {
// Extend log_msg with internal buffer to store its payload.
// THis is needed since log_msg holds string_views that points to stack data.
class log_msg_buffer : public log_msg
{
memory_buf_t buffer;
void update_string_views();
public:
log_msg_buffer() = default;
explicit log_msg_buffer(const log_msg &orig_msg);
log_msg_buffer(const log_msg_buffer &other);
log_msg_buffer(log_msg_buffer &&other) SPDLOG_NOEXCEPT;
log_msg_buffer &operator=(const log_msg_buffer &other);
log_msg_buffer &operator=(log_msg_buffer &&other) SPDLOG_NOEXCEPT;
};
} // namespace details
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
#include "log_msg_buffer-inl.h"
#endif
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
// multi producer-multi consumer blocking queue.
// enqueue(..) - will block until room found to put the new message.
// enqueue_nowait(..) - will return immediately with false if no room left in
// the queue.
// dequeue_for(..) - will block until the queue is not empty or timeout have
// passed.
#include <spdlog/details/circular_q.h>
#include <condition_variable>
#include <mutex>
namespace spdlog {
namespace details {
template<typename T>
class mpmc_blocking_queue
{
public:
using item_type = T;
explicit mpmc_blocking_queue(size_t max_items)
: q_(max_items)
{}
#ifndef __MINGW32__
// try to enqueue and block if no room left
void enqueue(T &&item)
{
{
std::unique_lock<std::mutex> lock(queue_mutex_);
pop_cv_.wait(lock, [this] { return !this->q_.full(); });
q_.push_back(std::move(item));
}
push_cv_.notify_one();
}
// enqueue immediately. overrun oldest message in the queue if no room left.
void enqueue_nowait(T &&item)
{
{
std::unique_lock<std::mutex> lock(queue_mutex_);
q_.push_back(std::move(item));
}
push_cv_.notify_one();
}
// try to dequeue item. if no item found. wait upto timeout and try again
// Return true, if succeeded dequeue item, false otherwise
bool dequeue_for(T &popped_item, std::chrono::milliseconds wait_duration)
{
{
std::unique_lock<std::mutex> lock(queue_mutex_);
if (!push_cv_.wait_for(lock, wait_duration, [this] { return !this->q_.empty(); }))
{
return false;
}
popped_item = std::move(q_.front());
q_.pop_front();
}
pop_cv_.notify_one();
return true;
}
#else
// apparently mingw deadlocks if the mutex is released before cv.notify_one(),
// so release the mutex at the very end each function.
// try to enqueue and block if no room left
void enqueue(T &&item)
{
std::unique_lock<std::mutex> lock(queue_mutex_);
pop_cv_.wait(lock, [this] { return !this->q_.full(); });
q_.push_back(std::move(item));
push_cv_.notify_one();
}
// enqueue immediately. overrun oldest message in the queue if no room left.
void enqueue_nowait(T &&item)
{
std::unique_lock<std::mutex> lock(queue_mutex_);
q_.push_back(std::move(item));
push_cv_.notify_one();
}
// try to dequeue item. if no item found. wait upto timeout and try again
// Return true, if succeeded dequeue item, false otherwise
bool dequeue_for(T &popped_item, std::chrono::milliseconds wait_duration)
{
std::unique_lock<std::mutex> lock(queue_mutex_);
if (!push_cv_.wait_for(lock, wait_duration, [this] { return !this->q_.empty(); }))
{
return false;
}
popped_item = std::move(q_.front());
q_.pop_front();
pop_cv_.notify_one();
return true;
}
#endif
size_t overrun_counter()
{
std::unique_lock<std::mutex> lock(queue_mutex_);
return q_.overrun_counter();
}
private:
std::mutex queue_mutex_;
std::condition_variable push_cv_;
std::condition_variable pop_cv_;
spdlog::details::circular_q<T> q_;
};
} // namespace details
} // namespace spdlog
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include <atomic>
#include <utility>
// null, no cost dummy "mutex" and dummy "atomic" int
namespace spdlog {
namespace details {
struct null_mutex
{
void lock() const {}
void unlock() const {}
bool try_lock() const
{
return true;
}
};
struct null_atomic_int
{
int value;
null_atomic_int() = default;
explicit null_atomic_int(int new_value)
: value(new_value)
{}
int load(std::memory_order = std::memory_order_relaxed) const
{
return value;
}
void store(int new_value, std::memory_order = std::memory_order_relaxed)
{
value = new_value;
}
int exchange(int new_value, std::memory_order = std::memory_order_relaxed)
{
std::swap(new_value, value);
return new_value; // return value before the call
}
};
} // namespace details
} // namespace spdlog
This diff is collapsed.
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include <spdlog/common.h>
#include <ctime> // std::time_t
namespace spdlog {
namespace details {
namespace os {
spdlog::log_clock::time_point now() SPDLOG_NOEXCEPT;
std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT;
std::tm localtime() SPDLOG_NOEXCEPT;
std::tm gmtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT;
std::tm gmtime() SPDLOG_NOEXCEPT;
// eol definition
#if !defined(SPDLOG_EOL)
#ifdef _WIN32
#define SPDLOG_EOL "\r\n"
#else
#define SPDLOG_EOL "\n"
#endif
#endif
SPDLOG_CONSTEXPR static const char *default_eol = SPDLOG_EOL;
// folder separator
#ifdef _WIN32
static const char folder_sep = '\\';
#else
SPDLOG_CONSTEXPR static const char folder_sep = '/';
#endif
#ifdef SPDLOG_PREVENT_CHILD_FD
void prevent_child_fd(FILE *f);
#endif
// fopen_s on non windows for writing
bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode);
// Remove filename. return 0 on success
int remove(const filename_t &filename) SPDLOG_NOEXCEPT;
// Remove file if exists. return 0 on success
// Note: Non atomic (might return failure to delete if concurrently deleted by other process/thread)
int remove_if_exists(const filename_t &filename) SPDLOG_NOEXCEPT;
int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT;
// Return if file exists.
bool path_exists(const filename_t &filename) SPDLOG_NOEXCEPT;
// Return file size according to open FILE* object
size_t filesize(FILE *f);
// Return utc offset in minutes or throw spdlog_ex on failure
int utc_minutes_offset(const std::tm &tm = details::os::localtime());
// Return current thread id as size_t
// It exists because the std::this_thread::get_id() is much slower(especially
// under VS 2013)
size_t _thread_id() SPDLOG_NOEXCEPT;
// Return current thread id as size_t (from thread local storage)
size_t thread_id() SPDLOG_NOEXCEPT;
// This is avoid msvc issue in sleep_for that happens if the clock changes.
// See https://github.com/gabime/spdlog/issues/609
void sleep_for_millis(int milliseconds) SPDLOG_NOEXCEPT;
std::string filename_to_str(const filename_t &filename);
int pid() SPDLOG_NOEXCEPT;
// Determine if the terminal supports colors
// Source: https://github.com/agauniyal/rang/
bool is_color_terminal() SPDLOG_NOEXCEPT;
// Determine if the terminal attached
// Source: https://github.com/agauniyal/rang/
bool in_terminal(FILE *file) SPDLOG_NOEXCEPT;
#if (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32)
void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target);
#endif
// Return directory name from given path or empty string
// "abc/file" => "abc"
// "abc/" => "abc"
// "abc" => ""
// "abc///" => "abc//"
filename_t dir_name(filename_t path);
// Create a dir from the given path.
// Return true if succeeded or if this dir already exists.
bool create_dir(filename_t path);
} // namespace os
} // namespace details
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
#include "os-inl.h"
#endif
This diff is collapsed.
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include <spdlog/common.h>
#include <spdlog/details/log_msg.h>
#include <spdlog/details/os.h>
#include <spdlog/formatter.h>
#include <chrono>
#include <ctime>
#include <memory>
#include <string>
#include <vector>
namespace spdlog {
namespace details {
// padding information.
struct padding_info
{
enum pad_side
{
left,
right,
center
};
padding_info() = default;
padding_info(size_t width, padding_info::pad_side side, bool truncate)
: width_(width)
, side_(side)
, truncate_(truncate)
, enabled_(true)
{}
bool enabled() const
{
return enabled_;
}
const size_t width_ = 0;
const pad_side side_ = left;
bool truncate_ = false;
bool enabled_ = false;
};
class flag_formatter
{
public:
explicit flag_formatter(padding_info padinfo)
: padinfo_(padinfo)
{}
flag_formatter() = default;
virtual ~flag_formatter() = default;
virtual void format(const details::log_msg &msg, const std::tm &tm_time, memory_buf_t &dest) = 0;
protected:
padding_info padinfo_;
};
} // namespace details
class pattern_formatter final : public formatter
{
public:
explicit pattern_formatter(
std::string pattern, pattern_time_type time_type = pattern_time_type::local, std::string eol = spdlog::details::os::default_eol);
// use default pattern is not given
explicit pattern_formatter(pattern_time_type time_type = pattern_time_type::local, std::string eol = spdlog::details::os::default_eol);
pattern_formatter(const pattern_formatter &other) = delete;
pattern_formatter &operator=(const pattern_formatter &other) = delete;
std::unique_ptr<formatter> clone() const override;
void format(const details::log_msg &msg, memory_buf_t &dest) override;
private:
std::string pattern_;
std::string eol_;
pattern_time_type pattern_time_type_;
std::tm cached_tm_;
std::chrono::seconds last_log_secs_;
std::vector<std::unique_ptr<details::flag_formatter>> formatters_;
std::tm get_time_(const details::log_msg &msg);
template<typename Padder>
void handle_flag_(char flag, details::padding_info padding);
// Extract given pad spec (e.g. %8X)
// Advance the given it pass the end of the padding spec found (if any)
// Return padding.
details::padding_info handle_padspec_(std::string::const_iterator &it, std::string::const_iterator end);
void compile_pattern_(const std::string &pattern);
};
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
#include "pattern_formatter-inl.h"
#endif
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include <spdlog/details/periodic_worker.h>
#endif
namespace spdlog {
namespace details {
SPDLOG_INLINE periodic_worker::periodic_worker(const std::function<void()> &callback_fun, std::chrono::seconds interval)
{
active_ = (interval > std::chrono::seconds::zero());
if (!active_)
{
return;
}
worker_thread_ = std::thread([this, callback_fun, interval]() {
for (;;)
{
std::unique_lock<std::mutex> lock(this->mutex_);
if (this->cv_.wait_for(lock, interval, [this] { return !this->active_; }))
{
return; // active_ == false, so exit this thread
}
callback_fun();
}
});
}
// stop the worker thread and join it
SPDLOG_INLINE periodic_worker::~periodic_worker()
{
if (worker_thread_.joinable())
{
{
std::lock_guard<std::mutex> lock(mutex_);
active_ = false;
}
cv_.notify_one();
worker_thread_.join();
}
}
} // namespace details
} // namespace spdlog
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
// periodic worker thread - periodically executes the given callback function.
//
// RAII over the owned thread:
// creates the thread on construction.
// stops and joins the thread on destruction (if the thread is executing a callback, wait for it to finish first).
#include <chrono>
#include <condition_variable>
#include <functional>
#include <mutex>
#include <thread>
namespace spdlog {
namespace details {
class periodic_worker
{
public:
periodic_worker(const std::function<void()> &callback_fun, std::chrono::seconds interval);
periodic_worker(const periodic_worker &) = delete;
periodic_worker &operator=(const periodic_worker &) = delete;
// stop the worker thread and join it
~periodic_worker();
private:
bool active_;
std::thread worker_thread_;
std::mutex mutex_;
std::condition_variable cv_;
};
} // namespace details
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
#include "periodic_worker-inl.h"
#endif
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include <spdlog/details/registry.h>
#endif
#include <spdlog/common.h>
#include <spdlog/details/periodic_worker.h>
#include <spdlog/logger.h>
#include <spdlog/details/pattern_formatter.h>
#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER
// support for the default stdout color logger
#ifdef _WIN32
#include <spdlog/sinks/wincolor_sink.h>
#else
#include <spdlog/sinks/ansicolor_sink.h>
#endif
#endif // SPDLOG_DISABLE_DEFAULT_LOGGER
#include <chrono>
#include <functional>
#include <memory>
#include <string>
#include <unordered_map>
namespace spdlog {
namespace details {
SPDLOG_INLINE registry::registry()
: formatter_(new pattern_formatter())
{
#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER
// create default logger (ansicolor_stdout_sink_mt or wincolor_stdout_sink_mt in windows).
#ifdef _WIN32
auto color_sink = std::make_shared<sinks::wincolor_stdout_sink_mt>();
#else
auto color_sink = std::make_shared<sinks::ansicolor_stdout_sink_mt>();
#endif
const char *default_logger_name = "";
default_logger_ = std::make_shared<spdlog::logger>(default_logger_name, std::move(color_sink));
loggers_[default_logger_name] = default_logger_;
#endif // SPDLOG_DISABLE_DEFAULT_LOGGER
}
SPDLOG_INLINE void registry::register_logger(std::shared_ptr<logger> new_logger)
{
std::lock_guard<std::mutex> lock(logger_map_mutex_);
register_logger_(std::move(new_logger));
}
SPDLOG_INLINE void registry::initialize_logger(std::shared_ptr<logger> new_logger)
{
std::lock_guard<std::mutex> lock(logger_map_mutex_);
new_logger->set_formatter(formatter_->clone());
if (err_handler_)
{
new_logger->set_error_handler(err_handler_);
}
new_logger->set_level(level_);
new_logger->flush_on(flush_level_);
if (backtrace_n_messages_ > 0)
{
new_logger->enable_backtrace(backtrace_n_messages_);
}
if (automatic_registration_)
{
register_logger_(std::move(new_logger));
}
}
SPDLOG_INLINE std::shared_ptr<logger> registry::get(const std::string &logger_name)
{
std::lock_guard<std::mutex> lock(logger_map_mutex_);
auto found = loggers_.find(logger_name);
return found == loggers_.end() ? nullptr : found->second;
}
SPDLOG_INLINE std::shared_ptr<logger> registry::default_logger()
{
std::lock_guard<std::mutex> lock(logger_map_mutex_);
return default_logger_;
}
// Return raw ptr to the default logger.
// To be used directly by the spdlog default api (e.g. spdlog::info)
// This make the default API faster, but cannot be used concurrently with set_default_logger().
// e.g do not call set_default_logger() from one thread while calling spdlog::info() from another.
SPDLOG_INLINE logger *registry::get_default_raw()
{
return default_logger_.get();
}
// set default logger.
// default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map.
SPDLOG_INLINE void registry::set_default_logger(std::shared_ptr<logger> new_default_logger)
{
std::lock_guard<std::mutex> lock(logger_map_mutex_);
// remove previous default logger from the map
if (default_logger_ != nullptr)
{
loggers_.erase(default_logger_->name());
}
if (new_default_logger != nullptr)
{
loggers_[new_default_logger->name()] = new_default_logger;
}
default_logger_ = std::move(new_default_logger);
}
SPDLOG_INLINE void registry::set_tp(std::shared_ptr<thread_pool> tp)
{
std::lock_guard<std::recursive_mutex> lock(tp_mutex_);
tp_ = std::move(tp);
}
SPDLOG_INLINE std::shared_ptr<thread_pool> registry::get_tp()
{
std::lock_guard<std::recursive_mutex> lock(tp_mutex_);
return tp_;
}
// Set global formatter. Each sink in each logger will get a clone of this object
SPDLOG_INLINE void registry::set_formatter(std::unique_ptr<formatter> formatter)
{
std::lock_guard<std::mutex> lock(logger_map_mutex_);
formatter_ = std::move(formatter);
for (auto &l : loggers_)
{
l.second->set_formatter(formatter_->clone());
}
}
SPDLOG_INLINE void registry::enable_backtrace(size_t n_messages)
{
std::lock_guard<std::mutex> lock(logger_map_mutex_);
backtrace_n_messages_ = n_messages;
for (auto &l : loggers_)
{
l.second->enable_backtrace(n_messages);
}
}
SPDLOG_INLINE void registry::disable_backtrace()
{
std::lock_guard<std::mutex> lock(logger_map_mutex_);
backtrace_n_messages_ = 0;
for (auto &l : loggers_)
{
l.second->disable_backtrace();
}
}
SPDLOG_INLINE void registry::set_level(level::level_enum log_level)
{
std::lock_guard<std::mutex> lock(logger_map_mutex_);
for (auto &l : loggers_)
{
l.second->set_level(log_level);
}
level_ = log_level;
}
SPDLOG_INLINE void registry::flush_on(level::level_enum log_level)
{
std::lock_guard<std::mutex> lock(logger_map_mutex_);
for (auto &l : loggers_)
{
l.second->flush_on(log_level);
}
flush_level_ = log_level;
}
SPDLOG_INLINE void registry::flush_every(std::chrono::seconds interval)
{
std::lock_guard<std::mutex> lock(flusher_mutex_);
std::function<void()> clbk = std::bind(&registry::flush_all, this);
periodic_flusher_ = details::make_unique<periodic_worker>(clbk, interval);
}
SPDLOG_INLINE void registry::set_error_handler(void (*handler)(const std::string &msg))
{
std::lock_guard<std::mutex> lock(logger_map_mutex_);
for (auto &l : loggers_)
{
l.second->set_error_handler(handler);
}
err_handler_ = handler;
}
SPDLOG_INLINE void registry::apply_all(const std::function<void(const std::shared_ptr<logger>)> &fun)
{
std::lock_guard<std::mutex> lock(logger_map_mutex_);
for (auto &l : loggers_)
{
fun(l.second);
}
}
SPDLOG_INLINE void registry::flush_all()
{
std::lock_guard<std::mutex> lock(logger_map_mutex_);
for (auto &l : loggers_)
{
l.second->flush();
}
}
SPDLOG_INLINE void registry::drop(const std::string &logger_name)
{
std::lock_guard<std::mutex> lock(logger_map_mutex_);
loggers_.erase(logger_name);
if (default_logger_ && default_logger_->name() == logger_name)
{
default_logger_.reset();
}
}
SPDLOG_INLINE void registry::drop_all()
{
std::lock_guard<std::mutex> lock(logger_map_mutex_);
loggers_.clear();
default_logger_.reset();
}
// clean all resources and threads started by the registry
SPDLOG_INLINE void registry::shutdown()
{
{
std::lock_guard<std::mutex> lock(flusher_mutex_);
periodic_flusher_.reset();
}
drop_all();
{
std::lock_guard<std::recursive_mutex> lock(tp_mutex_);
tp_.reset();
}
}
SPDLOG_INLINE std::recursive_mutex &registry::tp_mutex()
{
return tp_mutex_;
}
SPDLOG_INLINE void registry::set_automatic_registration(bool automatic_registration)
{
std::lock_guard<std::mutex> lock(logger_map_mutex_);
automatic_registration_ = automatic_registration;
}
SPDLOG_INLINE registry &registry::instance()
{
static registry s_instance;
return s_instance;
}
SPDLOG_INLINE void registry::throw_if_exists_(const std::string &logger_name)
{
if (loggers_.find(logger_name) != loggers_.end())
{
SPDLOG_THROW(spdlog_ex("logger with name '" + logger_name + "' already exists"));
}
}
SPDLOG_INLINE void registry::register_logger_(std::shared_ptr<logger> new_logger)
{
auto logger_name = new_logger->name();
throw_if_exists_(logger_name);
loggers_[logger_name] = std::move(new_logger);
}
} // namespace details
} // namespace spdlog
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
// Loggers registry of unique name->logger pointer
// An attempt to create a logger with an already existing name will result with spdlog_ex exception.
// If user requests a non existing logger, nullptr will be returned
// This class is thread safe
#include <spdlog/common.h>
#include <chrono>
#include <functional>
#include <memory>
#include <string>
#include <unordered_map>
#include <mutex>
namespace spdlog {
class logger;
namespace details {
class thread_pool;
class periodic_worker;
class registry
{
public:
registry(const registry &) = delete;
registry &operator=(const registry &) = delete;
void register_logger(std::shared_ptr<logger> new_logger);
void initialize_logger(std::shared_ptr<logger> new_logger);
std::shared_ptr<logger> get(const std::string &logger_name);
std::shared_ptr<logger> default_logger();
// Return raw ptr to the default logger.
// To be used directly by the spdlog default api (e.g. spdlog::info)
// This make the default API faster, but cannot be used concurrently with set_default_logger().
// e.g do not call set_default_logger() from one thread while calling spdlog::info() from another.
logger *get_default_raw();
// set default logger.
// default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map.
void set_default_logger(std::shared_ptr<logger> new_default_logger);
void set_tp(std::shared_ptr<thread_pool> tp);
std::shared_ptr<thread_pool> get_tp();
// Set global formatter. Each sink in each logger will get a clone of this object
void set_formatter(std::unique_ptr<formatter> formatter);
void enable_backtrace(size_t n_messages);
void disable_backtrace();
void set_level(level::level_enum log_level);
void flush_on(level::level_enum log_level);
void flush_every(std::chrono::seconds interval);
void set_error_handler(void (*handler)(const std::string &msg));
void apply_all(const std::function<void(const std::shared_ptr<logger>)> &fun);
void flush_all();
void drop(const std::string &logger_name);
void drop_all();
// clean all resources and threads started by the registry
void shutdown();
std::recursive_mutex &tp_mutex();
void set_automatic_registration(bool automatic_registration);
static registry &instance();
private:
registry();
~registry() = default;
void throw_if_exists_(const std::string &logger_name);
void register_logger_(std::shared_ptr<logger> new_logger);
std::mutex logger_map_mutex_, flusher_mutex_;
std::recursive_mutex tp_mutex_;
std::unordered_map<std::string, std::shared_ptr<logger>> loggers_;
std::unique_ptr<formatter> formatter_;
level::level_enum level_ = level::info;
level::level_enum flush_level_ = level::off;
void (*err_handler_)(const std::string &msg);
std::shared_ptr<thread_pool> tp_;
std::unique_ptr<periodic_worker> periodic_flusher_;
std::shared_ptr<logger> default_logger_;
bool automatic_registration_ = true;
size_t backtrace_n_messages_ = 0;
};
} // namespace details
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
#include "registry-inl.h"
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment