aboutsummaryrefslogtreecommitdiffstats
path: root/doc/examples
diff options
context:
space:
mode:
authorlloyd <[email protected]>2011-12-30 18:04:36 +0000
committerlloyd <[email protected]>2011-12-30 18:04:36 +0000
commit07b11b4b3d9c7ef289050252c29bc8174d102148 (patch)
tree54e70aecf09ff89b0e92b5e5c081d41846dd7ba0 /doc/examples
parent8a4d079cd6219a27f3a9fe1fdac74bc27a6338d8 (diff)
New more interesting client, pipes stdin<->remote box via TLS ala
OpenSSL's s_client instead of just doing a one-shot request.
Diffstat (limited to 'doc/examples')
-rw-r--r--doc/examples/tls_client.cpp196
1 files changed, 122 insertions, 74 deletions
diff --git a/doc/examples/tls_client.cpp b/doc/examples/tls_client.cpp
index 1d62bbc20..3fb7f10c6 100644
--- a/doc/examples/tls_client.cpp
+++ b/doc/examples/tls_client.cpp
@@ -1,14 +1,21 @@
#include <botan/botan.h>
#include <botan/tls_client.h>
-#include "socket.h"
-
-using namespace Botan;
-
#include <stdio.h>
#include <string>
#include <iostream>
#include <memory>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+using namespace Botan;
+
class Client_TLS_Policy : public TLS_Policy
{
public:
@@ -25,83 +32,74 @@ class Client_TLS_Policy : public TLS_Policy
}
};
-class HTTPS_Client
+int connect_to_host(const std::string& host, u16bit port)
{
- 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),
- sessions,
- policy,
- rng,
- host,
- host + "_username")
- {
- SecureVector<byte> socket_buf(1024);
- size_t desired = 0;
+ hostent* host_addr = ::gethostbyname(host.c_str());
- quit_reading = false;
+ if(host_addr == 0)
+ throw std::runtime_error("gethostbyname failed for " + host);
- while(!client.is_active() || 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");
+ if(host_addr->h_addrtype != AF_INET) // FIXME
+ throw std::runtime_error(host + " has IPv6 address");
- if(quit_reading)
- break;
- }
- }
+ int fd = ::socket(PF_INET, SOCK_STREAM, 0);
+ if(fd == -1)
+ throw std::runtime_error("Unable to acquire socket");
- void socket_write(const byte buf[], size_t buf_size)
- {
- std::cout << "socket_write " << buf_size << "\n";
- socket.write(buf, buf_size);
- }
+ sockaddr_in socket_info;
+ ::memset(&socket_info, 0, sizeof(socket_info));
+ socket_info.sin_family = AF_INET;
+ socket_info.sin_port = htons(port);
- void proc_data(const byte data[], size_t data_len, u16bit alert_info)
- {
- printf("Block of data %d bytes alert %d\n", (int)data_len, alert_info);
- for(size_t i = 0; i != data_len; ++i)
- printf("%c", data[i]);
+ ::memcpy(&socket_info.sin_addr,
+ host_addr->h_addr,
+ host_addr->h_length);
- if(alert_info != 255)
- quit_reading = true;
- }
+ socket_info.sin_addr = *(struct in_addr*)host_addr->h_addr; // FIXME
- void write(const std::string& s)
- {
- client.queue_for_sending((const byte*)s.c_str(), s.length());
- }
+ if(::connect(fd, (sockaddr*)&socket_info, sizeof(struct sockaddr)) != 0)
+ {
+ ::close(fd);
+ throw std::runtime_error("connect failed");
+ }
- void read_response()
- {
- while(!quit_reading)
- {
- SecureVector<byte> buf(4096);
+ return fd;
+ }
- size_t got = socket.read(&buf[0], buf.size(), true);
+void socket_write(int sockfd, const byte buf[], size_t length)
+ {
+ size_t offset = 0;
- if(got == 0)
- break;
+ while(length)
+ {
+ ssize_t sent = ::send(sockfd, (const char*)buf + offset,
+ length, MSG_NOSIGNAL);
- client.received_data(&buf[0], got);
- }
+ if(sent == -1)
+ {
+ if(errno == EINTR)
+ sent = 0;
+ else
+ throw std::runtime_error("Socket::write: Socket write failed");
}
- private:
- bool quit_reading;
- RandomNumberGenerator& rng;
- Socket socket;
- Client_TLS_Policy policy;
- TLS_Session_Manager_In_Memory sessions;
+ offset += sent;
+ length -= sent;
+ }
- TLS_Client client;
- };
+ //printf("socket write %d\n", offset);
+ }
+
+void process_data(const byte buf[], size_t buf_size, u16bit alert_info)
+ {
+ if(alert_info != NULL_ALERT)
+ {
+ printf("Alert: %d\n", alert_info);
+ }
+
+ for(size_t i = 0; i != buf_size; ++i)
+ printf("%c", buf[i]);
+ }
int main(int argc, char* argv[])
{
@@ -114,25 +112,75 @@ int main(int argc, char* argv[])
try
{
LibraryInitializer botan_init;
+ AutoSeeded_RNG rng;
+ Client_TLS_Policy policy;
+ TLS_Session_Manager_In_Memory session_manager;
std::string host = argv[1];
u32bit port = argc == 3 ? Botan::to_u32bit(argv[2]) : 443;
- //SocketInitializer socket_init;
+ int sockfd = connect_to_host(host, port);
- AutoSeeded_RNG rng;
+ TLS_Client client(std::tr1::bind(socket_write, sockfd, _1, _2),
+ process_data,
+ session_manager,
+ policy,
+ rng,
+ host);
- printf("Connecting to %s:%d...\n", host.c_str(), port);
+ fd_set readfds;
- HTTPS_Client https(host, port, rng);
+ while(true)
+ {
+ FD_ZERO(&readfds);
+ FD_SET(sockfd, &readfds);
+ FD_SET(STDIN_FILENO, &readfds);
- std::string http_command = "GET / HTTP/1.0\r\n\r\n";
+ ::select(sockfd + 1, &readfds, NULL, NULL, NULL);
- printf("Sending request\n");
- https.write(http_command);
+ if(client.is_closed())
+ break;
- https.read_response();
+ if(FD_ISSET(sockfd, &readfds))
+ {
+ byte buf[1024] = { 0 };
+ ssize_t got = read(sockfd, buf, sizeof(buf));
+ if(got == 0)
+ {
+ printf("EOF on socket\n");
+ break;
+ }
+ else if(got == -1)
+ {
+ printf("Socket error %d (%s)\n", errno, strerror(errno));
+ continue;
+ }
+
+ //printf("socket read %d\n", got);
+
+ client.received_data(buf, got);
+ }
+ else if(FD_ISSET(STDIN_FILENO, &readfds))
+ {
+ byte buf[1024] = { 0 };
+ ssize_t got = read(STDIN_FILENO, buf, sizeof(buf));
+
+ if(got == 0)
+ {
+ printf("EOF on stdin\n");
+ client.close();
+ break;
+ }
+ else if(got == -1)
+ {
+ printf("Error reading stdin %d (%s)\n", errno, strerror(errno));
+ continue;
+ }
+
+ client.queue_for_sending(buf, got);
+ }
+ }
}
catch(std::exception& e)
{