mirror of
https://gitee.com/fasiondog/hikyuu.git
synced 2024-11-30 10:59:43 +08:00
update
This commit is contained in:
parent
bf55a8e151
commit
054b18c058
@ -14,12 +14,13 @@
|
||||
#include "hikyuu/version.h"
|
||||
#include "hikyuu/DataType.h"
|
||||
#include "hikyuu/utilities/os.h"
|
||||
#include "node/NodeClient.h"
|
||||
#include "hikyuu/utilities/http_client/HttpClient.h"
|
||||
#include "sysinfo.h"
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
#define FEEDBACK_SERVER_ADDR "tcp://1.tcp.cpolar.cn:20981"
|
||||
// #define FEEDBACK_SERVER_ADDR "tcp://1.tcp.cpolar.cn:20981"
|
||||
#define FEEDBACK_SERVER_ADDR "http://127.0.0.1:80"
|
||||
|
||||
namespace hku {
|
||||
|
||||
@ -116,27 +117,15 @@ void sendFeedback() {
|
||||
saveUUID(uid);
|
||||
}
|
||||
|
||||
NodeClient client(FEEDBACK_SERVER_ADDR);
|
||||
client.dial();
|
||||
|
||||
json req, res;
|
||||
req["cmd"] = 2;
|
||||
client.post(req, res);
|
||||
std::string host = res["host"].get<std::string>();
|
||||
uint64_t port = res["port"].get<uint64_t>();
|
||||
g_latest_version = res.contains("last_version") ? res["last_version"].get<int>() : 0;
|
||||
client.close();
|
||||
|
||||
client.setServerAddr(fmt::format("tcp://{}:{}", host, port));
|
||||
client.dial();
|
||||
req["cmd"] = 1;
|
||||
HttpClient client(FEEDBACK_SERVER_ADDR);
|
||||
json req;
|
||||
req["uid"] = boost::uuids::to_string(uid);
|
||||
req["part"] = "hikyuu";
|
||||
req["version"] = HKU_VERSION;
|
||||
req["build"] = fmt::format("{}", HKU_VERSION_BUILD);
|
||||
req["platform"] = getPlatform();
|
||||
req["arch"] = getCpuArch();
|
||||
client.post(req, res);
|
||||
client.post("/hku/visit", req);
|
||||
|
||||
} catch (...) {
|
||||
// do nothing
|
||||
@ -149,24 +138,14 @@ void sendFeedback() {
|
||||
void sendPythonVersionFeedBack(int major, int minor, int micro) {
|
||||
std::thread t([=]() {
|
||||
try {
|
||||
NodeClient client(FEEDBACK_SERVER_ADDR);
|
||||
client.dial();
|
||||
|
||||
json req, res;
|
||||
req["cmd"] = 2;
|
||||
client.post(req, res);
|
||||
std::string host = res["host"].get<std::string>();
|
||||
uint64_t port = res["port"].get<uint64_t>();
|
||||
g_latest_version = res.contains("last_version") ? res["last_version"].get<int>() : 0;
|
||||
client.close();
|
||||
|
||||
client.setServerAddr(fmt::format("tcp://{}:{}", host, port));
|
||||
client.dial();
|
||||
req["cmd"] = 3;
|
||||
HttpClient client(FEEDBACK_SERVER_ADDR);
|
||||
json req;
|
||||
req["major"] = major;
|
||||
req["minor"] = minor;
|
||||
req["micro"] = micro;
|
||||
client.post(req, res);
|
||||
auto res = client.post("/hku/pyver", req);
|
||||
json r = res.json();
|
||||
g_latest_version = r["data"]["last_version"].get<int>();
|
||||
} catch (...) {
|
||||
// do nothing
|
||||
}
|
||||
|
230
hikyuu_cpp/hikyuu/utilities/LRUCache11.h
Normal file
230
hikyuu_cpp/hikyuu/utilities/LRUCache11.h
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* LRUCache11 - a templated C++11 based LRU cache class that allows
|
||||
* specification of
|
||||
* key, value and optionally the map container type (defaults to
|
||||
* std::unordered_map)
|
||||
* By using the std::unordered_map and a linked list of keys it allows O(1) insert, delete
|
||||
* and
|
||||
* refresh operations.
|
||||
*
|
||||
* This is a header-only library and all you need is the LRUCache11.hpp file
|
||||
*
|
||||
* Github: https://github.com/mohaps/lrucache11
|
||||
*
|
||||
* This is a follow-up to the LRUCache project -
|
||||
* https://github.com/mohaps/lrucache
|
||||
*
|
||||
* Copyright (c) 2012-22 SAURAV MOHAPATRA <mohaps@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and 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.
|
||||
*/
|
||||
#pragma once
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace lru11 {
|
||||
/*
|
||||
* a noop lockable concept that can be used in place of std::mutex
|
||||
*/
|
||||
class NullLock {
|
||||
public:
|
||||
void lock() {}
|
||||
void unlock() {}
|
||||
bool try_lock() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* error raised when a key not in cache is passed to get()
|
||||
*/
|
||||
class KeyNotFound : public std::invalid_argument {
|
||||
public:
|
||||
KeyNotFound() : std::invalid_argument("key_not_found") {}
|
||||
};
|
||||
|
||||
template <typename K, typename V>
|
||||
struct KeyValuePair {
|
||||
public:
|
||||
K key;
|
||||
V value;
|
||||
|
||||
KeyValuePair(K k, V v) : key(std::move(k)), value(std::move(v)) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* The LRU Cache class templated by
|
||||
* Key - key type
|
||||
* Value - value type
|
||||
* MapType - an associative container like std::unordered_map
|
||||
* LockType - a lock type derived from the Lock class (default:
|
||||
*NullLock = no synchronization)
|
||||
*
|
||||
* The default NullLock based template is not thread-safe, however passing
|
||||
*Lock=std::mutex will make it
|
||||
* thread-safe
|
||||
*/
|
||||
template <class Key, class Value, class Lock = NullLock,
|
||||
class Map =
|
||||
std::unordered_map<Key, typename std::list<KeyValuePair<Key, Value>>::iterator>>
|
||||
class Cache {
|
||||
public:
|
||||
typedef KeyValuePair<Key, Value> node_type;
|
||||
typedef std::list<KeyValuePair<Key, Value>> list_type;
|
||||
typedef Map map_type;
|
||||
typedef Lock lock_type;
|
||||
using Guard = std::lock_guard<lock_type>;
|
||||
/**
|
||||
* the maxSize is the soft limit of keys and (maxSize + elasticity) is the
|
||||
* hard limit
|
||||
* the cache is allowed to grow till (maxSize + elasticity) and is pruned back
|
||||
* to maxSize keys
|
||||
* set maxSize = 0 for an unbounded cache (but in that case, you're better off
|
||||
* using a std::unordered_map
|
||||
* directly anyway! :)
|
||||
*/
|
||||
explicit Cache(size_t maxSize = 64, size_t elasticity = 10)
|
||||
: maxSize_(maxSize), elasticity_(elasticity) {}
|
||||
virtual ~Cache() = default;
|
||||
size_t size() const {
|
||||
Guard g(lock_);
|
||||
return cache_.size();
|
||||
}
|
||||
bool empty() const {
|
||||
Guard g(lock_);
|
||||
return cache_.empty();
|
||||
}
|
||||
void clear() {
|
||||
Guard g(lock_);
|
||||
cache_.clear();
|
||||
keys_.clear();
|
||||
}
|
||||
void insert(const Key& k, const Value& v) {
|
||||
Guard g(lock_);
|
||||
const auto iter = cache_.find(k);
|
||||
if (iter != cache_.end()) {
|
||||
iter->second->value = v;
|
||||
keys_.splice(keys_.begin(), keys_, iter->second);
|
||||
return;
|
||||
}
|
||||
|
||||
keys_.emplace_front(k, v);
|
||||
cache_[k] = keys_.begin();
|
||||
prune();
|
||||
}
|
||||
void insert(const Key& k, Value&& v) {
|
||||
Guard g(lock_);
|
||||
const auto iter = cache_.find(k);
|
||||
if (iter != cache_.end()) {
|
||||
iter->second->value = std::move(v);
|
||||
keys_.splice(keys_.begin(), keys_, iter->second);
|
||||
return;
|
||||
}
|
||||
|
||||
keys_.emplace_front(k, std::move(v));
|
||||
cache_[k] = keys_.begin();
|
||||
prune();
|
||||
}
|
||||
bool tryGet(const Key& kIn, Value& vOut) {
|
||||
Guard g(lock_);
|
||||
const auto iter = cache_.find(kIn);
|
||||
if (iter == cache_.end()) {
|
||||
return false;
|
||||
}
|
||||
keys_.splice(keys_.begin(), keys_, iter->second);
|
||||
vOut = iter->second->value;
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* The const reference returned here is only
|
||||
* guaranteed to be valid till the next insert/delete
|
||||
* 修改为非常量引用,以便修改。但请注意这是危险操作!
|
||||
*/
|
||||
Value& get(const Key& k) {
|
||||
Guard g(lock_);
|
||||
const auto iter = cache_.find(k);
|
||||
if (iter == cache_.end()) {
|
||||
throw KeyNotFound();
|
||||
}
|
||||
keys_.splice(keys_.begin(), keys_, iter->second);
|
||||
return iter->second->value;
|
||||
}
|
||||
/**
|
||||
* returns a copy of the stored object (if found)
|
||||
*/
|
||||
Value getCopy(const Key& k) {
|
||||
return get(k);
|
||||
}
|
||||
bool remove(const Key& k) {
|
||||
Guard g(lock_);
|
||||
auto iter = cache_.find(k);
|
||||
if (iter == cache_.end()) {
|
||||
return false;
|
||||
}
|
||||
keys_.erase(iter->second);
|
||||
cache_.erase(iter);
|
||||
return true;
|
||||
}
|
||||
bool contains(const Key& k) const {
|
||||
Guard g(lock_);
|
||||
return cache_.find(k) != cache_.end();
|
||||
}
|
||||
|
||||
size_t getMaxSize() const {
|
||||
return maxSize_;
|
||||
}
|
||||
size_t getElasticity() const {
|
||||
return elasticity_;
|
||||
}
|
||||
size_t getMaxAllowedSize() const {
|
||||
return maxSize_ + elasticity_;
|
||||
}
|
||||
template <typename F>
|
||||
void cwalk(F& f) const {
|
||||
Guard g(lock_);
|
||||
std::for_each(keys_.begin(), keys_.end(), f);
|
||||
}
|
||||
|
||||
protected:
|
||||
size_t prune() {
|
||||
size_t maxAllowed = maxSize_ + elasticity_;
|
||||
if (maxSize_ == 0 || cache_.size() < maxAllowed) {
|
||||
return 0;
|
||||
}
|
||||
size_t count = 0;
|
||||
while (cache_.size() > maxSize_) {
|
||||
cache_.erase(keys_.back().key);
|
||||
keys_.pop_back();
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private:
|
||||
// Disallow copying.
|
||||
Cache(const Cache&) = delete;
|
||||
Cache& operator=(const Cache&) = delete;
|
||||
|
||||
mutable Lock lock_;
|
||||
Map cache_;
|
||||
list_type keys_;
|
||||
size_t maxSize_;
|
||||
size_t elasticity_;
|
||||
};
|
||||
|
||||
} // namespace lru11
|
142
hikyuu_cpp/hikyuu/utilities/any_to_string.h
Normal file
142
hikyuu_cpp/hikyuu/utilities/any_to_string.h
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2023 hikyuu.org
|
||||
*
|
||||
* Created on: 2023-01-15
|
||||
* Author: fasiondog
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "osdef.h"
|
||||
#include "cppdef.h"
|
||||
#if !HKU_OS_IOS && CPP_STANDARD >= CPP_STANDARD_17
|
||||
#include <any>
|
||||
#else
|
||||
#include <boost/any.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(HKU_SUPPORT_DATETIME)
|
||||
#include "hikyuu/utilities/datetime/Datetime.h"
|
||||
#endif
|
||||
|
||||
namespace hku {
|
||||
|
||||
#if !HKU_OS_IOS && CPP_STANDARD >= CPP_STANDARD_17
|
||||
using any_t = std::any;
|
||||
using std::any_cast;
|
||||
#else
|
||||
using any_t = boost::any;
|
||||
using boost::any_cast;
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// 常见基本类型包装的 any_t 和 std::string 的互相转换函数
|
||||
// any_to_string 要用户自定义类型需包含从 std::string 进行构造的构造函数
|
||||
// string_to_any 需要用户自定义实现 std::to_string 特化方法
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <typename ValueT>
|
||||
inline std::string any_to_string(const any_t& data) {
|
||||
return any_cast<ValueT>(data).str();
|
||||
}
|
||||
|
||||
template <typename ValueT>
|
||||
inline any_t string_to_any(const std::string& data) {
|
||||
return any_t(ValueT(data));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::string any_to_string<int>(const any_t& data) {
|
||||
return std::to_string(any_cast<int>(data));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::string any_to_string<long>(const any_t& data) {
|
||||
return std::to_string(any_cast<long>(data));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::string any_to_string<long long>(const any_t& data) {
|
||||
return std::to_string(any_cast<long long>(data));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::string any_to_string<unsigned int>(const any_t& data) {
|
||||
return std::to_string(any_cast<unsigned int>(data));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::string any_to_string<unsigned long>(const any_t& data) {
|
||||
return std::to_string(any_cast<unsigned long>(data));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::string any_to_string<unsigned long long>(const any_t& data) {
|
||||
return std::to_string(any_cast<unsigned long long>(data));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::string any_to_string<float>(const any_t& data) {
|
||||
return std::to_string(any_cast<float>(data));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::string any_to_string<double>(const any_t& data) {
|
||||
return std::to_string(any_cast<double>(data));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::string any_to_string<long double>(const any_t& data) {
|
||||
return std::to_string(any_cast<long double>(data));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline any_t string_to_any<int>(const std::string& data) {
|
||||
return any_t(std::stoi(data));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline any_t string_to_any<long>(const std::string& data) {
|
||||
return any_t(std::stol(data));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline any_t string_to_any<long long>(const std::string& data) {
|
||||
return any_t(std::stoll(data));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline any_t string_to_any<unsigned int>(const std::string& data) {
|
||||
return any_t((unsigned int)(std::stoul(data)));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline any_t string_to_any<unsigned long>(const std::string& data) {
|
||||
return any_t(std::stoul(data));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline any_t string_to_any<unsigned long long>(const std::string& data) {
|
||||
return any_t(std::stoull(data));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline any_t string_to_any<float>(const std::string& data) {
|
||||
return any_t(std::stof(data));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline any_t string_to_any<double>(const std::string& data) {
|
||||
return any_t(std::stod(data));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline any_t string_to_any<long double>(const std::string& data) {
|
||||
return any_t(std::stold(data));
|
||||
}
|
||||
|
||||
} // namespace hku
|
@ -166,6 +166,10 @@ public:
|
||||
return post(path, HttpParams(), headers, body);
|
||||
}
|
||||
|
||||
HttpResponse post(const std::string& path, const json& body) {
|
||||
return post(path, HttpHeaders(), body);
|
||||
}
|
||||
|
||||
private:
|
||||
void _connect();
|
||||
HttpResponse _readResChunk(const std::string& method, const std::string& uri,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* IniFile.cpp
|
||||
*
|
||||
* Created on: 2010-5-19
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* IniFile.h
|
||||
*
|
||||
* Created on: 2010-5-19
|
||||
|
291
hikyuu_cpp/hikyuu/utilities/md5.cpp
Normal file
291
hikyuu_cpp/hikyuu/utilities/md5.cpp
Normal file
@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Copyright (c) hikyuu
|
||||
* Created on: 2021/12/06
|
||||
* Author: fasiondog
|
||||
*
|
||||
* 注: boost的md5计算在windows和linux平台上结果不一致,所以改从 dlib 移植
|
||||
*/
|
||||
|
||||
#include "arithmetic.h"
|
||||
#include "md5.h"
|
||||
#include "Log.h"
|
||||
|
||||
namespace hku {
|
||||
|
||||
inline uint32_t F(uint32_t x, uint32_t y, uint32_t z) {
|
||||
return ((x & y) | ((~x) & z));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
inline uint32_t G(uint32_t x, uint32_t y, uint32_t z) {
|
||||
return ((x & z) | (y & (~z)));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
inline uint32_t H(uint32_t x, uint32_t y, uint32_t z) {
|
||||
return (x ^ y ^ z);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
inline uint32_t I(uint32_t x, uint32_t y, uint32_t z) {
|
||||
return (y ^ (x | (~z)));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
inline uint32_t rotate_left(uint32_t x, uint32_t n) {
|
||||
return ((x << n) | (x >> (32 - n)));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
inline void FF(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s,
|
||||
uint32_t ac) {
|
||||
a += F(b, c, d) + x + ac;
|
||||
a = rotate_left(a, s);
|
||||
a += b;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
inline void GG(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s,
|
||||
uint32_t ac) {
|
||||
a += G(b, c, d) + x + ac;
|
||||
a = rotate_left(a, s);
|
||||
a += b;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
inline void HH(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s,
|
||||
uint32_t ac) {
|
||||
a += H(b, c, d) + x + ac;
|
||||
a = rotate_left(a, s);
|
||||
a += b;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
inline void II(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s,
|
||||
uint32_t ac) {
|
||||
a += I(b, c, d) + x + ac;
|
||||
a = rotate_left(a, s);
|
||||
a += b;
|
||||
}
|
||||
|
||||
void scramble_block(uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d, uint32_t* x) {
|
||||
const uint32_t S11 = 7;
|
||||
const uint32_t S12 = 12;
|
||||
const uint32_t S13 = 17;
|
||||
const uint32_t S14 = 22;
|
||||
const uint32_t S21 = 5;
|
||||
const uint32_t S22 = 9;
|
||||
const uint32_t S23 = 14;
|
||||
const uint32_t S24 = 20;
|
||||
const uint32_t S31 = 4;
|
||||
const uint32_t S32 = 11;
|
||||
const uint32_t S33 = 16;
|
||||
const uint32_t S34 = 23;
|
||||
const uint32_t S41 = 6;
|
||||
const uint32_t S42 = 10;
|
||||
const uint32_t S43 = 15;
|
||||
const uint32_t S44 = 21;
|
||||
|
||||
// round 1
|
||||
FF(a, b, c, d, x[0], S11, 0xd76aa478); // 1
|
||||
FF(d, a, b, c, x[1], S12, 0xe8c7b756); // 2
|
||||
FF(c, d, a, b, x[2], S13, 0x242070db); // 3
|
||||
FF(b, c, d, a, x[3], S14, 0xc1bdceee); // 4
|
||||
FF(a, b, c, d, x[4], S11, 0xf57c0faf); // 5
|
||||
FF(d, a, b, c, x[5], S12, 0x4787c62a); // 6
|
||||
FF(c, d, a, b, x[6], S13, 0xa8304613); // 7
|
||||
FF(b, c, d, a, x[7], S14, 0xfd469501); // 8
|
||||
FF(a, b, c, d, x[8], S11, 0x698098d8); // 9
|
||||
FF(d, a, b, c, x[9], S12, 0x8b44f7af); // 10
|
||||
FF(c, d, a, b, x[10], S13, 0xffff5bb1); // 11
|
||||
FF(b, c, d, a, x[11], S14, 0x895cd7be); // 12
|
||||
FF(a, b, c, d, x[12], S11, 0x6b901122); // 13
|
||||
FF(d, a, b, c, x[13], S12, 0xfd987193); // 14
|
||||
FF(c, d, a, b, x[14], S13, 0xa679438e); // 15
|
||||
FF(b, c, d, a, x[15], S14, 0x49b40821); // 16
|
||||
|
||||
// Round 2
|
||||
GG(a, b, c, d, x[1], S21, 0xf61e2562); // 17
|
||||
GG(d, a, b, c, x[6], S22, 0xc040b340); // 18
|
||||
GG(c, d, a, b, x[11], S23, 0x265e5a51); // 19
|
||||
GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); // 20
|
||||
GG(a, b, c, d, x[5], S21, 0xd62f105d); // 21
|
||||
GG(d, a, b, c, x[10], S22, 0x2441453); // 22
|
||||
GG(c, d, a, b, x[15], S23, 0xd8a1e681); // 23
|
||||
GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); // 24
|
||||
GG(a, b, c, d, x[9], S21, 0x21e1cde6); // 25
|
||||
GG(d, a, b, c, x[14], S22, 0xc33707d6); // 26
|
||||
GG(c, d, a, b, x[3], S23, 0xf4d50d87); // 27
|
||||
GG(b, c, d, a, x[8], S24, 0x455a14ed); // 28
|
||||
GG(a, b, c, d, x[13], S21, 0xa9e3e905); // 29
|
||||
GG(d, a, b, c, x[2], S22, 0xfcefa3f8); // 30
|
||||
GG(c, d, a, b, x[7], S23, 0x676f02d9); // 31
|
||||
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); // 32
|
||||
|
||||
// Round 3
|
||||
HH(a, b, c, d, x[5], S31, 0xfffa3942); // 33
|
||||
HH(d, a, b, c, x[8], S32, 0x8771f681); // 34
|
||||
HH(c, d, a, b, x[11], S33, 0x6d9d6122); // 35
|
||||
HH(b, c, d, a, x[14], S34, 0xfde5380c); // 36
|
||||
HH(a, b, c, d, x[1], S31, 0xa4beea44); // 37
|
||||
HH(d, a, b, c, x[4], S32, 0x4bdecfa9); // 38
|
||||
HH(c, d, a, b, x[7], S33, 0xf6bb4b60); // 39
|
||||
HH(b, c, d, a, x[10], S34, 0xbebfbc70); // 40
|
||||
HH(a, b, c, d, x[13], S31, 0x289b7ec6); // 41
|
||||
HH(d, a, b, c, x[0], S32, 0xeaa127fa); // 42
|
||||
HH(c, d, a, b, x[3], S33, 0xd4ef3085); // 43
|
||||
HH(b, c, d, a, x[6], S34, 0x4881d05); // 44
|
||||
HH(a, b, c, d, x[9], S31, 0xd9d4d039); // 45
|
||||
HH(d, a, b, c, x[12], S32, 0xe6db99e5); // 46
|
||||
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); // 47
|
||||
HH(b, c, d, a, x[2], S34, 0xc4ac5665); // 48
|
||||
|
||||
// Round 4
|
||||
II(a, b, c, d, x[0], S41, 0xf4292244); // 49
|
||||
II(d, a, b, c, x[7], S42, 0x432aff97); // 50
|
||||
II(c, d, a, b, x[14], S43, 0xab9423a7); // 51
|
||||
II(b, c, d, a, x[5], S44, 0xfc93a039); // 52
|
||||
II(a, b, c, d, x[12], S41, 0x655b59c3); // 53
|
||||
II(d, a, b, c, x[3], S42, 0x8f0ccc92); // 54
|
||||
II(c, d, a, b, x[10], S43, 0xffeff47d); // 55
|
||||
II(b, c, d, a, x[1], S44, 0x85845dd1); // 56
|
||||
II(a, b, c, d, x[8], S41, 0x6fa87e4f); // 57
|
||||
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); // 58
|
||||
II(c, d, a, b, x[6], S43, 0xa3014314); // 59
|
||||
II(b, c, d, a, x[13], S44, 0x4e0811a1); // 60
|
||||
II(a, b, c, d, x[4], S41, 0xf7537e82); // 61
|
||||
II(d, a, b, c, x[11], S42, 0xbd3af235); // 62
|
||||
II(c, d, a, b, x[2], S43, 0x2ad7d2bb); // 63
|
||||
II(b, c, d, a, x[9], S44, 0xeb86d391); // 64
|
||||
}
|
||||
|
||||
std::string HKU_UTILS_API md5(const unsigned char* input, size_t len) {
|
||||
HKU_CHECK(input, "char *buf is null!");
|
||||
// make a temp version of input with enough space for padding and len appended
|
||||
unsigned long extra_len = 64 - len % 64;
|
||||
if (extra_len <= 8)
|
||||
extra_len += 64;
|
||||
unsigned char* temp = new unsigned char[extra_len + len];
|
||||
|
||||
// number of 16 word blocks
|
||||
const unsigned long N = (extra_len + static_cast<unsigned long>(len)) / 64;
|
||||
|
||||
const unsigned char* input2 = input;
|
||||
unsigned char* temp2 = temp;
|
||||
unsigned char* end = temp + len;
|
||||
|
||||
// copy input into temp
|
||||
while (temp2 != end) {
|
||||
*temp2 = *input2;
|
||||
++temp2;
|
||||
++input2;
|
||||
}
|
||||
|
||||
// pad temp
|
||||
end += extra_len - 8;
|
||||
*temp2 = static_cast<unsigned char>(0x80);
|
||||
++temp2;
|
||||
while (temp2 != end) {
|
||||
*temp2 = 0;
|
||||
++temp2;
|
||||
}
|
||||
|
||||
// make len the number of bits in the original message
|
||||
// but first multiply len by 8 and since len is only 32 bits the number might
|
||||
// overflow so we will carry out the multiplication manually and end up with
|
||||
// the result in the base 65536 number with three digits
|
||||
// result = low + high*65536 + upper*65536*65536
|
||||
unsigned long low = len & 0xFFFF;
|
||||
unsigned long high = static_cast<unsigned long>(len) >> 16;
|
||||
unsigned long upper;
|
||||
unsigned long tmp;
|
||||
tmp = low * 8;
|
||||
low = tmp & 0xFFFF;
|
||||
tmp = high * 8 + (tmp >> 16);
|
||||
high = tmp & 0xFFFF;
|
||||
upper = tmp >> 16;
|
||||
|
||||
// append the length
|
||||
*temp2 = static_cast<unsigned char>(low & 0xFF);
|
||||
++temp2;
|
||||
*temp2 = static_cast<unsigned char>((low >> 8) & 0xFF);
|
||||
++temp2;
|
||||
*temp2 = static_cast<unsigned char>((high) & 0xFF);
|
||||
++temp2;
|
||||
*temp2 = static_cast<unsigned char>((high >> 8) & 0xFF);
|
||||
++temp2;
|
||||
*temp2 = static_cast<unsigned char>((upper) & 0xFF);
|
||||
;
|
||||
++temp2;
|
||||
*temp2 = static_cast<unsigned char>((upper >> 8) & 0xFF);
|
||||
;
|
||||
++temp2;
|
||||
*temp2 = 0;
|
||||
++temp2;
|
||||
*temp2 = 0;
|
||||
|
||||
uint32_t a = 0x67452301;
|
||||
uint32_t b = 0xefcdab89;
|
||||
uint32_t c = 0x98badcfe;
|
||||
uint32_t d = 0x10325476;
|
||||
|
||||
// an array of 16 words
|
||||
uint32_t x[16];
|
||||
|
||||
for (unsigned long i = 0; i < N; ++i) {
|
||||
// copy a block of 16 words from m into x
|
||||
for (unsigned long j = 0; j < 16; ++j) {
|
||||
x[j] = ((static_cast<uint32_t>(temp[4 * (j + 16 * i) + 3]) << 24) |
|
||||
(static_cast<uint32_t>(temp[4 * (j + 16 * i) + 2]) << 16) |
|
||||
(static_cast<uint32_t>(temp[4 * (j + 16 * i) + 1]) << 8) |
|
||||
(static_cast<uint32_t>(temp[4 * (j + 16 * i)])));
|
||||
}
|
||||
|
||||
uint32_t aa = a;
|
||||
uint32_t bb = b;
|
||||
uint32_t cc = c;
|
||||
uint32_t dd = d;
|
||||
|
||||
scramble_block(a, b, c, d, x);
|
||||
|
||||
a = a + aa;
|
||||
b = b + bb;
|
||||
c = c + cc;
|
||||
d = d + dd;
|
||||
}
|
||||
|
||||
unsigned char output[16];
|
||||
// put a, b, c, and d into output
|
||||
output[0] = static_cast<unsigned char>((a) & 0xFF);
|
||||
output[1] = static_cast<unsigned char>((a >> 8) & 0xFF);
|
||||
output[2] = static_cast<unsigned char>((a >> 16) & 0xFF);
|
||||
output[3] = static_cast<unsigned char>((a >> 24) & 0xFF);
|
||||
|
||||
output[4] = static_cast<unsigned char>((b) & 0xFF);
|
||||
output[5] = static_cast<unsigned char>((b >> 8) & 0xFF);
|
||||
output[6] = static_cast<unsigned char>((b >> 16) & 0xFF);
|
||||
output[7] = static_cast<unsigned char>((b >> 24) & 0xFF);
|
||||
|
||||
output[8] = static_cast<unsigned char>((c) & 0xFF);
|
||||
output[9] = static_cast<unsigned char>((c >> 8) & 0xFF);
|
||||
output[10] = static_cast<unsigned char>((c >> 16) & 0xFF);
|
||||
output[11] = static_cast<unsigned char>((c >> 24) & 0xFF);
|
||||
|
||||
output[12] = static_cast<unsigned char>((d) & 0xFF);
|
||||
output[13] = static_cast<unsigned char>((d >> 8) & 0xFF);
|
||||
output[14] = static_cast<unsigned char>((d >> 16) & 0xFF);
|
||||
output[15] = static_cast<unsigned char>((d >> 24) & 0xFF);
|
||||
|
||||
delete[] temp;
|
||||
return byteToHexStr((const char*)output, 16);
|
||||
}
|
||||
|
||||
} // namespace hku
|
41
hikyuu_cpp/hikyuu/utilities/md5.h
Normal file
41
hikyuu_cpp/hikyuu/utilities/md5.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2019~2021, hikyuu
|
||||
*
|
||||
* Created on: 2021/12/06
|
||||
* Author: fasiondog
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef HKU_UTILS_MD5_H
|
||||
#define HKU_UTILS_MD5_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifndef HKU_UTILS_API
|
||||
#define HKU_UTILS_API
|
||||
#endif
|
||||
|
||||
namespace hku {
|
||||
|
||||
/**
|
||||
* @brief 计算 md5 值
|
||||
*
|
||||
* @param input 待计算数据起始指针
|
||||
* @param len 待计算数据字节长度
|
||||
* @return std::string
|
||||
*/
|
||||
std::string HKU_UTILS_API md5(const unsigned char* input, size_t len);
|
||||
|
||||
/**
|
||||
* @brief 计算字符串 md5
|
||||
*
|
||||
* @param src 待计算的字符串
|
||||
* @return std::string
|
||||
*/
|
||||
inline std::string md5(const std::string& src) {
|
||||
return md5((const unsigned char*)src.data(), src.size());
|
||||
}
|
||||
|
||||
} // namespace hku
|
||||
|
||||
#endif // #define HKU_UTILS_MD5_H
|
@ -7,6 +7,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hikyuu/utilities/config.h"
|
||||
#if !HKU_ENABLE_NODE
|
||||
#error "Don't enable node client, please config with --node=y"
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
#include <nng/nng.h>
|
||||
#include <nng/protocol/reqrep0/req.h>
|
||||
@ -59,13 +64,11 @@ public:
|
||||
|
||||
return true;
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
HKU_ERROR_IF(m_show_log, "Failed dail server: {}! {}", m_server_addr, e.what());
|
||||
} catch (...) {
|
||||
HKU_ERROR_IF(m_show_log, "Failed dail server: {}! Unknown error!", m_server_addr);
|
||||
}
|
||||
// } catch (const std::exception& e) {
|
||||
// HKU_ERROR("Failed dail server: {}! {}", m_server_addr, e.what());
|
||||
// } catch (...) {
|
||||
// HKU_ERROR("Failed dail server: {}! Unknown error!", m_server_addr);
|
||||
// }
|
||||
|
||||
m_connected = false;
|
||||
nng_close(m_socket);
|
||||
@ -101,6 +104,10 @@ public:
|
||||
return _send(req) && _recv(res);
|
||||
}
|
||||
|
||||
void showLog(bool show) {
|
||||
m_show_log = show;
|
||||
}
|
||||
|
||||
private:
|
||||
bool _send(const json& req) const noexcept {
|
||||
bool success = false;
|
||||
@ -118,13 +125,11 @@ private:
|
||||
NODE_NNG_CHECK(rv, "Failed nng_sendmsg!");
|
||||
success = true;
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
HKU_ERROR_IF(m_show_log, "Failed send result! {}", e.what());
|
||||
} catch (...) {
|
||||
HKU_ERROR_IF(m_show_log, "Failed send result! Unknown error!");
|
||||
}
|
||||
// } catch (const std::exception& e) {
|
||||
// HKU_ERROR("Failed send result! {}", e.what());
|
||||
// } catch (...) {
|
||||
// HKU_ERROR("Failed send result! Unknown error!");
|
||||
// }
|
||||
|
||||
if (!success) {
|
||||
nng_msg_free(msg);
|
||||
@ -137,21 +142,22 @@ private:
|
||||
bool success = false;
|
||||
nng_msg* msg{nullptr};
|
||||
int rv = nng_recvmsg(m_socket, &msg, 0);
|
||||
// HKU_ERROR_IF_RETURN(rv != 0, success, "Failed nng_recvmsg! {}", nng_strerror(rv));
|
||||
HKU_IF_RETURN(rv != 0, success);
|
||||
if (rv != 0) {
|
||||
HKU_ERROR_IF(m_show_log, "Failed nng_recvmsg! {}", nng_strerror(rv));
|
||||
return success;
|
||||
}
|
||||
|
||||
m_last_ack_time = Datetime::now();
|
||||
|
||||
try {
|
||||
res = decodeMsg(msg);
|
||||
success = true;
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
HKU_ERROR_IF(m_show_log, "Failed recv response! {}", e.what());
|
||||
} catch (...) {
|
||||
HKU_ERROR_IF(m_show_log, "Failed recv response! Unknown error!");
|
||||
}
|
||||
// } catch (const std::exception& e) {
|
||||
// HKU_ERROR("Failed recv response! {}", e.what());
|
||||
// } catch (...) {
|
||||
// HKU_ERROR("Failed recv response! Unknown error!");
|
||||
// }
|
||||
|
||||
nng_msg_free(msg);
|
||||
return success;
|
||||
@ -161,8 +167,9 @@ private:
|
||||
std::mutex m_mutex;
|
||||
std::string m_server_addr; // 服务端地址
|
||||
nng_socket m_socket;
|
||||
std::atomic_bool m_connected{false};
|
||||
Datetime m_last_ack_time{Datetime::now()}; // 最后一次接收服务端响应的时间
|
||||
std::atomic_bool m_connected{false};
|
||||
std::atomic_bool m_show_log{true};
|
||||
};
|
||||
|
||||
} // namespace hku
|
@ -7,7 +7,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hikyuu/utilities/exception.h"
|
||||
#include <hikyuu/utilities/exception.h>
|
||||
|
||||
namespace hku {
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <vector>
|
||||
#include <nng/nng.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <hikyuu/utilities/Log.h>
|
||||
#include "NodeError.h"
|
||||
|
||||
using json = nlohmann::json;
|
||||
@ -26,8 +27,8 @@ namespace hku {
|
||||
* req ->
|
||||
* {"cmd": int, ...}
|
||||
*
|
||||
* req ->
|
||||
* {"cmd": int, "ret": code, "msg": str}
|
||||
* <- res
|
||||
* {"ret": code, "msg": str} // msg 存在错误时返回错误信息 (可选)
|
||||
*
|
||||
*
|
||||
*/
|
249
hikyuu_cpp/hikyuu/utilities/node/NodeServer.h
Normal file
249
hikyuu_cpp/hikyuu/utilities/node/NodeServer.h
Normal file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright (c) 2022 hikyuu.org
|
||||
*
|
||||
* Created on: 2022-04-15
|
||||
* Author: fasiondog
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hikyuu/utilities/config.h"
|
||||
#if !HKU_ENABLE_NODE
|
||||
#error "Don't enable node server, please config with --node=y"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <nng/nng.h>
|
||||
#include <nng/protocol/reqrep0/rep.h>
|
||||
|
||||
#include <hikyuu/utilities/osdef.h>
|
||||
#if HKU_OS_WINDOWS
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include <WS2tcpip.h>
|
||||
#include <Ws2ipdef.h>
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "hikyuu/utilities/Log.h"
|
||||
#include "NodeMessage.h"
|
||||
|
||||
namespace hku {
|
||||
|
||||
class NodeServer {
|
||||
CLASS_LOGGER_IMP(NodeServer)
|
||||
|
||||
private:
|
||||
static constexpr size_t PARALLEL = 128;
|
||||
|
||||
public:
|
||||
NodeServer() = default;
|
||||
explicit NodeServer(const std::string& addr) : m_addr(addr) {}
|
||||
virtual ~NodeServer() {
|
||||
stop();
|
||||
}
|
||||
|
||||
void setAddr(const std::string& addr) {
|
||||
m_addr = addr;
|
||||
}
|
||||
|
||||
void regHandle(const std::string& cmd, const std::function<json(json&& req)>& handle) {
|
||||
m_handles[cmd] = handle;
|
||||
}
|
||||
|
||||
void regHandle(const std::string& cmd, std::function<json(json&& req)>&& handle) {
|
||||
m_handles[cmd] = std::move(handle);
|
||||
}
|
||||
|
||||
void start() {
|
||||
CLS_CHECK(!m_addr.empty(), "You must set NodeServer's addr first!");
|
||||
|
||||
// 启动 node server
|
||||
int rv = nng_rep0_open(&m_socket);
|
||||
CLS_CHECK(0 == rv, "Failed open server socket! {}", nng_strerror(rv));
|
||||
rv = nng_listen(m_socket, m_addr.c_str(), &m_listener, 0);
|
||||
CLS_CHECK(0 == rv, "Failed listen node server socket ({})! {}", m_addr, nng_strerror(rv));
|
||||
CLS_TRACE("channel lisenter server: {}", m_addr);
|
||||
|
||||
m_works.resize(PARALLEL);
|
||||
for (size_t i = 0, total = m_works.size(); i < total; i++) {
|
||||
Work* w = &m_works[i];
|
||||
rv = nng_aio_alloc(&w->aio, _serverCallback, w);
|
||||
CLS_CHECK(0 == rv, "Failed create work {}! {}", i, nng_strerror(rv));
|
||||
rv = nng_ctx_open(&w->ctx, m_socket);
|
||||
CLS_CHECK(0 == rv, "Failed open ctx {}! {}", i, nng_strerror(rv));
|
||||
w->state = Work::INIT;
|
||||
w->server = this;
|
||||
}
|
||||
|
||||
for (size_t i = 0, total = m_works.size(); i < total; i++) {
|
||||
_serverCallback(&m_works[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
while (true) {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
}
|
||||
|
||||
void stop() {
|
||||
HKU_IF_RETURN(m_works.empty(), void());
|
||||
for (size_t i = 0, total = m_works.size(); i < total; i++) {
|
||||
Work* w = &m_works[i];
|
||||
w->server = nullptr;
|
||||
w->state = Work::FINISH;
|
||||
if (w->aio) {
|
||||
nng_aio_stop(w->aio);
|
||||
nng_aio_free(w->aio);
|
||||
nng_ctx_close(w->ctx);
|
||||
w->aio = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭 socket 服务节点
|
||||
nng_listener_close(m_listener);
|
||||
nng_close(m_socket);
|
||||
m_works.clear();
|
||||
CLS_INFO("stopped node server.");
|
||||
}
|
||||
|
||||
private:
|
||||
struct Work {
|
||||
enum { INIT, RECV, SEND, FINISH } state = INIT;
|
||||
nng_aio* aio{nullptr};
|
||||
nng_ctx ctx;
|
||||
NodeServer* server{nullptr};
|
||||
};
|
||||
|
||||
static void _serverCallback(void* arg) {
|
||||
Work* work = static_cast<Work*>(arg);
|
||||
int rv = 0;
|
||||
switch (work->state) {
|
||||
case Work::INIT:
|
||||
work->state = Work::RECV;
|
||||
nng_ctx_recv(work->ctx, work->aio);
|
||||
break;
|
||||
|
||||
case Work::RECV:
|
||||
_processRequest(work);
|
||||
break;
|
||||
|
||||
case Work::SEND:
|
||||
if ((rv = nng_aio_result(work->aio)) != 0) {
|
||||
CLS_FATAL("Failed nng_ctx_send! {}", nng_strerror(rv));
|
||||
work->state = Work::FINISH;
|
||||
return;
|
||||
}
|
||||
work->state = Work::RECV;
|
||||
nng_ctx_recv(work->ctx, work->aio);
|
||||
break;
|
||||
|
||||
case Work::FINISH:
|
||||
break;
|
||||
|
||||
default:
|
||||
CLS_FATAL("nng bad state!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _processRequest(Work* work) {
|
||||
NodeServer* server = work->server;
|
||||
CLS_IF_RETURN(!server || !work->aio, void());
|
||||
nng_msg* msg = nullptr;
|
||||
json res;
|
||||
|
||||
try {
|
||||
int rv = nng_aio_result(work->aio);
|
||||
HKU_CHECK(rv == 0, "Failed nng_aio_result!");
|
||||
|
||||
msg = nng_aio_get_msg(work->aio);
|
||||
json req = decodeMsg(msg);
|
||||
NODE_CHECK(req.contains("cmd"), NodeErrorCode::MISSING_CMD, "Missing command!");
|
||||
|
||||
// 兼容老版本数字cmd
|
||||
std::string cmd = req["cmd"].is_number() ? fmt::format("{}", req["cmd"].get<int>())
|
||||
: req["cmd"].get<std::string>();
|
||||
auto iter = server->m_handles.find(cmd);
|
||||
NODE_CHECK(iter != server->m_handles.end(), NodeErrorCode::INVALID_CMD,
|
||||
"The server does not know how to process the message: {}", cmd);
|
||||
|
||||
// tcp 连接尝试获取客户端地址和端口加入 req 中
|
||||
req["remote_host"] = "";
|
||||
req["remote_port"] = 0;
|
||||
nng_pipe p = nng_msg_get_pipe(msg);
|
||||
if (nng_pipe_id(p) > 0) {
|
||||
uint16_t port = 0;
|
||||
nng_sockaddr ra;
|
||||
rv = nng_pipe_get_addr(p, NNG_OPT_REMADDR, &ra);
|
||||
if (rv == 0) {
|
||||
if (ra.s_family == NNG_AF_INET) {
|
||||
char ipAddr[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, (void*)&ra.s_in.sa_addr, ipAddr, INET_ADDRSTRLEN);
|
||||
port = ntohs(ra.s_in.sa_port);
|
||||
req["remote_host"] = ipAddr;
|
||||
req["remote_port"] = port;
|
||||
} else if (ra.s_family == NNG_AF_INET6) {
|
||||
char ipAddr[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, (void*)&ra.s_in.sa_addr, ipAddr, INET6_ADDRSTRLEN);
|
||||
port = ntohs(ra.s_in6.sa_port);
|
||||
req["remote_host"] = ipAddr;
|
||||
req["remote_port"] = port;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res = iter->second(std::move(req));
|
||||
res["ret"] = NodeErrorCode::SUCCESS;
|
||||
encodeMsg(msg, res);
|
||||
|
||||
nng_aio_set_msg(work->aio, msg);
|
||||
work->state = Work::SEND;
|
||||
nng_ctx_send(work->ctx, work->aio);
|
||||
|
||||
} catch (const NodeNngError& e) {
|
||||
CLS_FATAL(e.what());
|
||||
work->state = Work::FINISH;
|
||||
|
||||
} catch (const NodeError& e) {
|
||||
CLS_ERROR(e.what());
|
||||
res["ret"] = e.errcode();
|
||||
res["msg"] = e.what();
|
||||
encodeMsg(msg, res);
|
||||
nng_aio_set_msg(work->aio, msg);
|
||||
work->state = Work::SEND;
|
||||
nng_ctx_send(work->ctx, work->aio);
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
CLS_ERROR(e.what());
|
||||
res["ret"] = NodeErrorCode::UNKNOWN_ERROR;
|
||||
res["msg"] = e.what();
|
||||
encodeMsg(msg, res);
|
||||
nng_aio_set_msg(work->aio, msg);
|
||||
work->state = Work::SEND;
|
||||
nng_ctx_send(work->ctx, work->aio);
|
||||
|
||||
} catch (...) {
|
||||
std::string errmsg = "Unknown error!";
|
||||
CLS_ERROR(errmsg);
|
||||
res["ret"] = NodeErrorCode::UNKNOWN_ERROR;
|
||||
res["msg"] = errmsg;
|
||||
nng_aio_set_msg(work->aio, msg);
|
||||
work->state = Work::SEND;
|
||||
nng_ctx_send(work->ctx, work->aio);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_addr;
|
||||
nng_socket m_socket;
|
||||
nng_listener m_listener;
|
||||
std::vector<Work> m_works;
|
||||
std::unordered_map<std::string, std::function<json(json&& req)>> m_handles;
|
||||
};
|
||||
|
||||
} // namespace hku
|
Loading…
Reference in New Issue
Block a user