Bond's TCP Library  1.0
Bond's TCP Client/Server Library
tcpclient.cpp
1 #include "tcpclient.h"
2 #include <sys/ioctl.h>
3 #include <openssl/ssl.h>
4 
5 namespace tcp {
6 
7 using namespace std;
8 
10 {
11  if (state_ == SocketState::CONNECTED) {
12  disconnect();
13  }
14 }
15 
16 bool Client::connect(const char *host, const char *service)
17 {
18  struct addrinfo hints;
19  struct addrinfo *result, *rp;
20  int errorcode;
21 
22  if ( socket() == -1) {
23  return false;
24  }
25  mtx.lock();
26  memset(&result,0,sizeof(struct addrinfo));
27  memset(&hints,0,sizeof(struct addrinfo));
28  hints.ai_family = domain();
29  hints.ai_socktype = SOCK_STREAM;
30  hints.ai_flags |= AI_CANONNAME;
31  errorcode = getaddrinfo(host,service,&hints,&result);
32  if (errorcode != 0) {
33  fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(errorcode));
34  mtx.unlock();
35  return false;
36  }
37 
38  if (ssl_) {
39  delete ssl_;
40  ssl_ = nullptr;
41  }
42 
43  if (!certfile.empty() && !keyfile.empty()) {
44  ssl_ = createSSL(ctx_);
45  ssl_->setOptions(verifyPeer);
46  if (verifyPeer && checkPeerSubjectName) {
47  ssl_->requiresCertPostValidation = true;
48  ssl_->setHostname(host);
49  }
50  if (!ssl_->setCertificateAndKey(certfile.c_str(),keyfile.c_str())) {
51  mtx.unlock();
52  return false;
53  }
54  if (!ssl_->setfd(socket())) {
55  mtx.unlock();
56  return false;
57  }
58  }
59 
60  log("Connecting to " + string(result->ai_canonname) + " on port " + string(service));
61 
62  for (rp = result; rp != nullptr; rp = rp->ai_next) {
63  if (::connect(socket(),rp->ai_addr,rp->ai_addrlen) == -1) {
64  if (errno == EINPROGRESS) {
65  state_ = SocketState::CONNECTING;
66  setEvents(EPOLLIN | EPOLLOUT | EPOLLRDHUP);
67  mtx.unlock();
68  return true;
69  } else {
70  setEvents(0);
71  error("connect",strerror(errno));
72  mtx.unlock();
73  return false;
74  }
75  } else {
76  connected();
77  mtx.unlock();
78  return true;
79  }
80  }
81  error("Could not find host " + string(host));
82  freeaddrinfo(result);
83  mtx.unlock();
84  return false;
85 }
86 
88  if (ssl_) {
89  mtx.lock();
90  ssl_->connect();
91  printSSLErrors();
92  readToInputBuffer();
93  mtx.unlock();
94  }
95 
96  state_ = SocketState::CONNECTED;
97  log("Connected");
98 }
99 
100 void Client::handleEvents(uint32_t events)
101 {
102  if (state_ == SocketState::CONNECTING) {
103  if (events & EPOLLERR) {
104  error("handleEvents",strerror(errno));
105  }
106  if (events & EPOLLRDHUP) {
107  state_ = SocketState::UNCONNECTED;
108  return;
109  }
110  if (events & EPOLLOUT) {
111  connected();
112  }
113  } else {
114  DataSocket::handleEvents(events);
115  }
116 }
117 
118 } // namespace mqttS
tcp::printSSLErrors
void printSSLErrors()
This method logs openSSL errors to cerr.
Definition: tcpssl.cpp:56
tcp::Client::handleEvents
void handleEvents(uint32_t events) override
Receive epoll events sent to this socket.
Definition: tcpclient.cpp:100
tcp::error
void error(string msg)
Send an error message to the log stream.
Definition: tcpsocket.cpp:18
tcp::Client::connected
virtual void connected()
Called when the client connects to the server.
Definition: tcpclient.cpp:87
tcp::Client::connect
virtual bool connect(const char *host, const char *service)
Initiates a connection to a server.
Definition: tcpclient.cpp:16
tcp::Client::~Client
virtual ~Client()
Destroys the client.
Definition: tcpclient.cpp:9
tcp::DataSocket::handleEvents
void handleEvents(uint32_t events) override
Called by the EPoll class when the listening socket recieves an epoll event.
Definition: tcpsocket.cpp:255
tcpclient.h
Provides basic tcp client functionality.
tcp::log
void log(string msg)
Send an log message to the log stream.
Definition: tcpsocket.cpp:22
tcp
A tcp client/server library for linux that supports openSSL and EPoll.
Definition: tcpclient.cpp:5