Подписанная PGP ключом ДС Created сделка сначала должна отправляться по bitmessage, затем должна быть отдана МС.

This commit is contained in:
Преподобный Ален
2022-09-12 20:41:28 +03:00
parent fb2e9c5cb5
commit 3b69fc0889
3 changed files with 186 additions and 140 deletions

View File

@@ -55,8 +55,6 @@ namespace Apostol {
m_Status = psStopped;
CWebService::InitMethods();
InitServerList();
}
//--------------------------------------------------------------------------------------------------------------

View File

@@ -39,6 +39,9 @@ Author:
#define CONFIG_SECTION_NAME "module"
//----------------------------------------------------------------------------------------------------------------------
#define NOT_FOUND_ACTIVE_CONNECTION "Not found active connection. Try again later."
//----------------------------------------------------------------------------------------------------------------------
extern "C++" {
namespace Apostol {
@@ -144,7 +147,7 @@ namespace Apostol {
CHTTPRequest::Prepare(ARequest, "POST", "/api/v1/dm/service");
const auto& caModuleAddress = m_Module["address"];
const auto &caModuleAddress = m_Module["address"];
if (!caModuleAddress.IsEmpty())
ARequest->AddHeader("Module-Address", caModuleAddress);
@@ -377,12 +380,12 @@ namespace Apostol {
for (int i = 0; i < List.Count(); i++) {
const auto& uid = List[i];
const auto &uid = List[i];
DebugMessage("%s (%s)\n", uid.Name.c_str(), uid.Desc.c_str());
const auto& name = uid.Name.Lower();
const auto& data = uid.Desc.Lower();
const auto &name = uid.Name.Lower();
const auto &data = uid.Desc.Lower();
if (name == "technical_data") {
SplitColumns(data, Data, ';');
@@ -402,7 +405,7 @@ namespace Apostol {
}
}
} else if (name.Find("bitcoin_key") != CString::npos) {
const auto& key = wallet::ec_public(data.c_str());
const auto &key = wallet::ec_public(data.c_str());
if (verify(key))
KeyList.AddPair(name, key.encoded());
}
@@ -412,7 +415,7 @@ namespace Apostol {
for (int i = 1; i <= KeyList.Count(); i++) {
Name = "bitcoin_key";
Name << i;
const auto& key = KeyList[Name];
const auto &key = KeyList[Name];
if (!key.IsEmpty()) {
BTCKeys.Add(key);
}
@@ -490,6 +493,57 @@ namespace Apostol {
}
//--------------------------------------------------------------------------------------------------------------
CWebSocketClient *CWebSocketModule::GetConnectedClient(const CClientContext &Context) {
for (int i = 0; i < Context.ClientManager().Count(); i++) {
auto pClient = Context.ClientManager()[i];
if (pClient->Connected())
return pClient;
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------------------
int CWebSocketModule::CurrentContextIndex(const CString &Params) {
int index = 0;
while (index < m_Servers.Count()) {
const auto &caContext = m_Servers[index].Value();
if (caContext.Status() == Context::csRunning) {
if (Params.IsEmpty() || Params == caContext.URL().Origin()) {
auto pClient = GetConnectedClient(caContext);
if (pClient != nullptr)
return index;
}
}
index++;
}
return -1;
}
//--------------------------------------------------------------------------------------------------------------
CWebSocketClient *CWebSocketModule::GetConnectedClient(const CString &Params) {
int index = 0;
while (index < m_Servers.Count()) {
const auto &caContext = m_Servers[index].Value();
if (caContext.Status() == Context::csRunning) {
if (Params.IsEmpty() || Params == caContext.URL().Origin()) {
auto pClient = GetConnectedClient(caContext);
if (pClient != nullptr)
return pClient;
}
}
index++;
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------------------
void CWebSocketModule::DoClientConnected(CObject *Sender) {
auto pConnection = dynamic_cast<CWebSocketClientConnection *>(Sender);
if (pConnection != nullptr) {
@@ -647,33 +701,33 @@ namespace Apostol {
auto pServerRequest = AConnection->Request();
const auto& caModuleAddress = m_Module["address"];
const auto& caHost = pServerRequest->Headers["host"];
const auto& caOrigin = pServerRequest->Headers["origin"];
const auto& caUserAddress = pServerRequest->Params["address"];
const auto &caModuleAddress = m_Module["address"];
const auto &caHost = pServerRequest->Headers["host"];
const auto &caOrigin = pServerRequest->Headers["origin"];
const auto &caUserAddress = pServerRequest->Params["address"];
const auto& pgpValue = pServerRequest->Params["pgp"];
const auto& caServerParam = pServerRequest->Params["server"];
const auto &pgpValue = pServerRequest->Params["pgp"];
const auto &caServerParam = pServerRequest->Params["server"];
CStringList caClearText;
CString sPayload;
if (!pServerRequest->Content.IsEmpty()) {
const auto& ContentType = pServerRequest->Headers.Values(_T("content-type"));
const auto &ContentType = pServerRequest->Headers.Values(_T("content-type"));
if (ContentType.Find("application/x-www-form-urlencoded") == 0) {
const CStringList &FormData = pServerRequest->FormData;
const auto& formDate = FormData["date"];
const auto& formAddress = FormData["address"];
const auto& formBitmessage = FormData["bitmessage"];
const auto& formKey = FormData["key"];
const auto& formPGP = FormData["pgp"];
const auto& formURL = FormData["url"];
const auto& formFlags = FormData["flags"];
const auto& formSign = FormData["sign"];
const auto &formDate = FormData["date"];
const auto &formAddress = FormData["address"];
const auto &formBitmessage = FormData["bitmessage"];
const auto &formKey = FormData["key"];
const auto &formPGP = FormData["pgp"];
const auto &formURL = FormData["url"];
const auto &formFlags = FormData["flags"];
const auto &formSign = FormData["sign"];
if (!formDate.IsEmpty()) {
caClearText << formDate;
@@ -712,14 +766,14 @@ namespace Apostol {
CFormData FormData;
CHTTPRequestParser::ParseFormData(pServerRequest, FormData);
const auto& formDate = FormData.Data("date");
const auto& formAddress = FormData.Data("address");
const auto& formBitmessage = FormData.Data("bitmessage");
const auto& formKey = FormData.Data("key");
const auto& formPGP = FormData.Data("pgp");
const auto& formURL = FormData.Data("url");
const auto& formFlags = FormData.Data("flags");
const auto& formSign = FormData.Data("sign");
const auto &formDate = FormData.Data("date");
const auto &formAddress = FormData.Data("address");
const auto &formBitmessage = FormData.Data("bitmessage");
const auto &formKey = FormData.Data("key");
const auto &formPGP = FormData.Data("pgp");
const auto &formURL = FormData.Data("url");
const auto &formFlags = FormData.Data("flags");
const auto &formSign = FormData.Data("sign");
if (!formDate.IsEmpty()) {
caClearText << formDate;
@@ -757,13 +811,13 @@ namespace Apostol {
const CJSON contextJson(pServerRequest->Content);
const auto& jsonDate = contextJson["date"].AsString();
const auto& jsonAddress = contextJson["address"].AsString();
const auto& jsonBitmessage = contextJson["bitmessage"].AsString();
const auto& jsonKey = contextJson["key"].AsString();
const auto& jsonPGP = contextJson["pgp"].AsString();
const auto& jsonFlags = contextJson["flags"].AsString();
const auto& jsonSign = contextJson["sign"].AsString();
const auto &jsonDate = contextJson["date"].AsString();
const auto &jsonAddress = contextJson["address"].AsString();
const auto &jsonBitmessage = contextJson["bitmessage"].AsString();
const auto &jsonKey = contextJson["key"].AsString();
const auto &jsonPGP = contextJson["pgp"].AsString();
const auto &jsonFlags = contextJson["flags"].AsString();
const auto &jsonSign = contextJson["sign"].AsString();
if (!jsonDate.IsEmpty()) {
caClearText << jsonDate;
@@ -835,27 +889,12 @@ namespace Apostol {
if (!sPayload.IsEmpty())
Json.Object().AddPair("payload", base64_encode(sPayload));
int index = 0;
while (index < m_Servers.Count()) {
const auto &Context = m_Servers[index].Value();
if (Context.Status() == Context::csRunning) {
if (caServerParam.IsEmpty()) {
break;
} else {
if (Context.URL().Origin() == caServerParam)
break;
}
}
}
auto pClient = GetConnectedClient(caServerParam);
if (index == m_Servers.Count()) {
throw Delphi::Exception::Exception("Not found active connection.");
if (pClient == nullptr) {
throw Delphi::Exception::Exception(NOT_FOUND_ACTIVE_CONNECTION);
}
const auto &caContext = m_Servers[index].Value();
auto pClient = caContext.ClientManager().First();
pClient->Send(URI, Json, OnRequest);
}
//--------------------------------------------------------------------------------------------------------------
@@ -876,34 +915,28 @@ namespace Apostol {
auto pServerRequest = AConnection->Request();
const auto& caModuleAddress = m_Module["address"];
const auto& caModuleFee = m_Module["fee"];
const auto &caModuleAddress = m_Module["address"];
const auto &caModuleFee = m_Module["fee"];
const auto checkFee = CheckFee(caModuleFee);
if (checkFee == -1)
throw ExceptionFrm("Invalid module fee value: %s", caModuleFee.c_str());
const auto& caHost = pServerRequest->Headers["host"];
const auto& caOrigin = pServerRequest->Headers["origin"];
const auto& caUserAddress = pServerRequest->Params["address"];
const auto& pgpValue = pServerRequest->Params["pgp"];
const auto& caServerParam = pServerRequest->Params["server"];
const auto &caHost = pServerRequest->Headers["host"];
const auto &caOrigin = pServerRequest->Headers["origin"];
int index = 0;
while (index < m_Servers.Count()) {
const auto &Context = m_Servers[index].Value();
if (Context.Status() == Context::csRunning) {
if (caServerParam.IsEmpty()) {
break;
} else {
if (Context.URL().Origin() == caServerParam)
break;
}
}
}
const auto &address = pServerRequest->Params["address"];
const auto &code = pServerRequest->Params["code"];
if (index == m_Servers.Count()) {
throw Delphi::Exception::Exception("Not found active connection.");
const auto &caUserAddress = address.length() == 40 ? CString() : address;
const auto &caDealCode = !code.empty() ? code : address.length() == 40 ? address : CString();
const auto &pgpValue = pServerRequest->Params["pgp"];
const auto &caServerParam = pServerRequest->Params["server"];
const auto index = CurrentContextIndex(caServerParam);
if (index == -1) {
throw Delphi::Exception::Exception(NOT_FOUND_ACTIVE_CONNECTION);
}
const auto &caContext = m_Servers[index].Value();
@@ -914,27 +947,27 @@ namespace Apostol {
if (!pServerRequest->Content.IsEmpty()) {
const auto& ContentType = pServerRequest->Headers.Values(_T("content-type"));
const auto &ContentType = pServerRequest->Headers.Values(_T("content-type"));
if (ContentType.Find("application/x-www-form-urlencoded") == 0) {
const CStringList &FormData = pServerRequest->FormData;
const auto& formType = FormData["type"];
const auto& formAt = FormData["at"];
const auto& formDate = FormData["date"];
const auto& formSellerAddress = FormData["seller_address"];
const auto& formSellerRating = FormData["seller_rating"];
const auto& formSellerSignature = FormData["seller_signature"];
const auto& formCustomerAddress = FormData["customer_address"];
const auto& formCustomerRating = FormData["customer_rating"];
const auto& formCustomerSignature = FormData["customer_signature"];
const auto& formPaymentAddress = FormData["payment_address"];
const auto& formPaymentUntil = FormData["payment_until"];
const auto& formPaymentSum = FormData["payment_sum"];
const auto& formFeedbackLeaveBefore = FormData["feedback_leave_before"];
const auto& formFeedbackStatus = FormData["feedback_status"];
const auto& formFeedbackComments = FormData["feedback_comments"];
const auto &formType = FormData["type"];
const auto &formAt = FormData["at"];
const auto &formDate = FormData["date"];
const auto &formSellerAddress = FormData["seller_address"];
const auto &formSellerRating = FormData["seller_rating"];
const auto &formSellerSignature = FormData["seller_signature"];
const auto &formCustomerAddress = FormData["customer_address"];
const auto &formCustomerRating = FormData["customer_rating"];
const auto &formCustomerSignature = FormData["customer_signature"];
const auto &formPaymentAddress = FormData["payment_address"];
const auto &formPaymentUntil = FormData["payment_until"];
const auto &formPaymentSum = FormData["payment_sum"];
const auto &formFeedbackLeaveBefore = FormData["feedback_leave_before"];
const auto &formFeedbackStatus = FormData["feedback_status"];
const auto &formFeedbackComments = FormData["feedback_comments"];
CheckKeyForNull("order", Action.c_str());
CheckKeyForNull("type", formType.c_str());
@@ -1007,21 +1040,21 @@ namespace Apostol {
CFormData FormData;
CHTTPRequestParser::ParseFormData(pServerRequest, FormData);
const auto& formType = FormData.Data("type");
const auto& formAt = FormData.Data("at");
const auto& formDate = FormData.Data("date");
const auto& formSellerAddress = FormData.Data("seller_address");
const auto& formSellerRating = FormData.Data("seller_rating");
const auto& formSellerSignature = FormData.Data("seller_signature");
const auto& formCustomerAddress = FormData.Data("customer_address");
const auto& formCustomerRating = FormData.Data("customer_rating");
const auto& formCustomerSignature = FormData.Data("customer_signature");
const auto& formPaymentAddress = FormData.Data("payment_address");
const auto& formPaymentUntil = FormData.Data("payment_until");
const auto& formPaymentSum = FormData.Data("payment_sum");
const auto& formFeedbackLeaveBefore = FormData.Data("feedback_leave_before");
const auto& formFeedbackStatus = FormData.Data("feedback_status");
const auto& formFeedbackComments = FormData.Data("feedback_comments");
const auto &formType = FormData.Data("type");
const auto &formAt = FormData.Data("at");
const auto &formDate = FormData.Data("date");
const auto &formSellerAddress = FormData.Data("seller_address");
const auto &formSellerRating = FormData.Data("seller_rating");
const auto &formSellerSignature = FormData.Data("seller_signature");
const auto &formCustomerAddress = FormData.Data("customer_address");
const auto &formCustomerRating = FormData.Data("customer_rating");
const auto &formCustomerSignature = FormData.Data("customer_signature");
const auto &formPaymentAddress = FormData.Data("payment_address");
const auto &formPaymentUntil = FormData.Data("payment_until");
const auto &formPaymentSum = FormData.Data("payment_sum");
const auto &formFeedbackLeaveBefore = FormData.Data("feedback_leave_before");
const auto &formFeedbackStatus = FormData.Data("feedback_status");
const auto &formFeedbackComments = FormData.Data("feedback_comments");
CheckKeyForNull("order", Action.c_str());
CheckKeyForNull("type", formType.c_str());
@@ -1093,35 +1126,35 @@ namespace Apostol {
const CJSON jsonData(pServerRequest->Content);
const auto& formOrder = jsonData["order"].AsString().Lower();
const auto& formType = jsonData["type"].AsString();
const auto &formOrder = jsonData["order"].AsString().Lower();
const auto &formType = jsonData["type"].AsString();
const auto& formAt = jsonData["at"].AsString();
const auto& formDate = jsonData["date"].AsString();
const auto &formAt = jsonData["at"].AsString();
const auto &formDate = jsonData["date"].AsString();
const CJSONValue &jsonSeller = jsonData["seller"];
const auto& formSellerAddress = jsonSeller["address"].AsString();
const auto& formSellerRating = jsonSeller["rating"].AsString();
const auto& formSellerSignature = jsonSeller["signature"].AsString();
const auto &formSellerAddress = jsonSeller["address"].AsString();
const auto &formSellerRating = jsonSeller["rating"].AsString();
const auto &formSellerSignature = jsonSeller["signature"].AsString();
const CJSONValue &jsonCustomer = jsonData["customer"];
const auto& formCustomerAddress = jsonCustomer["address"].AsString();
const auto& formCustomerRating = jsonCustomer["rating"].AsString();
const auto& formCustomerSignature = jsonCustomer["signature"].AsString();
const auto &formCustomerAddress = jsonCustomer["address"].AsString();
const auto &formCustomerRating = jsonCustomer["rating"].AsString();
const auto &formCustomerSignature = jsonCustomer["signature"].AsString();
const CJSONValue &jsonPayment = jsonData["payment"];
const auto& formPaymentAddress = jsonPayment["address"].AsString();
const auto& formPaymentUntil = jsonPayment["until"].AsString();
const auto& formPaymentSum = jsonPayment["sum"].AsString();
const auto &formPaymentAddress = jsonPayment["address"].AsString();
const auto &formPaymentUntil = jsonPayment["until"].AsString();
const auto &formPaymentSum = jsonPayment["sum"].AsString();
const CJSONValue &jsonFeedback = jsonData["feedback"];
const auto& formFeedbackLeaveBefore = jsonFeedback["leave-before"].AsString();
const auto& formFeedbackStatus = jsonFeedback["status"].AsString();
const auto& formFeedbackComments = jsonFeedback["comments"].AsString();
const auto &formFeedbackLeaveBefore = jsonFeedback["leave-before"].AsString();
const auto &formFeedbackStatus = jsonFeedback["status"].AsString();
const auto &formFeedbackComments = jsonFeedback["comments"].AsString();
const auto &action = Action.IsEmpty() ? formOrder : Action;
@@ -1251,10 +1284,20 @@ namespace Apostol {
Json.Object().AddPair("module", Module);
Json.Object().AddPair("address", caUserAddress.IsEmpty() ? caModuleAddress : caUserAddress);
if (!caDealCode.IsEmpty()) {
CJSONValue Deal(jvtObject);
Deal.Object().AddPair("code", caDealCode);
Json.Object().AddPair("deal", Deal);
}
if (!sPayload.IsEmpty())
Json.Object().AddPair("payload", base64_encode(sPayload));
auto pClient = caContext.ClientManager().First();
auto pClient = GetConnectedClient(caContext);
if (pClient == nullptr) {
throw Delphi::Exception::Exception(NOT_FOUND_ACTIVE_CONNECTION);
}
pClient->Send(URI, Json, OnRequest);
}
@@ -1279,10 +1322,10 @@ namespace Apostol {
return;
}
const auto& caService = slRouts[0].Lower();
const auto& caVersion = slRouts[1].Lower();
const auto& caCommand = slRouts[2].Lower();
const auto& caAction = slRouts.Count() == 4 ? slRouts[3].Lower() : "";
const auto &caService = slRouts[0].Lower();
const auto &caVersion = slRouts[1].Lower();
const auto &caCommand = slRouts[2].Lower();
const auto &caAction = slRouts.Count() == 4 ? slRouts[3].Lower() : "";
if (caService != "api") {
AConnection->SendStockReply(CHTTPReply::not_found);
@@ -1331,7 +1374,7 @@ namespace Apostol {
} else if (caCommand == "bc" && caAction == "history") {
const auto& caAccount = pRequest->Params["account"];
const auto &caAccount = pRequest->Params["account"];
if (caAccount.IsEmpty()) {
AConnection->SendStockReply(CHTTPReply::bad_request);
@@ -1354,8 +1397,8 @@ namespace Apostol {
} else if (caCommand == "bc" && caAction == "header") {
const auto& caHeight = pRequest->Params["height"];
const auto& caHash = pRequest->Params["hash"];
const auto &caHeight = pRequest->Params["height"];
const auto &caHash = pRequest->Params["hash"];
if (caHeight.IsEmpty() && caHash.IsEmpty()) {
AConnection->SendStockReply(CHTTPReply::bad_request);
@@ -1433,10 +1476,10 @@ namespace Apostol {
return;
}
const auto& caService = slRouts[0].Lower();
const auto& caVersion = slRouts[1].Lower();
const auto& caCommand = slRouts[2].Lower();
const auto& caAction = slRouts.Count() == 4 ? slRouts[3].Lower() : "";
const auto &caService = slRouts[0].Lower();
const auto &caVersion = slRouts[1].Lower();
const auto &caCommand = slRouts[2].Lower();
const auto &caAction = slRouts.Count() == 4 ? slRouts[3].Lower() : "";
if (caService != "api") {
AConnection->SendStockReply(CHTTPReply::not_found);
@@ -1527,8 +1570,8 @@ namespace Apostol {
m_OAuth2 = Config()->Prefix() + m_OAuth2;
}
const auto& caPrivateKey = Config()->IniFile().ReadString("pgp", "private", "module.sec");
const auto& caPublicKey = Config()->IniFile().ReadString("pgp", "public", "dm.pub");
const auto &caPrivateKey = Config()->IniFile().ReadString("pgp", "private", "module.sec");
const auto &caPublicKey = Config()->IniFile().ReadString("pgp", "public", "dm.pub");
m_pgpPassphrase = Config()->IniFile().ReadString("pgp", "passphrase", "");
@@ -1601,7 +1644,7 @@ namespace Apostol {
//--------------------------------------------------------------------------------------------------------------
void CWebSocketModule::CheckDeal(const CDeal &Deal) {
const auto& Data = Deal.Data();
const auto &Data = Deal.Data();
const auto DateTime = UTC();
const auto Date = StringToDate(Data.Date);

View File

@@ -96,6 +96,11 @@ namespace Apostol {
void FetchOAuth2(CContext &Context);
static CWebSocketClient *GetConnectedClient(const CClientContext &Context);
int CurrentContextIndex(const CString &Params);
CWebSocketClient *GetConnectedClient(const CString &Params);
protected:
void Heartbeat(CDateTime Now) override;