diff --git a/stream/ch/chain/net/srv/DapStreamChChainNetSrv.cpp b/stream/ch/chain/net/srv/DapStreamChChainNetSrv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..92bb5c63f59c21e2bc24f57f39fc191de839b7c6 --- /dev/null +++ b/stream/ch/chain/net/srv/DapStreamChChainNetSrv.cpp @@ -0,0 +1,160 @@ +/* +* Authors: +* Dmitriy Gerasimov <naeper@demlabs.net> +* Cellframe https://cellframe.net +* DeM Labs Inc. https://demlabs.net +* Copyright (c) 2017-2019 +* All rights reserved. + +This file is part of CellFrame SDK the open source project + +CellFrame SDK is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +CellFrame SDK is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with any CellFrame SDK based project. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <QtDebug> +#include "dap_common.h" +#include "DapStreamChChainNetSrv.h" + + +// TYPE_REQUEST +typedef struct dap_stream_ch_chain_net_srv_pkt_request_hdr{ + dap_chain_net_id_t net_id;// Network id wheither to request + dap_chain_hash_fast_t tx_cond; // Conditioned transaction with paymemt for + dap_chain_net_srv_uid_t srv_uid; + char token[DAP_CHAIN_TICKER_SIZE_MAX]; +} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_request_hdr_t; + +typedef struct dap_stream_ch_chain_net_srv_pkt_request{ + dap_stream_ch_chain_net_srv_pkt_request_hdr_t hdr; + uint8_t data[]; +} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_request_t; + +typedef struct dap_stream_ch_chain_net_srv_pkt_success_hdr{ + uint32_t usage_id; + dap_chain_net_id_t net_id; + dap_chain_net_srv_uid_t srv_uid; +} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_success_hdr_t; + +typedef struct dap_stream_ch_chain_net_srv_pkt_success{ + dap_stream_ch_chain_net_srv_pkt_success_hdr_t hdr; + uint8_t custom_data[]; +} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_success_t; + +// TYPE_RESPONSE_ERROR +typedef struct dap_stream_ch_chain_net_srv_pkt_error{ + dap_chain_net_id_t net_id; + dap_chain_net_srv_uid_t srv_uid; + uint32_t usage_id; + uint32_t code; // error code +} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_error_t; + +using namespace Dap; +using namespace Dap::Stream; +using namespace Dap::Chain; +using namespace Dap::Crypto; + +/** + * @brief ChChainNetSrv::ChChainNetSrv + * @param a_streamer + * @param a_mainDapSession + */ +ChChainNetSrv::ChChainNetSrv(DapStreamer * a_streamer, DapSession * a_mainDapSession) + : DapChBase(nullptr, 'R'), m_streamer(a_streamer), m_mainDapSession(a_mainDapSession) +{ + +} + +/** + * @brief ChChainNetSrv::sendReceipt + * @param receipt + */ +void ChChainNetSrv::sendReceipt(Chain::Receipt * receipt ) +{ + sendPacket( get_id(),ChChainNetSrvPktType::SIGN_RESPONSE,receipt->value() ,receipt->size() ); + + // To prevent double free + receipt->release(); + delete receipt; +} + +/** + * @brief ChChainNetSrv::onPktIn + * @param a_pkt + */ +void ChChainNetSrv::onPktIn(DapChannelPacket* a_pkt) +{ + switch (static_cast<ChChainNetSrvPktType>(a_pkt->hdr()->type) ) { + case REQUEST:{ + qWarning() << "We don't serve any service so nothing todo with REQUEST. TODO: add service provide for this realization as well"; + } break; + case SIGN_REQUEST:{ + Chain::Receipt * receipt = nullptr; + try { + receipt = new Chain::Receipt(a_pkt->data(), a_pkt->hdr()->size); + emit sigReceiptToSign(receipt); + } catch (Chain::Receipt::ThrowClass err) { + switch (err) { + case Chain::Receipt::DataNull: + qWarning() << "Packet with receipt has NULL data"; + break; + case Chain::Receipt::DataSizeWrong: + qWarning() << "Packet with receipt has wrong data size "<< a_pkt->hdr()->size; + break; + } + } + + } break; + case SIGN_RESPONSE:{ + qWarning() << "We don't serve any service so nothing todo with SIG_RESPONSE. TODO: add service provide for this realization as well"; + } break; + case RESPONSE_SUCCESS:{ + if( a_pkt->hdr()->size < sizeof(dap_stream_ch_chain_net_srv_pkt_success_hdr_t) ){ + qWarning() << "Wrong error packet data size, expected to be at least " << sizeof(dap_stream_ch_chain_net_srv_pkt_success_hdr_t); + break; + } + const dap_stream_ch_chain_net_srv_pkt_success_t * l_success = + reinterpret_cast<const dap_stream_ch_chain_net_srv_pkt_success_t* >(a_pkt->data()); + emit sigProvideSuccess( l_success->hdr.net_id, l_success->hdr.srv_uid, l_success->hdr.usage_id ); + } break; + case RESPONSE_ERROR:{ + const dap_stream_ch_chain_net_srv_pkt_error_t *l_err; + if( a_pkt->hdr()->size != sizeof(*l_err) ){ + qWarning() << "Wrong error packet data size, expected to be "<<sizeof (*l_err); + break; + } + l_err =reinterpret_cast<const dap_stream_ch_chain_net_srv_pkt_error_t*>(a_pkt->data()); + emit sigProvideError(l_err->net_id, l_err->srv_uid, l_err->usage_id, l_err->code ); + } break; + case NOTIFY_STOPPED: { + /// TODO add usage id, net id and service id to identify what exactly was stopped + emit sigNotifyStopped(); + } break; + //default: qWarning() << "Unknown packet type " << a_pkt->hdr()->type; + } +} + +void ChChainNetSrv::sendRequest(Chain::NetId a_netId,// Network id wheither to request + Crypto::HashFast a_txCond, // Conditioned transaction with paymemt for + Chain::NetSrv::Uid a_srvUid, const QString& a_token ) // Service ID +{ + dap_stream_ch_chain_net_srv_pkt_request_t * l_request =static_cast<dap_stream_ch_chain_net_srv_pkt_request_t *>( + calloc(1,sizeof(dap_stream_ch_chain_net_srv_pkt_request_t) ) ); + l_request->hdr.net_id = a_netId.value(); + l_request->hdr.tx_cond = a_txCond.value(); + qDebug() << "2791: Service req: net_id = " << a_netId.value().uint64 << "tx_cond = " << a_txCond.value().raw; + l_request->hdr.srv_uid = a_srvUid; + strncpy(l_request->hdr.token, a_token.toLatin1().constData(),sizeof (l_request->hdr.token)-1); + sendPacket( get_id(),ChChainNetSrvPktType::REQUEST,l_request,sizeof(*l_request)); + qInfo() << "Sent request for service "<<a_srvUid.toString(); +} diff --git a/stream/ch/chain/net/srv/DapStreamChChainNetSrv.h b/stream/ch/chain/net/srv/DapStreamChChainNetSrv.h new file mode 100755 index 0000000000000000000000000000000000000000..4cbbc723204b4308cae22c5843e5743ef18a0d06 --- /dev/null +++ b/stream/ch/chain/net/srv/DapStreamChChainNetSrv.h @@ -0,0 +1,227 @@ +/* +* Authors: +* Dmitriy Gerasimov <naeper@demlabs.net> +* Cellframe https://cellframe.net +* DeM Labs Inc. https://demlabs.net +* Copyright (c) 2017-2019 +* All rights reserved. + +This file is part of CellFrame SDK the open source project + +CellFrame SDK is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +CellFrame SDK is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with any CellFrame SDK based project. If not, see <http://www.gnu.org/licenses/>. +*/ +#pragma once + +#include "dap_common.h" +#include "dap_chain_common.h" +#include "dap_chain_datum_tx_receipt.h" +#include "DapChBase.h" +#include "DapCrypto.h" + + + +class DapStreamer; +class DapSession; +namespace Dap { + + // TODO move to its own module + namespace Chain { + + class NetId + { + private: + dap_chain_net_id_t m_value; + public: + const dap_chain_net_id_t& value () const { return m_value;} + NetId(){ m_value.uint64 = 0ull; } + NetId( const dap_chain_net_id_t& a_value){ m_value.uint64 = a_value.uint64; } + NetId( const NetId& a_netId){ m_value.uint64 = a_netId.m_value.uint64; } + NetId( const QString& a_str){ + m_value.uint64 = a_str.isNull() ? 0 : dap_chain_net_id_from_str(a_str.toLatin1().constData()).uint64; + } + QString toString(){ return QString().sprintf("0x%016lX",m_value.uint64); } + operator dap_chain_net_id_t& (){ return m_value; } + dap_chain_net_id_t& operator=(const NetId& a_netId) { m_value.uint64 = a_netId.m_value.uint64; return m_value; } + dap_chain_net_id_t& operator=(QString& a_netId_str) { + m_value.uint64 = a_netId_str.toInt(nullptr, 16); + return m_value; + } + bool operator==(const NetId& a_netId){ return a_netId.m_value.uint64 == m_value.uint64; } + }; + + + namespace NetSrv { + class Uid + { + private: + dap_chain_net_srv_uid_t m_value; + public: + Uid(quint64 a_value) { m_value.uint64 = a_value ;} + Uid(){ m_value.uint64 = 0ull; } + Uid( const dap_chain_net_srv_uid_t& a_value){ m_value.uint64 = a_value.uint64; } + Uid( const Uid& a_netSrvUid){ m_value.uint64 = a_netSrvUid.m_value.uint64; } + Uid( const QString& a_str){ + m_value.uint64 = dap_chain_net_srv_uid_from_str(a_str.toLatin1().constData()).uint64; + } + operator dap_chain_net_srv_uid_t& (){ return m_value; } + + QString toString(){ return QString().sprintf("0x%016lX",m_value.uint64); } + + dap_chain_net_srv_uid_t& operator=(const Uid& a_netSrvUid) { + m_value.uint64 = a_netSrvUid.m_value.uint64; + return m_value; + } + dap_chain_net_srv_uid_t& operator=(quint64 a_value) { + m_value.uint64 = a_value; + return m_value; + } + + bool operator==(const Uid& a_netSrvUid){ return a_netSrvUid.m_value.uint64 == m_value.uint64; } + }; + static const Uid UidNull=Uid(); + enum UnitType{ + UNIT_TYPE_UNDEFINED = 0 , + UNIT_TYPE_MB = 0x00000001, // megabytes + UNIT_TYPE_SEC = 0x00000002, // seconds + UNIT_TYPE_DAY = 0x00000003, // days + UNIT_TYPE_KB = 0x00000010, // kilobytes + UNIT_TYPE_B = 0x00000011, // bytes + }; + + + } + class Receipt { + private: + dap_chain_datum_tx_receipt_t * m_value; + public: + enum ThrowClass{DataNull, DataSizeWrong}; + Receipt() { m_value = nullptr; } + Receipt(const Receipt& a_receipt){ m_value = a_receipt.m_value; } + Receipt(const Receipt* a_receipt){ m_value = a_receipt->m_value; } + Receipt(const void * a_data, size_t a_dataSize){ + if( a_data == nullptr) + throw DataNull; + if( a_dataSize < ( 1 +sizeof (m_value->receipt_info)+sizeof (m_value->size))) + throw DataSizeWrong; + m_value = DAP_NEW_Z_SIZE(dap_chain_datum_tx_receipt_t, a_dataSize); + ::memcpy(m_value,a_data,a_dataSize); + } + ~Receipt(){ + if (m_value) + DAP_DELETE(m_value); + } + + void release(){ m_value = nullptr; } // Release wrapper from m_value to prevent doulbe free + operator dap_chain_datum_tx_receipt_t& () { return *m_value;} + operator dap_chain_datum_tx_receipt_t* () { return m_value;} + operator const void* () { return m_value;} + operator void* () { return m_value;} + quint16 size() { return m_value?m_value->size : 0; } + + dap_chain_datum_tx_receipt_t * value() { return m_value; } + NetSrv::Uid getNetSrvUid() { return m_value ? m_value->receipt_info.srv_uid : NetSrv::UidNull; } + NetSrv::UnitType getUnitType() { return m_value ?static_cast<NetSrv::UnitType>(m_value->receipt_info.units_type.uint32): + NetSrv::UNIT_TYPE_UNDEFINED ; } + quint64 getUnits() { return m_value? m_value->receipt_info.units : 0; } + quint64 getValueDatoshi() { return m_value ? m_value->receipt_info.value_datoshi: 0; } + + void signAdd(Crypto::Key& a_key){ + dap_chain_datum_tx_receipt_sign_add( &m_value, m_value->size, a_key ); + } + void signAdd(Crypto::Cert& a_cert){ + dap_chain_datum_tx_receipt_sign_add( &m_value, m_value->size, a_cert.key() ); + } + + Receipt* deepCopy(){ + Receipt* ret = new Receipt; + ret->m_value = DAP_NEW_Z_SIZE(dap_chain_datum_tx_receipt_t, m_value->size); + ::memcpy(ret->m_value, m_value, m_value->size); + return ret; + } + }; + + } + namespace Stream{ + enum ChChainNetSrvPktType { + REQUEST = 0x01, + SIGN_REQUEST = 0x10, + SIGN_RESPONSE = 0x11, + NOTIFY_STOPPED = 0x20, + RESPONSE_SUCCESS = 0xf0, + RESPONSE_ERROR = 0xff + }; + enum ChChainNetSrvPktResponseErrorCode{ + UNDEFINED = 0x00000000, + SERVICE_NOT_FOUND = 0x00000100, + NETWORK_NOT_FOUND = 0x00000200, + NETWORK_NO_LEDGER = 0x00000201, + USAGE_CANT_ADD = 0x00000300, + TX_COND_NOT_FOUND = 0x00000400, + TX_COND_NO_COND_OUT = 0x00000401, + TX_COND_NOT_ENOUGH = 0x00000402, + TX_COND_NOT_ACCEPT_TOKEN = 0x00000403, + TX_COND_WRONG_SRV_UID = 0x00000404, + TX_COND_WRONG_SIZE = 0x00000405, + RECEIPT_CANT_FIND = 0x00000500, + RECEIPT_NO_SIGN = 0x00000501, + PRICE_NOT_FOUND = 0x00000600, + RECEIPT_WRONG_PKEY_HASH = 0x00000502, + UNKNOWN = 0xffffffff + }; + static inline const QString chChainNetSrvPktResponseErrorCodeToString(quint32 a){ + switch (static_cast<ChChainNetSrvPktResponseErrorCode>(a)) { + case UNDEFINED: return "UNDEFINED"; + case SERVICE_NOT_FOUND: return "SERVICE_NOT_FOUND"; + case NETWORK_NOT_FOUND: return "NETWORK_NOT_FOUND"; + case NETWORK_NO_LEDGER: return "NETWORK_NO_LEDGER"; + case USAGE_CANT_ADD: return "USAGE_CANT_ADD"; + case TX_COND_NOT_FOUND: return "TX_COND_NOT_FOUND"; + case TX_COND_NO_COND_OUT: return "TX_COND_NO_COND_OUT"; + case TX_COND_NOT_ENOUGH: return "TX_COND_NOT_ENOUGH"; + case TX_COND_NOT_ACCEPT_TOKEN: return "TX_COND_NOT_ACCEPT_TOKEN"; + case TX_COND_WRONG_SRV_UID: return "TX_COND_WRONG_SRV_UID"; + case TX_COND_WRONG_SIZE: return "TX_COND_WRONG_SIZE"; + case RECEIPT_CANT_FIND: return "RECEIPT_CANT_FIND"; + case RECEIPT_NO_SIGN: return "RECEIPT_NO_SIGN"; + case PRICE_NOT_FOUND: return "PRICE_NOT_FOUND"; + case RECEIPT_WRONG_PKEY_HASH: return "RECEIPT_WRONG_PKEY_HASH"; + default: return "UNKNOWN"; + } + }; + + class ChChainNetSrv : public DapChBase + { + Q_OBJECT + private: + DapStreamer * m_streamer; + DapSession * m_mainDapSession; + public: + ChChainNetSrv(DapStreamer * a_streamer, DapSession * a_mainDapSession); + signals: + void sigReceiptToSign(Chain::Receipt * receipt ); + void sigProvideSuccess (Chain::NetId a_netId, Chain::NetSrv::Uid a_srvUid, quint32 a_usageId ); + void sigProvideError(Chain::NetId a_netId, Chain::NetSrv::Uid a_srvUid, quint32 a_usageId,quint32 a_errorCode); + void sigNotifyStopped(); // Service stopped + public slots: + void onPktIn(DapChannelPacket* a_pkt) override; + + void sendReceipt(Chain::Receipt * receipt ); + void sendRequest(Chain::NetId a_netId,// Network id wheither to request + Crypto::HashFast a_txCond, // Conditioned transaction with paymemt for + Chain::NetSrv::Uid a_srvUid ,// Service ID + const QString& a_token // Token to pay + ); + }; + } +} diff --git a/stream/ch/chain/net/srv/README.md b/stream/ch/chain/net/srv/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c9b4f1aa9868d47e0740b8970641a2096dcefc47 --- /dev/null +++ b/stream/ch/chain/net/srv/README.md @@ -0,0 +1,2 @@ +# libdap-qt-stream-ch-chain-net-srv + diff --git a/stream/ch/chain/net/srv/libdap-qt-stream-ch-chain-net-srv.pri b/stream/ch/chain/net/srv/libdap-qt-stream-ch-chain-net-srv.pri new file mode 100755 index 0000000000000000000000000000000000000000..9aadb1e5b5024d4dd4aa9de7238ec6febd62a3b7 --- /dev/null +++ b/stream/ch/chain/net/srv/libdap-qt-stream-ch-chain-net-srv.pri @@ -0,0 +1,7 @@ +SOURCES += \ + $$PWD/DapStreamChChainNetSrv.cpp + +HEADERS += \ + $$PWD/DapStreamChChainNetSrv.h + +INCLUDEPATH += $$PWD