diff options
author | lloyd <[email protected]> | 2011-12-27 15:17:04 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2011-12-27 15:17:04 +0000 |
commit | 726158b58a45689953fb474897fdee661829431a (patch) | |
tree | 03f217557c436c54689b75d176276a91a271fc93 | |
parent | 9990229e5a6233e609f316aa6e7740257ac07759 (diff) |
Make the server example less fragile, write a class that emulates the
old blocking interface and use that.
-rw-r--r-- | doc/examples/tls_server.cpp | 148 |
1 files changed, 118 insertions, 30 deletions
diff --git a/doc/examples/tls_server.cpp b/doc/examples/tls_server.cpp index eff3a3c3c..0f9b16871 100644 --- a/doc/examples/tls_server.cpp +++ b/doc/examples/tls_server.cpp @@ -4,6 +4,7 @@ #include <botan/rsa.h> #include <botan/dsa.h> #include <botan/x509self.h> +#include <botan/secqueue.h> #include "socket.h" @@ -14,6 +15,102 @@ using namespace Botan; #include <iostream> #include <memory> +class Blocking_TLS_Server + { + public: + Blocking_TLS_Server(std::tr1::function<void (const byte[], size_t)> output_fn, + std::tr1::function<size_t (byte[], size_t)> input_fn, + TLS_Session_Manager& sessions, + TLS_Policy& policy, + RandomNumberGenerator& rng, + const X509_Certificate& cert, + const Private_Key& key) : + input_fn(input_fn), + server( + output_fn, + std::tr1::bind(&Blocking_TLS_Server::reader_fn, std::tr1::ref(*this), _1, _2, _3), + sessions, + policy, + rng, + cert, + key), + exit(false) + { + read_loop(); + } + + size_t read(byte buf[], size_t buf_len) + { + size_t got = read_queue.read(buf, buf_len); + + while(!exit && !got) + { + read_loop(5); // header size + got = read_queue.read(buf, buf_len); + } + + return got; + } + + void write(const byte buf[], size_t buf_len) + { + server.queue_for_sending(buf, buf_len); + } + + void close() { server.close(); } + + bool is_active() const { return server.is_active(); } + + TLS_Server& underlying() { return server; } + private: + void read_loop(size_t init_desired = 0) + { + size_t desired = init_desired; + + byte buf[4096]; + while(!exit && (!server.is_active() || desired)) + { + const size_t asking = std::max(sizeof(buf), std::min(desired, static_cast<size_t>(1))); + + const size_t socket_got = input_fn(&buf[0], asking); + + if(socket_got == 0) // eof? + { + close(); + exit = true; + } + + desired = server.received_data(&buf[0], socket_got); + } + } + + void reader_fn(const byte buf[], size_t buf_len, u16bit alert_code) + { + if(buf_len == 0 && alert_code != NO_ALERT_TYPE) + { + printf("Alert: %d, quitting\n", alert_code); + exit = true; + } + + printf("Got %d bytes: ", buf_len); + for(size_t i = 0; i != buf_len; ++i) + { + if(isprint(buf[i])) + printf("%c", buf[i]); + else + printf("0x%02X", buf[i]); + } + printf("\n"); + + read_queue.write(buf, buf_len); + } + + std::tr1::function<size_t (byte[], size_t)> input_fn; + TLS_Server server; + SecureQueue read_queue; + bool exit; + }; + class Server_TLS_Policy : public TLS_Policy { public: @@ -30,13 +127,6 @@ class Server_TLS_Policy : public TLS_Policy } }; -void proc_data(const byte data[], size_t data_len, u16bit alert_info) - { - printf("Block of data %d bytes alert %04X\n", (int)data_len, alert_info); - for(size_t i = 0; i != data_len; ++i) - printf("%c", data[i]); - } - int main(int argc, char* argv[]) { int port = 4433; @@ -75,44 +165,42 @@ int main(int argc, char* argv[]) printf("Got new connection\n"); - TLS_Server tls( + Blocking_TLS_Server tls( std::tr1::bind(&Socket::write, std::tr1::ref(sock), _1, _2), - proc_data, + std::tr1::bind(&Socket::read, std::tr1::ref(sock), _1, _2, true), sessions, policy, rng, cert, key); - SecureVector<byte> buf(1024); - size_t desired = 0; - while(!tls.is_active() || desired) - { - const size_t socket_got = sock->read(&buf[0], desired || 1); - desired = tls.received_data(&buf[0], socket_got); - } - - const std::string hostname = tls.server_name_indicator(); - - if(hostname != "") - printf("Client requested host '%s'\n", hostname.c_str()); - - printf("Writing some text\n"); + const char* msg = "Welcome to the best echo server evar\n"; + tls.write((const Botan::byte*)msg, strlen(msg)); - char msg[] = "Welcome to the best echo server evar\n"; - tls.queue_for_sending((const Botan::byte*)msg, strlen(msg)); + std::string line; - while(true) + while(tls.is_active()) { - size_t got = sock->read(&buf[0], buf.size(), true); + byte b; + size_t got = tls.read(&b, 1); if(got == 0) break; - tls.received_data(&buf[0], got); - } + line += (char)b; + if(b == '\n') + { + tls.write(reinterpret_cast<const byte*>(line.data()), line.size()); + + if(line == "quit\n") + { + tls.close(); + break; + } - tls.close(); + line.clear(); + } + } } catch(std::exception& e) { printf("%s\n", e.what()); } } |