/** @file * @author Edouard DUPIN * @copyright 2016, Edouard DUPIN, all right reserved * @license APACHE v2.0 (see license file) */ #pragma once #include #include #include #include #include #include #include #include namespace jus { template void executeClassCallJson(const ememory::SharedPtr& _interfaceClient, uint64_t _transactionId, uint64_t _clientId, JUS_CLASS_TYPE* _pointer, JUS_RETURN (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), const ejson::Array& _params) { std::vector asyncAction; #if defined(__clang__) // clang generate a basic warning: // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] int32_t idParam = 0; ejson::Value ret = convertToJson(asyncAction, -1, (*_pointer.*_func)((convertJsonTo(_params[idParam++]))...)); #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; ejson::Value ret = convertToJson(asyncAction, -1, (*_pointer.*_func)(convertJsonTo(_params[idParam--])...)); #else #error Must be implemented ... ejson::Value ret = ejson::Null(); return; #endif if (asyncAction.size() != 0) { JUS_ERROR("Missing send async messages"); } ejson::Object answer; answer.add("id", ejson::Number(_transactionId)); answer.add("client-id", ejson::Number(_clientId)); answer.add("return", ret); JUS_INFO("Answer: " << answer.generateHumanString()); _interfaceClient->write(answer.generateMachineString()); } class SendFile { private: jus::FileServer m_data; uint64_t m_transactionId; uint64_t m_clientId; uint32_t m_partId; etk::FSNode m_node; uint64_t m_size; public: SendFile(jus::FileServer _data, uint64_t _transactionId, uint64_t _clientId) : m_data(_data), m_transactionId(_transactionId), m_clientId(_clientId), m_partId(0), m_node(_data.getFileName()), m_size(0) { } ~SendFile() { //m_node.fileClose(); } bool operator() (TcpString* _interface) { ejson::Object answer; answer.add("id", ejson::Number(m_transactionId)); answer.add("client-id", ejson::Number(m_clientId)); answer.add("part", ejson::Number(m_partId)); if (m_partId == 0) { m_node.fileOpenRead(); ejson::Object file; file.add("type", ejson::String("file")); std::string extention = std::string(m_data.getFileName().begin()+m_data.getFileName().size() -3, m_data.getFileName().end()); JUS_WARNING("send file: '" << m_data.getFileName() << "' with extention: '" << extention << "'"); file.add("mine-type", ejson::String(jus::getMineType(extention))); m_size = m_node.fileSize(); file.add("size", ejson::Number(m_size)); answer.add("return", file); JUS_INFO("Answer: " << answer.generateHumanString()); _interface->write(answer.generateMachineString()); m_partId++; return false; } int32_t tmpSize = 1024; if (m_size < 1024) { tmpSize = m_size; } uint8_t tmpData[1024]; m_node.fileRead(tmpData, 1, tmpSize); answer.add("data", ejson::String(ejson::base64::encode(tmpData, tmpSize))); m_size -= tmpSize; if (m_size <= 0) { answer.add("finish", ejson::Boolean(true)); m_node.fileClose(); } JUS_INFO("Answer: " << answer.generateHumanString()); _interface->write(answer.generateMachineString()); m_partId++; if (m_size <= 0) { return true; } return false; } }; template void executeClassCallJson(const ememory::SharedPtr& _interfaceClient, uint64_t _transactionId, uint64_t _clientId, JUS_CLASS_TYPE* _pointer, jus::FileServer (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), const ejson::Array& _params) { #if defined(__clang__) // clang generate a basic warning: // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] int32_t idParam = 0; jus::FileServer tmpElem = (*_pointer.*_func)((convertJsonTo(_params[idParam++]))...); #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; jus::FileServer tmpElem = (*_pointer.*_func)(convertJsonTo(_params[idParam--])...); #else #error Must be implemented ... jus::FileServer tmpElem; return; #endif _interfaceClient->addAsync(SendFile(tmpElem, _transactionId, _clientId)); } template void executeClassCallJson(const ememory::SharedPtr& _interfaceClient, uint64_t _transactionId, uint64_t _clientId, JUS_CLASS_TYPE* _pointer, void (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), const ejson::Array& _params) { ejson::Object out; #if defined(__clang__) // clang generate a basic warning: // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] int32_t idParam = 0; (*_pointer.*_func)((convertJsonTo(_params[idParam++]))...); #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; (*_pointer.*_func)(convertJsonTo(_params[idParam--])...); #else #error Must be implemented ... ejson::Value ret = ejson::Null(); return; #endif ejson::Object answer; answer.add("id", ejson::Number(_transactionId)); answer.add("client-id", ejson::Number(_clientId)); answer.add("return", ejson::Null()); JUS_INFO("Answer: " << answer.generateHumanString()); _interfaceClient->write(answer.generateMachineString()); } template std::string executeClassCallString(JUS_CLASS_TYPE* _pointer, JUS_RETURN (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), const std::vector& _params) { #if defined(__clang__) // clang generate a basic warning: // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] int32_t idParam = 0; return etk::to_string((*_pointer.*_func)((convertStringTo(_params[idParam++]))...)); #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; return etk::to_string((*_pointer.*_func)(convertStringTo(_params[idParam--])...)); #else #error Must be implemented ... #endif return ""; } template std::string executeClassCallString(JUS_CLASS_TYPE* _pointer, void (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), const std::vector& _params) { ejson::Object out; #if defined(__clang__) // clang generate a basic warning: // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] int32_t idParam = 0; (*_pointer.*_func)((convertStringTo(_params[idParam++]))...); #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; (*_pointer.*_func)(convertStringTo(_params[idParam--])...); #else #error Must be implemented ... #endif return ""; } template class AbstractFunctionTypeClass: public jus::AbstractFunction { protected: static const ParamType m_returnType; static const ParamType m_paramType[sizeof...(JUS_TYPES)]; public: using functionType = JUS_RETURN (JUS_CLASS_TYPE::*)(JUS_TYPES...); functionType m_function; AbstractFunctionTypeClass(const std::string& _name, const std::string& _desc, functionType _fptr): AbstractFunction(_name, _desc), m_function(_fptr) { } std::string getPrototype() const override { std::string ret; ret += m_returnType.getName(); ret += " "; ret += m_name; ret += "("; for (size_t iii=0; iii getPrototypeParam() const override { std::vector out; for (size_t iii=0; iii& _interfaceClient, uint64_t _transactionId, uint64_t _clientId, const ejson::Array& _params, void* _class) override { JUS_CLASS_TYPE* tmpClass = nullptr; if (_class != nullptr) { tmpClass = (JUS_CLASS_TYPE*)_class; } // check parameter number if (_params.size() != sizeof...(JUS_TYPES)) { JUS_ERROR("Wrong number of Parameters ..."); ejson::Object answer; answer.add("id", ejson::Number(_transactionId)); answer.add("client-id", ejson::Number(_clientId)); answer.add("error", ejson::String("WRONG-PARAMETER-NUMBER")); std::string help = "request "; help += etk::to_string(_params.size()); help += " parameters and need "; help += etk::to_string(sizeof...(JUS_TYPES)); help += " parameters. prototype function:"; help += getPrototype(); answer.add("error-help", ejson::String(help)); JUS_INFO("Answer: " << answer.generateHumanString()); _interfaceClient->write(answer.generateMachineString()); return; } // check parameter compatibility for (size_t iii=0; iiiwrite(answer.generateMachineString()); return; } } // execute cmd: jus::executeClassCallJson(_interfaceClient, _transactionId, _clientId, tmpClass, m_function, _params); } std::string executeString(const std::vector& _params, void* _class) override { JUS_CLASS_TYPE* tmpClass = (JUS_CLASS_TYPE*)_class; std::string out; // check parameter number if (_params.size() != sizeof...(JUS_TYPES)) { JUS_ERROR("Wrong number of Parameters ..."); out += "error:WRONG-PARAMETER-NUMBER;"; out += "error-help:request "; out += etk::to_string(_params.size()); out += " parameters and need "; out += etk::to_string(sizeof...(JUS_TYPES)); out += " parameters. prototype function:"; out += getPrototype(); return out; } // check parameter compatibility for (size_t iii=0; iii const ParamType AbstractFunctionTypeClass::m_returnType = createType(); template const ParamType AbstractFunctionTypeClass::m_paramType[sizeof...(JUS_TYPES)] = {createType()...}; template AbstractFunction* createAbstractFunctionClass(const std::string& _name, const std::string& _desc, JUS_RETURN (JUS_CLASS_TYPE::*_fffp)(JUS_TYPES...)) { return new AbstractFunctionTypeClass(_name, _desc, _fffp); } }