#include "FTAPIImp.h" using namespace std; CLock FTAPIImp::m_safe; static set s_setImp; static CLock m_safeImp; static void OnDisConnectCallback(FTAPIChannelPtr pChannel, i64_t nErrCode) { CAutoLock(m_safeImp); Foreach_Iter(iter, s_setImp) { FTAPIImp* pImp = *iter; If_Do(IsNotNullPtr(pImp), pImp->OnDisConnect(pChannel, nErrCode)); } } static void OnInitConnectCallback(FTAPIChannelPtr pChannel, i64_t nErrCode, const char* strDesc) { CAutoLock(m_safeImp); Foreach_Iter(iter, s_setImp) { FTAPIImp* pImp = *iter; If_Do(IsNotNullPtr(pImp), pImp->OnInitConnect(pChannel, nErrCode, strDesc)); } } static void OnReplyCallback(FTAPIChannelPtr pChannel, FTAPI_ReqReplyType enReqReplyType, const FTAPI_ProtoHeader* pProtoHeader, const i8_t* pProtoData, i32_t nDataLen) { CAutoLock(m_safeImp); Foreach_Iter(iter, s_setImp) { FTAPIImp* pImp = *iter; If_Do(IsNotNullPtr(pImp), pImp->OnReply(pChannel, enReqReplyType, pProtoHeader, pProtoData, nDataLen)); } } static void OnPushCallback(FTAPIChannelPtr pChannel, const FTAPI_ProtoHeader* pProtoHeader, const i8_t* pProtoData, i32_t nDataLen) { CAutoLock(m_safeImp); Foreach_Iter(iter, s_setImp) { FTAPIImp* pImp = *iter; If_Do(IsNotNullPtr(pImp), pImp->OnPush(pChannel, pProtoHeader, pProtoData, nDataLen)); } } static inline bool PbObj2BinData(const protobuf::Message& pbObj, Buf_t& binData) { binData.clear(); i32_t nSize = pbObj.ByteSize(); If_OMWarn_Return(nSize < 0, false); If_Return(nSize == 0, true); binData.resize(nSize); If_Do_OMWarn_Return(!pbObj.SerializeToString(&binData), binData.clear(), false); return true; } static inline bool BinData2PbObj(const i8_t* pData, i32_t nDataLen, u8_t nProtoFmtType, protobuf::Message& pbObj) { If_OMWarn_Return(IsNullPtr(pData) || nDataLen <= 0, false); bool bRet = false; if (nProtoFmtType == FTAPI_ProtoFmtType_Protobuf) { bRet = pbObj.ParseFromArray(pData, nDataLen); } else if (nProtoFmtType == FTAPI_ProtoFmtType_Json) { protobuf::util::JsonParseOptions ops; ops.ignore_unknown_fields = true; Str_t strJosn(pData, nDataLen); protobuf::util::Status status = JsonStringToMessage(strJosn, &pbObj, ops); bRet = (status.error_code() == protobuf::util::error::OK); } If_OMWarn(!bRet); return bRet; } static inline bool IsTrdPorto(u32_t nPorotID) { return nPorotID >= FTAPI_ProtoID_Trd_Begin && nPorotID <= FTAPI_ProtoID_Trd_End; } static inline bool IsQotPorto(u32_t nPorotID) { return nPorotID >= FTAPI_ProtoID_Qot_Begin && nPorotID <= FTAPI_ProtoID_Qot_End; } FTAPIImp::FTAPIImp(FTAPI_Conn *pConnApi) { m_pFTAPIChannel = CreateFTAPIChannel(); If_OMWarn(IsNullPtr(m_pFTAPIChannel)); { CAutoLock(m_safeImp); s_setImp.insert(this); } CAutoLock(m_safe); FTAPIChannel_SetOnDisconnectCallback(m_pFTAPIChannel, OnDisConnectCallback); FTAPIChannel_SetOnInitConnectCallback(m_pFTAPIChannel, OnInitConnectCallback); FTAPIChannel_SetOnReplyCallback(m_pFTAPIChannel, OnReplyCallback); FTAPIChannel_SetOnPushCallback(m_pFTAPIChannel, OnPushCallback); m_pConnApi = pConnApi; If_OMWarn(IsNullPtr(m_pConnApi)); } FTAPIImp::~FTAPIImp(void) { { CAutoLock(m_safeImp); s_setImp.erase(this); } CAutoLock(m_safe); FTAPIChannel_SetOnDisconnectCallback(m_pFTAPIChannel, nullptr); FTAPIChannel_SetOnInitConnectCallback(m_pFTAPIChannel, nullptr); FTAPIChannel_SetOnReplyCallback(m_pFTAPIChannel, nullptr); FTAPIChannel_SetOnPushCallback(m_pFTAPIChannel, nullptr); ReleaseFTAPIChannel(m_pFTAPIChannel); m_pFTAPIChannel = nullptr; } void FTAPIImp::SetClientInfo(const char* szClientID, i32_t nClientVer) { CAutoLock(m_safe); FTAPIChannel_SetClientInfo(m_pFTAPIChannel, szClientID, nClientVer); } void FTAPIImp::SetProgrammingLanguage(const char* szLanguage) { CAutoLock(m_safe); FTAPIChannel_SetProgrammingLanguage(m_pFTAPIChannel, szLanguage); } void FTAPIImp::SetRSAPrivateKey(const char* strRSAPrivateKey) { CAutoLock(m_safe); FTAPIChannel_SetRSAPrivateKey(m_pFTAPIChannel, strRSAPrivateKey); } bool FTAPIImp::InitConnect(const char* szIPAddr, u16_t nPort, bool bEnableEncrypt) { CAutoLock(m_safe); return FTAPIChannel_InitConnect(m_pFTAPIChannel, szIPAddr, nPort, bEnableEncrypt); } u64_t FTAPIImp::GetConnectID() { CAutoLock(m_safe); return FTAPIChannel_GetConnectID(m_pFTAPIChannel); } bool FTAPIImp::Close() { CAutoLock(m_safe); return FTAPIChannel_Close(m_pFTAPIChannel); } void FTAPIImp::RegisterConnSpi(FTSPI_Conn *pSpi) { CAutoLock(m_safe); m_pConnSpi = pSpi; } void FTAPIImp::UnregisterConnSpi() { CAutoLock(m_safe); m_pConnSpi = nullptr; } void FTAPIImp::RegisterQotSpi(FTSPI_Qot *pSpi) { CAutoLock(m_safe); m_pQotSpi = pSpi; } void FTAPIImp::UnregisterQotSpi() { CAutoLock(m_safe); m_pQotSpi = nullptr; } u32_t FTAPIImp::Sub(const Qot_Sub::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_Sub, stReq); } u32_t FTAPIImp::GetGlobalState(const GetGlobalState::Request &stReq) { return SendProto(FTAPI_ProtoID_GetGlobalState, stReq); } u32_t FTAPIImp::RegQotPush(const Qot_RegQotPush::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_RegQotPush, stReq); } u32_t FTAPIImp::GetSubInfo(const Qot_GetSubInfo::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetSubInfo, stReq); } u32_t FTAPIImp::GetTicker(const Qot_GetTicker::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetTicker, stReq); } u32_t FTAPIImp::GetBasicQot(const Qot_GetBasicQot::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetBasicQot, stReq); } u32_t FTAPIImp::GetOrderBook(const Qot_GetOrderBook::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetOrderBook, stReq); } u32_t FTAPIImp::GetKL(const Qot_GetKL::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetKL, stReq); } u32_t FTAPIImp::GetRT(const Qot_GetRT::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetRT, stReq); } u32_t FTAPIImp::GetBroker(const Qot_GetBroker::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetBroker, stReq); } u32_t FTAPIImp::RequestRehab(const Qot_RequestRehab::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_RequestRehab, stReq); } u32_t FTAPIImp::RequestHistoryKL(const Qot_RequestHistoryKL::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_RequestHistoryKL, stReq); } u32_t FTAPIImp::RequestHistoryKLQuota(const Qot_RequestHistoryKLQuota::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_RequestHistoryKLQuota, stReq); } u32_t FTAPIImp::GetTradeDate(const Qot_GetTradeDate::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetTradeDate, stReq); } u32_t FTAPIImp::GetStaticInfo(const Qot_GetStaticInfo::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetStaticInfo, stReq); } u32_t FTAPIImp::GetSecuritySnapshot(const Qot_GetSecuritySnapshot::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetSecuritySnapshot, stReq); } u32_t FTAPIImp::GetPlateSet(const Qot_GetPlateSet::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetPlateSet, stReq); } u32_t FTAPIImp::GetPlateSecurity(const Qot_GetPlateSecurity::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetPlateSecurity, stReq); } u32_t FTAPIImp::GetReference(const Qot_GetReference::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetReference, stReq); } u32_t FTAPIImp::GetOwnerPlate(const Qot_GetOwnerPlate::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetOwnerPlate, stReq); } u32_t FTAPIImp::GetHoldingChangeList(const Qot_GetHoldingChangeList::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetHoldingChangeList, stReq); } u32_t FTAPIImp::GetOptionChain(const Qot_GetOptionChain::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetOptionChain, stReq); } u32_t FTAPIImp::GetWarrant(const Qot_GetWarrant::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetWarrant, stReq); } u32_t FTAPIImp::GetCapitalFlow(const Qot_GetCapitalFlow::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetCapitalFlow, stReq); } u32_t FTAPIImp::GetCapitalDistribution(const Qot_GetCapitalDistribution::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetCapitalDistribution, stReq); } u32_t FTAPIImp::GetUserSecurity(const Qot_GetUserSecurity::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetUserSecurity, stReq); } u32_t FTAPIImp::ModifyUserSecurity(const Qot_ModifyUserSecurity::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_ModifyUserSecurity, stReq); } u32_t FTAPIImp::StockFilter(const Qot_StockFilter::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_StockFilter, stReq); } Futu::u32_t FTAPIImp::GetCodeChange(const Qot_GetCodeChange::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetCodeChange, stReq); } u32_t FTAPIImp::GetIpoList(const Qot_GetIpoList::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetIpoList, stReq); } u32_t FTAPIImp::GetFutureInfo(const Qot_GetFutureInfo::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetFutureInfo, stReq); } u32_t FTAPIImp::RequestTradeDate(const Qot_RequestTradeDate::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_RequestTradeDate, stReq); } u32_t FTAPIImp::SetPriceReminder(const Qot_SetPriceReminder::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_SetPriceReminder, stReq); } u32_t FTAPIImp::GetPriceReminder(const Qot_GetPriceReminder::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetPriceReminder, stReq); } u32_t FTAPIImp::GetUserSecurityGroup(const Qot_GetUserSecurityGroup::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetUserSecurityGroup, stReq); } u32_t FTAPIImp::GetMarketState(const Qot_GetMarketState::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetMarketState, stReq); } u32_t FTAPIImp::GetOptionExpirationDate(const Qot_GetOptionExpirationDate::Request &stReq) { return SendProto(FTAPI_ProtoID_Qot_GetOptionExpirationDate, stReq); } void FTAPIImp::RegisterTrdSpi(FTSPI_Trd *pSpi) { CAutoLock(m_safe); m_pTrdSpi = pSpi; } void FTAPIImp::UnregisterTrdSpi() { CAutoLock(m_safe); m_pTrdSpi = nullptr; } bool FTAPIImp::GetPacketID(Common::PacketID &stPacketID) { CAutoLock(m_safe); u64_t nConnectID = GetConnectID(); stPacketID.set_connid(nConnectID); stPacketID.set_serialno(++m_nTrdSerialNo); return nConnectID != 0; } u32_t FTAPIImp::GetAccList(const Trd_GetAccList::Request &stReq) { return SendProto(FTAPI_ProtoID_Trd_GetAccList, stReq); } u32_t FTAPIImp::UnlockTrade(const Trd_UnlockTrade::Request &stReq) { return SendProto(FTAPI_ProtoID_Trd_UnlockTrade, stReq); } u32_t FTAPIImp::SubAccPush(const Trd_SubAccPush::Request &stReq) { return SendProto(FTAPI_ProtoID_Trd_SubAccPush, stReq); } u32_t FTAPIImp::GetFunds(const Trd_GetFunds::Request &stReq) { return SendProto(FTAPI_ProtoID_Trd_GetFunds, stReq); } u32_t FTAPIImp::GetPositionList(const Trd_GetPositionList::Request &stReq) { return SendProto(FTAPI_ProtoID_Trd_GetPositionList, stReq); } u32_t FTAPIImp::GetMaxTrdQtys(const Trd_GetMaxTrdQtys::Request &stReq) { return SendProto(FTAPI_ProtoID_Trd_GetMaxTrdQtys, stReq); } u32_t FTAPIImp::GetOrderList(const Trd_GetOrderList::Request &stReq) { return SendProto(FTAPI_ProtoID_Trd_GetOrderList, stReq); } u32_t FTAPIImp::PlaceOrder(const Trd_PlaceOrder::Request &stReq) { Trd_PlaceOrder::Request stRealReq; stRealReq.CopyFrom(stReq); if (stRealReq.has_c2s()) { Common::PacketID *pPacketID = stRealReq.mutable_c2s()->mutable_packetid(); GetPacketID(*pPacketID); } return SendProto(FTAPI_ProtoID_Trd_PlaceOrder, stRealReq); } u32_t FTAPIImp::ModifyOrder(const Trd_ModifyOrder::Request &stReq) { Trd_ModifyOrder::Request stRealReq; stRealReq.CopyFrom(stReq); if (stRealReq.has_c2s()) { Common::PacketID *pPacketID = stRealReq.mutable_c2s()->mutable_packetid(); GetPacketID(*pPacketID); } return SendProto(FTAPI_ProtoID_Trd_ModifyOrder, stRealReq); } u32_t FTAPIImp::GetOrderFillList(const Trd_GetOrderFillList::Request &stReq) { return SendProto(FTAPI_ProtoID_Trd_GetOrderFillList, stReq); } u32_t FTAPIImp::GetHistoryOrderList(const Trd_GetHistoryOrderList::Request &stReq) { return SendProto(FTAPI_ProtoID_Trd_GetHistoryOrderList, stReq); } u32_t FTAPIImp::GetHistoryOrderFillList(const Trd_GetHistoryOrderFillList::Request &stReq) { return SendProto(FTAPI_ProtoID_Trd_GetHistoryOrderFillList, stReq); } u32_t FTAPIImp::GetMarginRatio(const Trd_GetMarginRatio::Request &stReq) { return SendProto(FTAPI_ProtoID_Trd_GetMarginRatio, stReq); } u32_t FTAPIImp::GetOrderFee(const Trd_GetOrderFee::Request& stReq) { return SendProto(FTAPI_ProtoID_Trd_GetOrderFee, stReq); } #define OnReplyNotify(strProtoType, strProtoName) \ case FTAPI_ProtoID_##strProtoType##_##strProtoName:\ {\ strProtoType##_##strProtoName::Response stRsp;\ if (enReqReplyType == FTAPI_ReqReplyType_SvrReply)\ {\ if(!BinData2PbObj(pProtoData, nDataLen, pProtoHeader->nProtoFmtType, stRsp))\ {\ stRsp.set_rettype(Common::RetType_Invalid);\ }\ }\ else {stRsp.set_rettype(enReqReplyType);}\ m_p##strProtoType##Spi->OnReply_##strProtoName(pProtoHeader->nSerialNo, stRsp);\ }\ break; #define OnTrdReply(strProto) OnReplyNotify(Trd, strProto) #define OnQotReply(strProto) OnReplyNotify(Qot, strProto) void FTAPIImp::OnReply(FTAPIChannelPtr pChannel, FTAPI_ReqReplyType enReqReplyType, const FTAPI_ProtoHeader* pProtoHeader, const i8_t* pProtoData, i32_t nDataLen) { CAutoLock(m_safe); If_ReturnVoid(pChannel != m_pFTAPIChannel); u32_t nProtoID = pProtoHeader->nProtoID; If_ReturnVoid(IsTrdPorto(nProtoID) && IsNullPtr(m_pTrdSpi)); If_ReturnVoid(IsQotPorto(nProtoID) && IsNullPtr(m_pQotSpi)); switch (nProtoID) { case FTAPI_ProtoID_GetGlobalState: { if (IsNotNullPtr(m_pQotSpi)) { GetGlobalState::Response stRsp; if (enReqReplyType == FTAPI_ReqReplyType_SvrReply) { if (!BinData2PbObj(pProtoData, nDataLen, pProtoHeader->nProtoFmtType, stRsp)) { stRsp.set_rettype(Common::RetType_Invalid); } } else { stRsp.set_rettype(enReqReplyType); } m_pQotSpi->OnReply_GetGlobalState(pProtoHeader->nSerialNo, stRsp); } } break; OnQotReply(Sub); OnQotReply(RegQotPush); OnQotReply(GetSubInfo); OnQotReply(GetTicker); OnQotReply(GetBasicQot); OnQotReply(GetOrderBook); OnQotReply(GetKL); OnQotReply(GetRT); OnQotReply(GetBroker); OnQotReply(RequestRehab); OnQotReply(RequestHistoryKL); OnQotReply(RequestHistoryKLQuota); OnQotReply(GetTradeDate); OnQotReply(GetStaticInfo); OnQotReply(GetSecuritySnapshot); OnQotReply(GetPlateSet); OnQotReply(GetPlateSecurity); OnQotReply(GetReference); OnQotReply(GetOwnerPlate); OnQotReply(GetHoldingChangeList); OnQotReply(GetOptionChain); OnQotReply(GetWarrant); OnQotReply(GetCapitalFlow); OnQotReply(GetCapitalDistribution); OnQotReply(GetUserSecurity); OnQotReply(ModifyUserSecurity); OnQotReply(StockFilter); OnQotReply(GetCodeChange); OnQotReply(GetIpoList); OnQotReply(GetFutureInfo); OnQotReply(RequestTradeDate); OnQotReply(SetPriceReminder); OnQotReply(GetPriceReminder); OnQotReply(GetUserSecurityGroup); OnQotReply(GetMarketState); OnQotReply(GetOptionExpirationDate); OnTrdReply(GetAccList); OnTrdReply(UnlockTrade); OnTrdReply(SubAccPush); OnTrdReply(GetFunds); OnTrdReply(GetPositionList); OnTrdReply(GetMaxTrdQtys); OnTrdReply(GetOrderList); OnTrdReply(PlaceOrder); OnTrdReply(ModifyOrder); OnTrdReply(GetOrderFillList); OnTrdReply(GetHistoryOrderList); OnTrdReply(GetHistoryOrderFillList); OnTrdReply(GetMarginRatio); OnTrdReply(GetOrderFee); } } #define OnPushNotify(strProtoType, strProtoName) \ case FTAPI_ProtoID_##strProtoType##_##strProtoName:\ {\ strProtoType##_##strProtoName::Response stRsp;\ if (!BinData2PbObj(pProtoData, nDataLen, pProtoHeader->nProtoFmtType, stRsp))\ {stRsp.set_rettype(Common::RetType_Invalid);}\ m_p##strProtoType##Spi->OnPush_##strProtoName(stRsp);\ }break; #define OnTrdPush(strProto) OnPushNotify(Trd, strProto) #define OnQotPush(strProto) OnPushNotify(Qot, strProto) void FTAPIImp::OnPush(FTAPIChannelPtr pChannel, const FTAPI_ProtoHeader* pProtoHeader, const i8_t* pProtoData, i32_t nDataLen) { CAutoLock(m_safe); If_ReturnVoid(pChannel != m_pFTAPIChannel); u32_t nProtoID = pProtoHeader->nProtoID; If_ReturnVoid(IsTrdPorto(nProtoID) && IsNullPtr(m_pTrdSpi)); If_ReturnVoid(IsQotPorto(nProtoID) && IsNullPtr(m_pQotSpi)); switch (nProtoID) { case FTAPI_ProtoID_Notify: { if (IsNotNullPtr(m_pQotSpi)) { Notify::Response stRsp; if (!BinData2PbObj(pProtoData, nDataLen, pProtoHeader->nProtoFmtType, stRsp)) { stRsp.set_rettype(Common::RetType_Invalid); } m_pQotSpi->OnPush_Notify(stRsp); } } break; OnQotPush(UpdateTicker); OnQotPush(UpdateBasicQot); OnQotPush(UpdateOrderBook); OnQotPush(UpdateKL); OnQotPush(UpdateRT); OnQotPush(UpdateBroker); OnQotPush(UpdatePriceReminder); OnTrdPush(UpdateOrder); OnTrdPush(UpdateOrderFill); } } void FTAPIImp::OnDisConnect(FTAPIChannelPtr pChannel, i64_t nErrCode) { CAutoLock(m_safe); If_ReturnVoid(pChannel != m_pFTAPIChannel); If_ReturnVoid(IsNullPtr(m_pConnSpi)); m_pConnSpi->OnDisConnect(m_pConnApi, nErrCode); } void FTAPIImp::OnInitConnect(FTAPIChannelPtr pChannel, i64_t nErrCode, const char* strDesc) { CAutoLock(m_safe); If_ReturnVoid(pChannel != m_pFTAPIChannel); If_ReturnVoid(IsNullPtr(m_pConnSpi)); m_pConnSpi->OnInitConnect(m_pConnApi, nErrCode, strDesc); } u32_t FTAPIImp::SendProto(u32_t nProtoID, const protobuf::Message& pbObj) { CAutoLock(m_safe); Buf_t binData; If_OMWarn_Return(!PbObj2BinData(pbObj, binData), 0); return FTAPIChannel_SendProto(m_pFTAPIChannel, nProtoID, 0, binData.data(), ContainerSize(binData)); }