Bredbandskollen CLI  1.2
Asynchronous network task engine
socketconnection.h
1 // Copyright (c) 2018 IIS (The Internet Foundation in Sweden)
2 // Written by Göran Andersson <initgoran@gmail.com>
3 
4 #pragma once
5 
6 #include <algorithm>
7 #include "socket.h"
8 
9 #ifdef USE_GNUTLS
10 #include <gnutls/gnutls.h>
11 #endif
12 
47 class SocketConnection : public Socket {
48  friend class Engine;
49 public:
54  SocketConnection(const std::string &label, Task *owner,
55  const std::string &hostname, uint16_t port,
56  uint16_t iptype = 0, struct addrinfo *local_addr=nullptr);
57 
58 #ifdef USE_GNUTLS
59  virtual ~SocketConnection() override {
60  if (tlsInitialized()) {
61  gnutls_deinit(session);
62  }
63  }
64 
66  void enableTLS() {
67  use_tls = true;
68  }
69 
71  bool is_tls() const {
72  return use_tls;
73  }
74 
76  gnutls_session_t cache_session() {
77  session_initialized = false;
78  return session;
79  }
80 
82  void insert_cached_session(gnutls_session_t &old_session) {
83  session_initialized = true;
84  use_tls = true;
85  session = old_session;
86  gnutls_transport_set_ptr(session,
87  static_cast<gnutls_transport_ptr_t>(this));
88  }
89 #endif
90 
99  virtual PollState connected() {
100  return PollState::CLOSE;
101  }
102 
104  virtual void connectionFailed(const std::string &err_msg) {
105  log() << "connection failed: " << err_msg;
106  }
107 
110  virtual void closedByPeer();
111 
121  virtual PollState readData(char *, size_t ) {
122  return PollState::CLOSE;
123  }
124 
131  virtual PollState unexpectedData(char *buf, size_t len);
132 
141  virtual PollState writeData() {
142  return PollState::CLOSE;
143  }
144 
157  size_t sendData(const char *buf, size_t len);
158 
159 #ifdef USE_WEBROOT
160  size_t sendFileData(int fd, size_t len);
161 #endif
162 
176  void asyncSendData(const char *buf, size_t len);
177 
191  void asyncSendData(const std::string data) {
192  asyncSendData(data.c_str(), data.size());
193  }
194 
198  size_t asyncBufferSize() const {
199  return to_send.size();
200  }
201 
203  static uint64_t totBytesSent() {
204  return tot_bytes_sent;
205  }
206 
208  static uint64_t totBytesReceived() {
209  return tot_bytes_received;
210  }
211 
215  static void resetByteCounter() {
216  tot_bytes_sent = 0;
217  tot_bytes_received = 0;
218  }
219 
221  const std::string &peerIp() const {
222  return peer_ip;
223  }
224 
226  uint16_t peerPort() const {
227  return peer_port;
228  }
229 
231  void dbgOn(bool b = true) {
232  debugging = b;
233  }
234 
236  bool dbgIsOn() {
237  return debugging;
238  }
239 protected:
240 
244  SocketConnection(const std::string &label, Task *owner, int fd,
245  const char *ip, uint16_t port);
246 
251  PollState tellOwner(const std::string &msg);
252 
253 private:
254  // Create a connection to the given host. Will be executed asynchronously,
255  // then one of the callbacks connected / connectionFailed will be called.
256  SocketConnection(Task *owner, const std::string &hostname,
257  unsigned int port);
258 
260 
261  // Will return false if connection fails immediately, e.g. if DNS
262  // lookup fails. Otherwise callback "connected" or "connectionFailed"
263  // will be called - perhaps even before this call returns:
264  bool asyncConnect();
265 
266  PollState doRead(int fd);
267 
268  // In states READ and READ_BLOCKED, this will be called to check if
269  // we the connection should be checked for writability too.
270  // If you override this, make sure to return true if asyncBufferSize() > 0.
271  bool wantToSend() override {
272  return !to_send.empty();
273  }
274 
275  PollState doWrite() {
276  if (to_send.empty())
277  return this->writeData();
278  if (size_t written = sendData(to_send.c_str(), to_send.size()))
279  to_send.erase(0, written);
280  return state();
281  }
282 
283  std::string to_send;
284  char socket_buffer[100000];
285 
286  std::string peer_ip;
287  struct addrinfo *local_ip;
288  uint16_t peer_port;
289  uint16_t prefer_ip_type;
290 
291 #ifdef USE_THREADS
292  thread_local
293 #endif
294  // Per thread byte counters.
295  static uint64_t tot_bytes_sent, tot_bytes_received;
296  bool debugging = false;
297 #ifdef USE_GNUTLS
298  bool use_tls = false;
299  bool session_initialized = false;
300  bool tls_send_pending = false;
301  void setSessionInitialized() {
302  session_initialized = true;
303  }
304  bool tlsInitialized() {
305  return session_initialized;
306  }
307  bool init_tls_server(gnutls_certificate_credentials_t &x509_cred,
308  gnutls_priority_t &priority_cache);
309  bool init_tls_client(gnutls_certificate_credentials_t &x509_cred,
310  bool verify_cert);
311  int try_tls_handshake() {
312  dbg_log() << "TLS handshake socket " << socket();
313  return gnutls_handshake(session);
314  }
315  static ssize_t tls_pull_static(gnutls_transport_ptr_t self,
316  void *buf, size_t len) {
317  return static_cast<SocketConnection *>(self)->tls_pull(buf, len);
318  }
319  static ssize_t tls_push_static(gnutls_transport_ptr_t self,
320  const void *buf, size_t len) {
321  return static_cast<SocketConnection *>(self)->tls_push(buf, len);
322  }
323  ssize_t tls_pull(void *buf, size_t len);
324  ssize_t tls_push(const void *buf, size_t len);
325  gnutls_session_t session;
326 #endif
327 };
The network engine.
Definition: engine.h:33
std::string label() const
Return the object's log label.
Definition: logger.h:251
std::ostream & log() const
Write a line of info log.
Definition: logger.h:328
std::ostream & dbg_log() const
Write a line of debug log.
Definition: logger.h:345
This class implements low-level socket connection operations. Inherit from it to implement protocols ...
Definition: socketconnection.h:47
gnutls_session_t cache_session()
Store SSL session in cache.
Definition: socketconnection.h:76
SocketConnection(const std::string &label, Task *owner, const std::string &hostname, uint16_t port, uint16_t iptype=0, struct addrinfo *local_addr=nullptr)
Definition: socketconnection.cpp:25
static uint64_t totBytesSent()
Number of bytes sent by current thread.
Definition: socketconnection.h:203
bool is_tls() const
Return true if the connection will be encrypted (SSL).
Definition: socketconnection.h:71
virtual void connectionFailed(const std::string &err_msg)
Will be called if the connection couldn't be established.
Definition: socketconnection.h:104
bool dbgIsOn()
Return true if socket debugging is enabled.
Definition: socketconnection.h:236
virtual void closedByPeer()
Definition: socketconnection.cpp:55
virtual PollState writeData()
Callback, called when socket is writable.
Definition: socketconnection.h:141
void asyncSendData(const char *buf, size_t len)
Send data to peer as soon as possible.
Definition: socketconnection.cpp:211
static uint64_t totBytesReceived()
Number of bytes recieved by current thread.
Definition: socketconnection.h:208
void dbgOn(bool b=true)
Enable debug output of data sent and received.
Definition: socketconnection.h:231
const std::string & peerIp() const
Return peer's IP address.
Definition: socketconnection.h:221
PollState tellOwner(const std::string &msg)
Definition: socketconnection.cpp:222
virtual PollState unexpectedData(char *buf, size_t len)
Peer has sent data when it wasn't supposed to.
Definition: socketconnection.cpp:134
size_t asyncBufferSize() const
Return number of bytes left to send after calling SocketConnection::asyncSendData.
Definition: socketconnection.h:198
void insert_cached_session(gnutls_session_t &old_session)
Reuse cached SSL session.
Definition: socketconnection.h:82
virtual PollState readData(char *, size_t)
Callback, called when data has arrived; len > 0.
Definition: socketconnection.h:121
virtual PollState connected()
Will be called when the connection is established.
Definition: socketconnection.h:99
size_t sendData(const char *buf, size_t len)
Try to send len bytes from the given buffer. Return the amount sent.
Definition: socketconnection.cpp:140
void asyncSendData(const std::string data)
Send data to peer as soon as possible.
Definition: socketconnection.h:191
void enableTLS()
Notify that the connection will be encrypted (SSL).
Definition: socketconnection.h:66
uint16_t peerPort() const
Return peer's port number.
Definition: socketconnection.h:226
static void resetByteCounter()
Reset counter for SocketConnection::totBytesSent and SocketConnection::totBytesReceived.
Definition: socketconnection.h:215
This is a slave to the Engine class. You can't use it directly, only through its subclasses,...
Definition: socket.h:18
Task * owner() const
Return task owning the socket.
Definition: socket.h:27
PollState state() const
Return current socket state.
Definition: socket.h:43
std::string hostname() const
Return name of the host to which the socket is supposed to connect.
Definition: socket.h:32
int socket() const
Return file descriptor.
Definition: socket.h:170
uint16_t port() const
Return port number to which the socket is supposed to connect.
Definition: socket.h:37
The purpose of a task is to manage socket connections, and/or to execute timers.
Definition: task.h:39
PollState
Definition: pollstate.h:11