aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/tls/asio/asio_async_write_op.h
blob: ac1d96857a0892baae11eecafd2cccd311e4e028 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/*
* TLS Stream Helper
* (C) 2018-2019 Jack Lloyd
*     2018-2019 Hannes Rantzsch, Tim Oesterreich, Rene Meusel
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#ifndef BOTAN_ASIO_ASYNC_WRITE_OP_H_
#define BOTAN_ASIO_ASYNC_WRITE_OP_H_

#if defined(BOTAN_HAS_TLS) && defined(BOTAN_HAS_BOOST_ASIO)

#include <boost/version.hpp>
#if BOOST_VERSION > 106600

#include <botan/internal/asio_async_base.h>
#include <botan/internal/asio_includes.h>
#include <botan/internal/asio_stream_core.h>

#include <boost/asio/yield.hpp>

namespace Botan {

namespace TLS {

template <typename Handler, class Stream, class Allocator = std::allocator<void>>
struct AsyncWriteOperation : public AsyncBase<Handler, typename Stream::executor_type, Allocator>
   {
   template <class HandlerT>
   AsyncWriteOperation(HandlerT&& handler,
                       Stream& stream,
                       StreamCore& core,
                       std::size_t plainBytesTransferred,
                       const boost::system::error_code& ec = {})
      : AsyncBase<Handler, typename Stream::executor_type, Allocator>(
           std::forward<HandlerT>(handler),
           stream.get_executor())
      , m_stream(stream)
      , m_core(core)
      , m_plainBytesTransferred(plainBytesTransferred)
      {
      this->operator()(ec, std::size_t(0), false);
      }

   AsyncWriteOperation(AsyncWriteOperation&&) = default;

   void operator()(boost::system::error_code ec, std::size_t bytes_transferred, bool isContinuation = true)
      {
      reenter(this)
         {
         m_core.consumeSendBuffer(bytes_transferred);

         if(m_core.hasDataToSend() && !ec){
            boost::asio::async_write(m_stream.next_layer(), m_core.sendBuffer(), std::move(*this));
            return;
         }

         if(!isContinuation)
            {
            m_ec = ec;
            yield m_stream.next_layer().async_write_some(boost::asio::const_buffer(), std::move(*this));
            ec = m_ec;
            }

         // the size of the sent TLS record can differ from the size of the payload due to TLS encryption. We need to tell
         // the handler how many bytes of the original data we already processed.
         this->complete_now(ec, ec ? 0 : m_plainBytesTransferred);
         }
      }

   Stream&     m_stream;
   StreamCore& m_core;

   std::size_t m_plainBytesTransferred;
   boost::system::error_code m_ec;
   };

}  // namespace TLS

}  // namespace Botan

#include <boost/asio/unyield.hpp>

#endif // BOOST_VERSION
#endif // BOTAN_HAS_TLS && BOTAN_HAS_BOOST_ASIO
#endif // BOTAN_ASIO_ASYNC_WRITE_OP_H_