LCOV - code coverage report
Current view: top level - core/network - SPNetworkData.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 52 251 20.7 %
Date: 2024-05-12 00:16:13 Functions: 21 140 15.0 %

          Line data    Source code
       1             : /**
       2             : Copyright (c) 2022 Roman Katuntsev <sbkarr@stappler.org>
       3             : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       4             : 
       5             : Permission is hereby granted, free of charge, to any person obtaining a copy
       6             : of this software and associated documentation files (the "Software"), to deal
       7             : in the Software without restriction, including without limitation the rights
       8             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       9             : copies of the Software, and to permit persons to whom the Software is
      10             : furnished to do so, subject to the following conditions:
      11             : 
      12             : The above copyright notice and this permission notice shall be included in
      13             : all copies or substantial portions of the Software.
      14             : 
      15             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      18             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      20             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      21             : THE SOFTWARE.
      22             : **/
      23             : 
      24             : #include "SPNetworkData.h"
      25             : 
      26             : #include "SPTime.h"
      27             : #include "SPValid.h"
      28             : #include "SPCrypto.h"
      29             : #include "SPFilesystem.h"
      30             : 
      31             : #if MODULE_STAPPLER_BITMAP
      32             : #include "SPBitmap.h"
      33             : #endif
      34             : 
      35             : #include "curl/curl.h"
      36             : 
      37             : namespace STAPPLER_VERSIONIZED stappler::network {
      38             : 
      39             : template <typename Interface>
      40        3025 : static void Handle_destroy(HandleData<Interface> &data) {
      41        3025 :         if (data.process.sharedHandle) {
      42           0 :                 curl_share_cleanup(data.process.sharedHandle);
      43             :         }
      44        3025 : }
      45             : 
      46             : template <typename Interface>
      47           0 : static bool Handle_reset(HandleData<Interface> &data, Method method, StringView url) {
      48           0 :         data.send.url = url.str<Interface>();
      49           0 :         data.send.method = method;
      50           0 :         return true;
      51             : }
      52             : 
      53             : template <typename Interface>
      54         700 : static void Handle_addHeader(HandleData<Interface> &data, StringView name, StringView value) {
      55         700 :         name.trimChars<StringView::WhiteSpace>();
      56         700 :         value.trimChars<StringView::WhiteSpace>();
      57             : 
      58         700 :         auto nameStr = string::tolower<Interface>(name);
      59             : 
      60         700 :         auto it = data.send.headers.find(nameStr);
      61         700 :         if (it != data.send.headers.end()) {
      62           0 :                 it->second = value.str<Interface>();
      63             :         } else {
      64         700 :                 data.send.headers.emplace(move(nameStr), value.str<Interface>());
      65             :         }
      66         700 : }
      67             : 
      68             : template <typename Interface>
      69           0 : static void Handle_addMailTo(HandleData<Interface> &data, StringView name) {
      70           0 :         auto nameStr = name.str<Interface>();
      71           0 :         if (!valid::validateEmail(nameStr)) {
      72           0 :                 log::error("NetworkHandle", "Fail to add MailTo: ", name, ": invalid email address");
      73           0 :                 return;
      74             :         }
      75             : 
      76           0 :         auto lb = std::lower_bound(data.send.recipients.begin(), data.send.recipients.end(), nameStr);
      77           0 :         if (lb != data.send.recipients.end() && *lb != name) {
      78           0 :                 data.send.recipients.emplace(lb, move(nameStr));
      79           0 :         } else if (lb != data.send.recipients.end()) {
      80           0 :                 data.send.recipients.emplace_back(move(nameStr));
      81             :         }
      82           0 : }
      83             : 
      84             : template <typename Interface>
      85         400 : static void Handle_setAuthority(HandleData<Interface> &data, StringView user, StringView passwd, AuthMethod method) {
      86         400 :         if (method == AuthMethod::PKey) {
      87           0 :                 return;
      88             :         }
      89             : 
      90         400 :         data.auth.data = pair(user.str<Interface>(), passwd.str<Interface>());
      91         400 :         data.auth.authMethod = method;
      92             : }
      93             : 
      94             : template <typename Interface>
      95           0 : static bool Handle_setPrivateKeyAuth(HandleData<Interface> &iface, const crypto::PrivateKey &pk) {
      96           0 :         auto pub = pk.exportPublic();
      97           0 :         if (!pub) {
      98           0 :                 return false;
      99             :         }
     100             : 
     101           0 :         bool ret = false;
     102           0 :         pub.exportDer([&] (BytesView pub) {
     103           0 :                 pk.sign([&] (BytesView sign) {
     104           0 :                         iface.auth.data = base64::encode<Interface>(data::write(data::ValueTemplate<Interface>({
     105             :                                 data::ValueTemplate<Interface>(pub),
     106             :                                 data::ValueTemplate<Interface>(sign)
     107             :                         })));
     108           0 :                         iface.auth.authMethod = AuthMethod::PKey;
     109           0 :                         ret = true;
     110             :                 }, pub, crypto::SignAlgorithm::RSA_SHA512);
     111             :         });
     112           0 :         return ret;
     113           0 : }
     114             : 
     115             : template <typename Interface>
     116           0 : static bool Handle_setPrivateKeyAuth(HandleData<Interface> &iface, BytesView data) {
     117           0 :         crypto::PrivateKey pk(crypto::Backend::Default, data);
     118           0 :         if (pk) {
     119           0 :                 return Handle_setPrivateKeyAuth(iface, pk);
     120             :         }
     121           0 :         return false;
     122           0 : }
     123             : 
     124             : template <typename Interface>
     125           0 : static void Handle_setSendFile(HandleData<Interface> &iface, StringView str, StringView type) {
     126           0 :         iface.send.data = str.str<Interface>();
     127           0 :         iface.send.size = 0;
     128           0 :         if (!type.empty()) {
     129           0 :                 iface.addHeader("Content-Type", type);
     130             :         } else {
     131             : #if LINUX
     132           0 :                 auto t = network_getUserMime<Interface>(str);
     133           0 :                 if (!t.empty()) {
     134           0 :                         iface.addHeader("Content-Type", t);
     135           0 :                         return;
     136             :                 }
     137             : #endif
     138             : #if MODULE_STAPPLER_BITMAP
     139             :                 // try image format
     140           0 :                 auto fmt = bitmap::detectFormat(StringView(str));
     141           0 :                 if (fmt.first != bitmap::FileFormat::Custom) {
     142           0 :                         iface.addHeader("Content-Type", bitmap::getMimeType(fmt.first));
     143           0 :                         return;
     144             :                 } else {
     145           0 :                         auto str = bitmap::getMimeType(fmt.second);
     146           0 :                         if (!str.empty()) {
     147           0 :                                 iface.addHeader("Content-Type", str);
     148           0 :                                 return;
     149             :                         }
     150             :                 }
     151             : #endif
     152           0 :         }
     153             : }
     154             : 
     155             : template <typename Interface>
     156           0 : static void Handle_setSendCallback(HandleData<Interface> &iface, typename HandleData<Interface>::IOCallback &&cb, size_t size, StringView type) {
     157           0 :         iface.send.data = move(cb);
     158           0 :         iface.send.size = size;
     159           0 :         if (!type.empty()) {
     160           0 :                 iface.addHeader("Content-Type", type);
     161             :         }
     162           0 : }
     163             : 
     164             : template <typename Interface>
     165           0 : static void Handle_setSendData(HandleData<Interface> &iface, StringView data, StringView type) {
     166           0 :         iface.send.data = BytesView((const uint8_t *)data.data(), data.size()).bytes<Interface>();
     167           0 :         iface.send.size = data.size();
     168           0 :         if (!type.empty()) {
     169           0 :                 iface.addHeader("Content-Type", type);
     170             :         }
     171           0 : }
     172             : 
     173             : template <typename Interface>
     174         225 : static void Handle_setSendData(HandleData<Interface> &iface, BytesView data, StringView type) {
     175         225 :         iface.send.data = data.bytes<Interface>();
     176         225 :         iface.send.size = data.size();
     177         225 :         if (!type.empty()) {
     178         225 :                 iface.addHeader("Content-Type", type);
     179             :         }
     180         225 : }
     181             : 
     182             : template <typename Interface>
     183           0 : static void Handle_setSendData(HandleData<Interface> &iface, typename HandleData<Interface>::Bytes &&data, StringView type) {
     184           0 :         iface.send.size = data.size();
     185           0 :         iface.send.data = move(data);
     186           0 :         if (!type.empty()) {
     187           0 :                 iface.addHeader("Content-Type", type);
     188             :         }
     189           0 : }
     190             : 
     191             : template <typename Interface>
     192           0 : static void Handle_setSendData(HandleData<Interface> &iface, const uint8_t *data, size_t size, StringView type) {
     193           0 :         iface.send.size = size;
     194           0 :         iface.send.data = BytesView(data, size).bytes<Interface>();
     195           0 :         if (!type.empty()) {
     196           0 :                 iface.addHeader("Content-Type", type);
     197             :         }
     198           0 : }
     199             : 
     200             : template <typename Interface>
     201         425 : static void Handle_setSendData(HandleData<Interface> &iface, const data::ValueTemplate<Interface> &data, data::EncodeFormat fmt) {
     202         425 :         auto d = data::write<Interface>(data, fmt);
     203         425 :         iface.send.size = d.size();
     204         425 :         iface.send.data = move(d);
     205         425 :         if (fmt.format == data::EncodeFormat::Cbor || fmt.format == data::EncodeFormat::DefaultFormat) {
     206         425 :                 iface.addHeader("Content-Type", "application/cbor");
     207           0 :         } else if (fmt.format == data::EncodeFormat::Json
     208           0 :                         || fmt.format == data::EncodeFormat::Pretty
     209           0 :                         || fmt.format == data::EncodeFormat::PrettyTime) {
     210           0 :                 iface.addHeader("Content-Type", "application/json");
     211             :         }
     212         425 : }
     213             : 
     214             : template <typename Interface>
     215          50 : static StringView Handle_getReceivedHeaderString(const HandleData<Interface> &iface, StringView name) {
     216          50 :         auto h = string::tolower<Interface>(name);
     217          50 :         auto i = iface.receive.parsed.find(h);
     218          50 :         if (i != iface.receive.parsed.end()) {
     219          50 :                 return i->second;
     220             :         }
     221           0 :         return StringView();
     222          50 : }
     223             : 
     224             : template <typename Interface>
     225           0 : static int64_t Handle_getReceivedHeaderInt(const HandleData<Interface> &iface, StringView name) {
     226           0 :         auto h = string::tolower<Interface>(name);
     227           0 :         auto i = iface.receive.parsed.find(h);
     228           0 :         if (i != iface.receive.parsed.end()) {
     229           0 :                 if (!i->second.empty()) {
     230           0 :                         return StringToNumber<int64_t>(i->second.c_str());
     231             :                 }
     232             :         }
     233           0 :         return 0;
     234           0 : }
     235             : 
     236             : #define HANDLE_NAME(ret, name, ...) template <> ret HandleData<HANDLE_INTERFACE>::name(__VA_ARGS__)
     237             : #define HANDLE_NAME_CONST(ret, name, ...) template <> auto HandleData<HANDLE_INTERFACE>::name(__VA_ARGS__) const -> ret
     238             : 
     239             : #define HANDLE_INTERFACE memory::PoolInterface
     240             : 
     241           0 : HANDLE_NAME(,~HandleData) { Handle_destroy(*this); }
     242           0 : HANDLE_NAME(bool, reset, Method method, StringView url) { return Handle_reset(*this, method, url); }
     243           0 : HANDLE_NAME_CONST(long, getResponseCode) { return process.responseCode; }
     244           0 : HANDLE_NAME_CONST(long, getErrorCode) { return process.errorCode; }
     245           0 : HANDLE_NAME_CONST(StringView, getError) { return process.error; }
     246           0 : HANDLE_NAME(void, setCookieFile, StringView str) { process.cookieFile = filesystem::native::posixToNative<HANDLE_INTERFACE>(str); }
     247           0 : HANDLE_NAME(void, setUserAgent, StringView str) { send.userAgent = str.str<HANDLE_INTERFACE>(); }
     248           0 : HANDLE_NAME(void, setUrl, StringView str) { send.url = str.str<HANDLE_INTERFACE>(); }
     249           0 : HANDLE_NAME(void, clearHeaders) { send.headers.clear(); }
     250           0 : HANDLE_NAME(void, addHeader, StringView header, StringView value) { Handle_addHeader(*this, header, value); }
     251           0 : HANDLE_NAME_CONST(const HeaderMap &, getRequestHeaders) { return send.headers; }
     252             : 
     253           0 : HANDLE_NAME(void, setMailFrom, StringView from) { send.from = from.str<HANDLE_INTERFACE>(); }
     254           0 : HANDLE_NAME(void, clearMailTo) { send.recipients.clear(); }
     255           0 : HANDLE_NAME(void, addMailTo, StringView to) { Handle_addMailTo(*this, to); }
     256           0 : HANDLE_NAME(void, setAuthority, StringView user, StringView passwd, AuthMethod method) { Handle_setAuthority(*this, user, passwd, method); }
     257           0 : HANDLE_NAME(bool, setPrivateKeyAuth, BytesView priv) { return Handle_setPrivateKeyAuth(*this, priv); }
     258           0 : HANDLE_NAME(bool, setPrivateKeyAuth, const crypto::PrivateKey &priv) { return Handle_setPrivateKeyAuth(*this, priv); }
     259           0 : HANDLE_NAME(void, setProxy, StringView proxy, StringView authData) {
     260           0 :         auth.proxyAddress = proxy.str<HANDLE_INTERFACE>();
     261           0 :         auth.proxyAuth = authData.str<HANDLE_INTERFACE>();
     262           0 : }
     263           0 : HANDLE_NAME(void, setReceiveFile, StringView filename, bool resumeDownload) {
     264           0 :         receive.data = filename.str<HANDLE_INTERFACE>();
     265           0 :         receive.resumeDownload = resumeDownload;
     266           0 : }
     267           0 : HANDLE_NAME(void, setReceiveCallback, IOCallback &&cb) { receive.data = move(cb); }
     268           0 : HANDLE_NAME(void, setResumeDownload, bool resumeDownload) { receive.resumeDownload = resumeDownload; }
     269           0 : HANDLE_NAME(void, setResumeOffset, uint64_t offset) { receive.offset = offset; }
     270           0 : HANDLE_NAME(void, setSendSize, size_t size) { send.size = size; }
     271           0 : HANDLE_NAME(void, setSendFile, StringView filename, StringView type) { Handle_setSendFile(*this, filename, type); }
     272           0 : HANDLE_NAME(void, setSendCallback, IOCallback &&cb, size_t outSize, StringView type) { Handle_setSendCallback(*this, move(cb), outSize, type); }
     273           0 : HANDLE_NAME(void, setSendData, StringView data, StringView type) { Handle_setSendData(*this, data, type); }
     274           0 : HANDLE_NAME(void, setSendData, BytesView data, StringView type) { Handle_setSendData(*this, data, type); }
     275           0 : HANDLE_NAME(void, setSendData, Bytes &&data, StringView type) { Handle_setSendData(*this, move(data), type); }
     276           0 : HANDLE_NAME(void, setSendData, const uint8_t *data, size_t size, StringView type) { Handle_setSendData(*this, data, size, type); }
     277           0 : HANDLE_NAME(void, setSendData, const Value &value, data::EncodeFormat fmt) { Handle_setSendData(*this, value, fmt); }
     278           0 : HANDLE_NAME_CONST(StringView, getReceivedHeaderString, StringView name) { return Handle_getReceivedHeaderString(*this, name); }
     279           0 : HANDLE_NAME_CONST(int64_t, getReceivedHeaderInt, StringView name) { return Handle_getReceivedHeaderInt(*this, name); }
     280             : 
     281           0 : HANDLE_NAME_CONST(Method, getMethod) { return send.method; }
     282           0 : HANDLE_NAME_CONST(StringView, getUrl) { return send.url; }
     283           0 : HANDLE_NAME_CONST(StringView, getCookieFile) { return process.cookieFile; }
     284           0 : HANDLE_NAME_CONST(StringView, getUserAgent) { return send.userAgent; }
     285           0 : HANDLE_NAME_CONST(StringView, getResponseContentType) { return receive.contentType; }
     286           0 : HANDLE_NAME_CONST(const Vector<String> &, getRecievedHeaders) { return receive.headers; }
     287             : 
     288           0 : HANDLE_NAME(void, setDebug, bool value) { process.debug = value; }
     289           0 : HANDLE_NAME(void, setReuse, bool value) { process.reuse = value; }
     290           0 : HANDLE_NAME(void, setShared, bool value) { process.shared = value; }
     291           0 : HANDLE_NAME(void, setSilent, bool value) { process.silent = value; }
     292           0 : HANDLE_NAME_CONST(const StringStream &, getDebugData) { return process.debugData; }
     293             : 
     294           0 : HANDLE_NAME(void, setDownloadProgress, ProgressCallback &&cb) { process.downloadProgress = move(cb); }
     295           0 : HANDLE_NAME(void, setUploadProgress, ProgressCallback &&cb) { process.uploadProgress = move(cb); }
     296             : 
     297           0 : HANDLE_NAME(void, setConnectTimeout, int time) { process.connectTimeout = time; }
     298           0 : HANDLE_NAME(void, setLowSpeedLimit, int time, size_t limit) { process.lowSpeedTime = time; process.lowSpeedLimit = int(limit); }
     299             : 
     300           0 : HANDLE_NAME(void, setVerifyTls, bool value) { process.verifyTsl = value; }
     301             : 
     302             : #undef HANDLE_INTERFACE
     303             : 
     304             : 
     305             : #define HANDLE_INTERFACE memory::StandartInterface
     306             : 
     307        3025 : HANDLE_NAME(,~HandleData) { Handle_destroy(*this); }
     308           0 : HANDLE_NAME(bool, reset, Method method, StringView url) { return Handle_reset(*this, method, url); }
     309          25 : HANDLE_NAME_CONST(long, getResponseCode) { return process.responseCode; }
     310           0 : HANDLE_NAME_CONST(long, getErrorCode) { return process.errorCode; }
     311           0 : HANDLE_NAME_CONST(StringView, getError) { return process.error; }
     312         700 : HANDLE_NAME(void, setCookieFile, StringView str) { process.cookieFile = filesystem::native::posixToNative<HANDLE_INTERFACE>(str); }
     313          25 : HANDLE_NAME(void, setUserAgent, StringView str) { send.userAgent = str.str<HANDLE_INTERFACE>(); }
     314           0 : HANDLE_NAME(void, setUrl, StringView str) { send.url = str.str<HANDLE_INTERFACE>(); }
     315           0 : HANDLE_NAME(void, clearHeaders) { send.headers.clear(); }
     316         700 : HANDLE_NAME(void, addHeader, StringView header, StringView value) { Handle_addHeader(*this, header, value); }
     317           0 : HANDLE_NAME_CONST(const HeaderMap &, getRequestHeaders) { return send.headers; }
     318             : 
     319           0 : HANDLE_NAME(void, setMailFrom, StringView from) { send.from = from.str<HANDLE_INTERFACE>(); }
     320           0 : HANDLE_NAME(void, clearMailTo) { send.recipients.clear(); }
     321           0 : HANDLE_NAME(void, addMailTo, StringView to) { Handle_addMailTo(*this, to); }
     322         400 : HANDLE_NAME(void, setAuthority, StringView user, StringView passwd, AuthMethod method) { Handle_setAuthority(*this, user, passwd, method); }
     323           0 : HANDLE_NAME(bool, setPrivateKeyAuth, BytesView priv) { return Handle_setPrivateKeyAuth(*this, priv); }
     324           0 : HANDLE_NAME(bool, setPrivateKeyAuth, const crypto::PrivateKey &priv) { return Handle_setPrivateKeyAuth(*this, priv); }
     325           0 : HANDLE_NAME(void, setProxy, StringView proxy, StringView authData) {
     326           0 :         auth.proxyAddress = proxy.str<HANDLE_INTERFACE>();
     327           0 :         auth.proxyAuth = authData.str<HANDLE_INTERFACE>();
     328           0 : }
     329           0 : HANDLE_NAME(void, setReceiveFile, StringView filename, bool resumeDownload) {
     330           0 :         receive.data = filename.str<HANDLE_INTERFACE>();
     331           0 :         receive.resumeDownload = resumeDownload;
     332           0 : }
     333        2850 : HANDLE_NAME(void, setReceiveCallback, IOCallback &&cb) { receive.data = move(cb); }
     334           0 : HANDLE_NAME(void, setResumeDownload, bool resumeDownload) { receive.resumeDownload = resumeDownload; }
     335           0 : HANDLE_NAME(void, setResumeOffset, uint64_t offset) { receive.offset = offset; }
     336           0 : HANDLE_NAME(void, setSendSize, size_t size) { send.size = size; }
     337           0 : HANDLE_NAME(void, setSendFile, StringView filename, StringView type) { Handle_setSendFile(*this, filename, type); }
     338           0 : HANDLE_NAME(void, setSendCallback, IOCallback &&cb, size_t outSize, StringView type) { Handle_setSendCallback(*this, move(cb), outSize, type); }
     339           0 : HANDLE_NAME(void, setSendData, StringView data, StringView type) { Handle_setSendData(*this, data, type); }
     340         225 : HANDLE_NAME(void, setSendData, BytesView data, StringView type) { Handle_setSendData(*this, data, type); }
     341           0 : HANDLE_NAME(void, setSendData, Bytes &&data, StringView type) { Handle_setSendData(*this, move(data), type); }
     342           0 : HANDLE_NAME(void, setSendData, const uint8_t *data, size_t size, StringView type) { Handle_setSendData(*this, data, size, type); }
     343         425 : HANDLE_NAME(void, setSendData, const Value &value, data::EncodeFormat fmt) { Handle_setSendData(*this, value, fmt); }
     344          50 : HANDLE_NAME_CONST(StringView, getReceivedHeaderString, StringView name) { return Handle_getReceivedHeaderString(*this, name); }
     345           0 : HANDLE_NAME_CONST(int64_t, getReceivedHeaderInt, StringView name) { return Handle_getReceivedHeaderInt(*this, name); }
     346             : 
     347           0 : HANDLE_NAME_CONST(Method, getMethod) { return send.method; }
     348           0 : HANDLE_NAME_CONST(StringView, getUrl) { return send.url; }
     349           0 : HANDLE_NAME_CONST(StringView, getCookieFile) { return process.cookieFile; }
     350           0 : HANDLE_NAME_CONST(StringView, getUserAgent) { return send.userAgent; }
     351           0 : HANDLE_NAME_CONST(StringView, getResponseContentType) { return receive.contentType; }
     352           0 : HANDLE_NAME_CONST(const Vector<String> &, getRecievedHeaders) { return receive.headers; }
     353             : 
     354           0 : HANDLE_NAME(void, setDebug, bool value) { process.debug = value; }
     355           0 : HANDLE_NAME(void, setReuse, bool value) { process.reuse = value; }
     356           0 : HANDLE_NAME(void, setShared, bool value) { process.shared = value; }
     357           0 : HANDLE_NAME(void, setSilent, bool value) { process.silent = value; }
     358           0 : HANDLE_NAME_CONST(const StringStream &, getDebugData) { return process.debugData; }
     359             : 
     360          25 : HANDLE_NAME(void, setDownloadProgress, ProgressCallback &&cb) { process.downloadProgress = move(cb); }
     361          25 : HANDLE_NAME(void, setUploadProgress, ProgressCallback &&cb) { process.uploadProgress = move(cb); }
     362             : 
     363           0 : HANDLE_NAME(void, setConnectTimeout, int time) { process.connectTimeout = time; }
     364           0 : HANDLE_NAME(void, setLowSpeedLimit, int time, size_t limit) { process.lowSpeedTime = time; process.lowSpeedLimit = int(limit); }
     365             : 
     366          25 : HANDLE_NAME(void, setVerifyTls, bool value) { process.verifyTsl = value; }
     367             : 
     368             : #undef HANDLE_INTERFACE
     369             : 
     370             : template <> const ReceiveData<memory::StandartInterface>::DataSource &
     371          25 : HandleData<memory::StandartInterface>::getReceiveDataSource() const {
     372          25 :         return receive.data;
     373             : }
     374             : 
     375             : template <> const ReceiveData<memory::PoolInterface>::DataSource &
     376           0 : HandleData<memory::PoolInterface>::getReceiveDataSource() const {
     377           0 :         return receive.data;
     378             : }
     379             : 
     380             : template <> const SendData<memory::StandartInterface>::DataSource &
     381           0 : HandleData<memory::StandartInterface>::getSendDataSource() const {
     382           0 :         return send.data;
     383             : }
     384             : 
     385             : template <> const SendData<memory::PoolInterface>::DataSource &
     386           0 : HandleData<memory::PoolInterface>::getSendDataSource() const {
     387           0 :         return send.data;
     388             : }
     389             : 
     390             : template <> void
     391          25 : HandleData<memory::StandartInterface>::setHeaderCallback(HeaderCallback &&cb) {
     392          25 :         receive.headerCallback = move(cb);
     393          25 : }
     394             : 
     395             : template <> void
     396           0 : HandleData<memory::PoolInterface>::setHeaderCallback(HeaderCallback &&cb) {
     397           0 :         receive.headerCallback = move(cb);
     398           0 : }
     399             : 
     400             : template <> const HandleData<memory::StandartInterface>::HeaderCallback &
     401           0 : HandleData<memory::StandartInterface>::getHeaderCallback() const {
     402           0 :         return receive.headerCallback;
     403             : }
     404             : 
     405             : template <> const HandleData<memory::PoolInterface>::HeaderCallback &
     406           0 : HandleData<memory::PoolInterface>::getHeaderCallback() const {
     407           0 :         return receive.headerCallback;
     408             : }
     409             : 
     410             : }
     411             : 
     412             : #undef SP_TERMINATED_DATA

Generated by: LCOV version 1.14