aboutsummaryrefslogtreecommitdiffstats
path: root/doc/examples
diff options
context:
space:
mode:
authorlloyd <[email protected]>2011-12-23 16:14:45 +0000
committerlloyd <[email protected]>2011-12-23 16:14:45 +0000
commitd363602f95f1514b4b595d9912fba2e503edcb21 (patch)
tree70d036ff58e67629103a4ac6c1374ec90b6bd3db /doc/examples
parenta3d81efbd2c56749d4abf9e6a27cb36cbbb10702 (diff)
First stab at an event driven TLS client.
Diffstat (limited to 'doc/examples')
-rw-r--r--doc/examples/socket.h20
-rw-r--r--doc/examples/tls_client.cpp109
2 files changed, 92 insertions, 37 deletions
diff --git a/doc/examples/socket.h b/doc/examples/socket.h
index f7ce98fea..f10ff9f26 100644
--- a/doc/examples/socket.h
+++ b/doc/examples/socket.h
@@ -48,6 +48,7 @@
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
+ #include <fcntl.h>
typedef int socket_t;
const socket_t invalid_socket = -1;
@@ -66,7 +67,7 @@
class Socket
{
public:
- size_t read(unsigned char[], size_t);
+ size_t read(unsigned char[], size_t, bool dont_block = false);
void write(const unsigned char[], size_t);
std::string peer_id() const { return peer; }
@@ -158,23 +159,28 @@ Socket::Socket(const std::string& host, unsigned short port) : peer(host)
throw std::runtime_error("Socket: connect failed");
}
+ //fcntl(fd, F_SETFL, O_NONBLOCK);
+
sockfd = fd;
}
/**
* Read from a Unix socket
*/
-size_t Socket::read(unsigned char buf[], size_t length)
+size_t Socket::read(unsigned char buf[], size_t length, bool partial)
{
if(sockfd == invalid_socket)
throw std::runtime_error("Socket::read: Socket not connected");
size_t got = 0;
+ int flags = MSG_NOSIGNAL;
+
while(length)
{
- ssize_t this_time = ::recv(sockfd, (char*)buf + got,
- length, MSG_NOSIGNAL);
+ ssize_t this_time = ::recv(sockfd, (char*)buf + got, length, flags);
+
+ const bool full_ret = (this_time == length);
if(this_time == 0)
break;
@@ -183,13 +189,19 @@ size_t Socket::read(unsigned char buf[], size_t length)
{
if(socket_error_code == EINTR)
this_time = 0;
+ else if(socket_error_code == EAGAIN)
+ break;
else
throw std::runtime_error("Socket::read: Socket read failed");
}
got += this_time;
length -= this_time;
+
+ if(partial && !full_ret)
+ break;
}
+
return got;
}
diff --git a/doc/examples/tls_client.cpp b/doc/examples/tls_client.cpp
index cedfe1ca8..a51febfcf 100644
--- a/doc/examples/tls_client.cpp
+++ b/doc/examples/tls_client.cpp
@@ -25,6 +25,76 @@ class Client_TLS_Policy : public TLS_Policy
}
};
+class HTTPS_Client
+ {
+ public:
+ HTTPS_Client(const std::string& host, u16bit port, RandomNumberGenerator& r) :
+ rng(r),
+ socket(host, port),
+ client(std::tr1::bind(&HTTPS_Client::socket_write, std::tr1::ref(*this), _1, _2),
+ std::tr1::bind(&HTTPS_Client::proc_data, std::tr1::ref(*this), _1, _2, _3),
+ policy,
+ rng)
+ {
+ SecureVector<byte> socket_buf(1024);
+ size_t desired = 0;
+
+ quit_reading = false;
+
+ while(!client.handshake_complete() || desired)
+ {
+ const size_t socket_got = socket.read(&socket_buf[0], socket_buf.size());
+ //printf("Got %d bytes from socket\n", socket_got);
+ desired = client.received_data(&socket_buf[0], socket_got);
+ socket_buf.resize(desired || 1);
+ //printf("Going around for another read?\n");
+ }
+ }
+
+ void socket_write(const byte buf[], size_t buf_size)
+ {
+ std::cout << "socket_write " << buf_size << "\n";
+ socket.write(buf, buf_size);
+ }
+
+ 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]);
+
+ if(data_len == 0 && alert_info == 0)
+ quit_reading = true;
+ }
+
+ void write(const std::string& s)
+ {
+ client.queue_for_sending((const byte*)s.c_str(), s.length());
+ }
+
+ void read_response()
+ {
+ while(true)
+ {
+ SecureVector<byte> buf(4096);
+
+ size_t got = socket.read(&buf[0], buf.size(), true);
+
+ if(got == 0)
+ break;
+
+ client.received_data(&buf[0], got);
+ }
+ }
+
+ private:
+ bool quit_reading;
+ RandomNumberGenerator& rng;
+ Socket socket;
+ Client_TLS_Policy policy;
+ TLS_Client client;
+ };
+
int main(int argc, char* argv[])
{
if(argc != 2 && argc != 3)
@@ -40,48 +110,21 @@ int main(int argc, char* argv[])
std::string host = argv[1];
u32bit port = argc == 3 ? Botan::to_u32bit(argv[2]) : 443;
- printf("Connecting to %s:%d...\n", host.c_str(), port);
-
- SocketInitializer socket_init;
-
- Socket sock(argv[1], port);
+ //SocketInitializer socket_init;
AutoSeeded_RNG rng;
- Client_TLS_Policy policy;
-
- TLS_Client tls(std::tr1::bind(&Socket::read, std::tr1::ref(sock), _1, _2),
- std::tr1::bind(&Socket::write, std::tr1::ref(sock), _1, _2),
- policy, rng);
+ printf("Connecting to %s:%d...\n", host.c_str(), port);
- printf("Handshake extablished...\n");
+ HTTPS_Client https(host, port, rng);
-#if 0
- std::string http_command = "GET / HTTP/1.1\r\n"
- "Server: " + host + ':' + to_string(port) + "\r\n\r\n";
-#else
std::string http_command = "GET / HTTP/1.0\r\n\r\n";
-#endif
- tls.write((const Botan::byte*)http_command.c_str(),
- http_command.length());
+ printf("Sending request\n");
+ https.write(http_command);
- size_t total_got = 0;
-
- while(true)
- {
- if(tls.is_closed())
- break;
-
- Botan::byte buf[128+1] = { 0 };
- size_t got = tls.read(buf, sizeof(buf)-1);
- printf("%s", buf);
- fflush(0);
-
- total_got += got;
- }
+ https.read_response();
- printf("\nRetrieved %d bytes total\n", total_got);
}
catch(std::exception& e)
{