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