1 /*
2 * TLS Blocking API
3 * (C) 2013 Jack Lloyd
4 *     2016 Matthias Gierlings
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8 
9 #include <botan/tls_blocking.h>
10 
11 namespace Botan {
12 
13 namespace TLS {
14 
Blocking_Client(read_fn reader,write_fn writer,Session_Manager & session_manager,Credentials_Manager & creds,const Policy & policy,RandomNumberGenerator & rng,const Server_Information & server_info,const Protocol_Version & offer_version,const std::vector<std::string> & next)15 Blocking_Client::Blocking_Client(read_fn reader,
16                                  write_fn writer,
17                                  Session_Manager& session_manager,
18                                  Credentials_Manager& creds,
19                                  const Policy& policy,
20                                  RandomNumberGenerator& rng,
21                                  const Server_Information& server_info,
22                                  const Protocol_Version& offer_version,
23                                  const std::vector<std::string>& next) :
24    m_read(reader),
25    m_callbacks(new TLS::Compat_Callbacks(
26                   /*
27                   we are ok using deprecated features here because the whole Blocking_Client class
28                   is also deprecated, so just silence the warning.
29                   */
30                TLS::Compat_Callbacks::SILENCE_DEPRECATION_WARNING::PLEASE,
31                writer,
32                std::bind(&Blocking_Client::data_cb, this, std::placeholders::_1, std::placeholders::_2),
33                std::function<void (Alert)>(std::bind(&Blocking_Client::alert_cb, this, std::placeholders::_1)),
34                std::bind(&Blocking_Client::handshake_cb, this, std::placeholders::_1)
35              )),
36    m_channel(*m_callbacks.get(),
37              session_manager,
38              creds,
39              policy,
40              rng,
41              server_info,
42              offer_version,
43              next)
44    {
45    }
46 
handshake_cb(const Session & session)47 bool Blocking_Client::handshake_cb(const Session& session)
48    {
49    return this->handshake_complete(session);
50    }
51 
alert_cb(const Alert & alert)52 void Blocking_Client::alert_cb(const Alert& alert)
53    {
54    this->alert_notification(alert);
55    }
56 
data_cb(const uint8_t data[],size_t data_len)57 void Blocking_Client::data_cb(const uint8_t data[], size_t data_len)
58    {
59    m_plaintext.insert(m_plaintext.end(), data, data + data_len);
60    }
61 
do_handshake()62 void Blocking_Client::do_handshake()
63    {
64    std::vector<uint8_t> readbuf(4096);
65 
66    while(!m_channel.is_closed() && !m_channel.is_active())
67       {
68       const size_t from_socket = m_read(readbuf.data(), readbuf.size());
69       m_channel.received_data(readbuf.data(), from_socket);
70       }
71    }
72 
read(uint8_t buf[],size_t buf_len)73 size_t Blocking_Client::read(uint8_t buf[], size_t buf_len)
74    {
75    std::vector<uint8_t> readbuf(4096);
76 
77    while(m_plaintext.empty() && !m_channel.is_closed())
78       {
79       const size_t from_socket = m_read(readbuf.data(), readbuf.size());
80       m_channel.received_data(readbuf.data(), from_socket);
81       }
82 
83    const size_t returned = std::min(buf_len, m_plaintext.size());
84 
85    for(size_t i = 0; i != returned; ++i)
86       buf[i] = m_plaintext[i];
87    m_plaintext.erase(m_plaintext.begin(), m_plaintext.begin() + returned);
88 
89    BOTAN_ASSERT_IMPLICATION(returned == 0, m_channel.is_closed(),
90                             "Only return zero if channel is closed");
91 
92    return returned;
93    }
94 
95 }
96 
97 }
98