Async 1.8.0
AsyncTcpConnection.h
Go to the documentation of this file.
1
30#ifndef ASYNC_TCP_CONNECTION_INCLUDED
31#define ASYNC_TCP_CONNECTION_INCLUDED
32
33
34/****************************************************************************
35 *
36 * System Includes
37 *
38 ****************************************************************************/
39
40#include <sigc++/sigc++.h>
41#include <stdint.h>
42#include <openssl/bio.h>
43#include <openssl/err.h>
44#include <openssl/pem.h>
45#include <openssl/ssl.h>
46
47#include <string>
48#include <cassert>
49#include <cstring>
50#include <vector>
51#include <map>
52
53
54/****************************************************************************
55 *
56 * Project Includes
57 *
58 ****************************************************************************/
59
60#include <AsyncIpAddress.h>
61#include <AsyncFdWatch.h>
62#include <AsyncSslContext.h>
63#include <AsyncSslX509.h>
64
65
66/****************************************************************************
67 *
68 * Local Includes
69 *
70 ****************************************************************************/
71
72
73
74/****************************************************************************
75 *
76 * Forward declarations
77 *
78 ****************************************************************************/
79
80
81
82/****************************************************************************
83 *
84 * Namespace
85 *
86 ****************************************************************************/
87
88namespace Async
89{
90
91/****************************************************************************
92 *
93 * Forward declarations of classes inside of the declared namespace
94 *
95 ****************************************************************************/
96
97class IpAddress;
98
99
100/****************************************************************************
101 *
102 * Defines & typedefs
103 *
104 ****************************************************************************/
105
106
107
108/****************************************************************************
109 *
110 * Exported Global Variables
111 *
112 ****************************************************************************/
113
114
115
116/****************************************************************************
117 *
118 * Class definitions
119 *
120 ****************************************************************************/
121
138class TcpConnection : virtual public sigc::trackable
139{
140 public:
154
162 {
163 typedef int result_type;
164 template <class I>
165 result_type operator()(I first, I last)
166 {
167 for (; first != last; first ++)
168 {
169 if (!*first) return 0;
170 }
171 return 1;
172 }
173 };
174
178 static const int DEFAULT_RECV_BUF_LEN = 1024;
179
183 static const char *disconnectReasonStr(DisconnectReason reason);
184
189 explicit TcpConnection(size_t recv_buf_len = DEFAULT_RECV_BUF_LEN);
190
198 TcpConnection(int sock, const IpAddress& remote_addr,
199 uint16_t remote_port,
200 size_t recv_buf_len = DEFAULT_RECV_BUF_LEN);
201
205 virtual ~TcpConnection(void);
206
217
227 void setRecvBufLen(size_t recv_buf_len);
228
229 size_t recvBufLen(void) const { return m_recv_buf.capacity(); }
230
238 virtual void disconnect(void) { closeConnection(); }
239
246 virtual int write(const void *buf, int count);
247
252 IpAddress localHost(void) const;
253
258 uint16_t localPort(void) const;
259
266 const IpAddress& remoteHost(void) const { return remote_addr; }
267
272 uint16_t remotePort(void) const { return remote_port; }
273
279 bool isConnected(void) const { return sock != -1; }
280
287 bool isIdle(void) const { return sock == -1; }
288
293 void enableSsl(bool enable);
294
305
309
314 long sslVerifyResult(void) const;
315
324 void setSslContext(SslContext& ctx, bool is_server);
325
326 SslContext* sslContext(void) { return m_ssl_ctx; }
327
328 bool isServer(void) const { return m_ssl_is_server; }
329
336 void freeze(void);
337
345 void unfreeze(void);
346
351 //std::string sslCommonName(void) const;
352
358 sigc::signal<void, TcpConnection *, DisconnectReason> disconnected;
359
374 sigc::signal<int, TcpConnection *, void *, int> dataReceived;
375
390 X509_STORE_CTX*>::accumulated<if_all_true_acc> verifyPeer;
391
399 sigc::signal<void, TcpConnection*> sslConnectionReady;
400
401 protected:
408 void setSocket(int sock);
409
416 void setRemoteAddr(const IpAddress& remote_addr);
417
424 void setRemotePort(uint16_t remote_port);
425
433 int socket(void) const { return sock; }
434
441 virtual void closeConnection(void);
442
450 virtual void onDisconnected(DisconnectReason reason)
451 {
452 emitDisconnected(reason);
453 }
454
469 virtual int onDataReceived(void *buf, int count)
470 {
471 return dataReceived(this, buf, count);
472 }
473
479 {
480 disconnected(this, reason);
481 }
482
489 virtual int emitVerifyPeer(int preverify_ok, X509_STORE_CTX* store_ctx)
490 {
491 if (verifyPeer.empty())
492 {
493 return preverify_ok;
494 }
495 return verifyPeer(this, preverify_ok, store_ctx);
496 }
497
498 private:
499 friend class TcpClientBase;
500
501 enum SslStatus { SSLSTATUS_OK, SSLSTATUS_WANT_IO, SSLSTATUS_FAIL };
502 struct Char
503 {
504 char value;
505 Char(void) noexcept
506 {
507 // Do nothing to suppress automatic initialization on container resize
508 // for m_recv_buf.
509 static_assert(sizeof *this == sizeof value, "invalid size");
510 static_assert(__alignof *this == __alignof value, "invalid alignment");
511 }
512 };
513
514 static constexpr const size_t DEFAULT_BUF_SIZE = 1024;
515
516 static std::map<SSL*, TcpConnection*> ssl_con_map;
517
518 IpAddress remote_addr;
519 uint16_t remote_port = 0;
520 int sock = -1;
521 FdWatch rd_watch;
522 std::vector<Char> m_recv_buf;
523 Async::FdWatch m_wr_watch;
524 std::vector<char> m_write_buf;
525
526 SslContext* m_ssl_ctx = nullptr;
527 bool m_ssl_is_server = false;
528 SSL* m_ssl = nullptr;
529 BIO* m_ssl_rd_bio = nullptr; // SSL reads, we write
530 BIO* m_ssl_wr_bio = nullptr; // SSL writes, we read
531 std::vector<char> m_ssl_encrypt_buf;
532
533 bool m_freezed = false;
534
535 static TcpConnection* lookupConnection(SSL* ssl)
536 {
537 auto it = ssl_con_map.find(ssl);
538 return (it != ssl_con_map.end()) ? it->second : nullptr;
539 }
540 static int sslVerifyCallback(int preverify_ok,
541 X509_STORE_CTX* x509_store_ctx);
542
543 void recvHandler(FdWatch *watch);
544 void processRecvBuf(void);
545 void addToWriteBuf(const char *buf, size_t len);
546 void onWriteSpaceAvailable(Async::FdWatch* w);
547 int rawWrite(const void* buf, int count);
548
549 SslStatus sslGetStatus(int n);
550 int sslRecvHandler(char* src, int count);
551 SslStatus sslDoHandshake(void);
552 int sslEncrypt(void);
553 int sslWrite(const void* buf, int count);
554
555}; /* class TcpConnection */
556
557
558} /* namespace */
559
560#endif /* ASYNC_TCP_CONNECTION_INCLUDED */
561
562
563
564/*
565 * This file has not been truncated
566 */
567
Contains a watch for file descriptors.
Platform independent representation of an IP address.
SSL context meant to be used with TcpConnection and friends.
Implements a representation of a X.509 certificate.
A class for watching file descriptors.
A class for representing an IP address in an OS independent way.
SSL context meant to be used with TcpConnection and friends.
A class representing an X.509 certificate.
A base class for creating a TCP client connection.
A class for handling exiting TCP connections.
static const char * disconnectReasonStr(DisconnectReason reason)
Translate disconnect reason to a string.
virtual void disconnect(void)
Disconnect from the remote host.
bool isIdle(void) const
Check if the connection is idle.
const IpAddress & remoteHost(void) const
Return the IP-address of the remote host.
Async::SslX509 sslCertificate(void) const
uint16_t remotePort(void) const
Return the remote port used.
static const int DEFAULT_RECV_BUF_LEN
The default size of the reception buffer.
DisconnectReason
Reason code for disconnects.
@ DR_HOST_NOT_FOUND
The specified host was not found in the DNS.
@ DR_SYSTEM_ERROR
A system error occured (check errno)
@ DR_BAD_STATE
The connection ended up in a bad state.
@ DR_PROTOCOL_ERROR
Protocol error.
@ DR_REMOTE_DISCONNECTED
The remote host disconnected.
@ DR_ORDERED_DISCONNECT
Disconnect ordered locally.
@ DR_SWITCH_PEER
A better peer was found so reconnecting.
virtual ~TcpConnection(void)
Destructor.
virtual void onDisconnected(DisconnectReason reason)
Called when a connection has been terminated.
void setSocket(int sock)
Setup information about the connection.
virtual int emitVerifyPeer(int preverify_ok, X509_STORE_CTX *store_ctx)
Emit the verifyPeer signal.
void setSslContext(SslContext &ctx, bool is_server)
Set the OpenSSL context to use when setting up the connection.
SslX509 sslPeerCertificate(void)
Get the peer certificate associated with this connection.
virtual TcpConnection & operator=(TcpConnection &&other)
Move assignmnt operator.
int socket(void) const
Return the socket file descriptor.
size_t recvBufLen(void) const
virtual int onDataReceived(void *buf, int count)
Called when data has been received on the connection.
bool isServer(void) const
sigc::signal< int, TcpConnection *, void *, int > dataReceived
A signal that is emitted when data has been received on the connection.
void setRecvBufLen(size_t recv_buf_len)
Set a new receive buffer size.
TcpConnection(int sock, const IpAddress &remote_addr, uint16_t remote_port, size_t recv_buf_len=DEFAULT_RECV_BUF_LEN)
Constructor.
void unfreeze(void)
Reenable all communication.
uint16_t localPort(void) const
Get the local TCP port associated with this connection.
void setRemotePort(uint16_t remote_port)
Setup information about the connection.
virtual void emitDisconnected(DisconnectReason reason)
Emit the disconnected signal.
void freeze(void)
Stop all communication.
void enableSsl(bool enable)
Enable or disable TLS for this connection.
long sslVerifyResult(void) const
Get the result of the certificate verification process.
virtual int write(const void *buf, int count)
Write data to the TCP connection.
sigc::signal< if_all_true_acc::result_type, TcpConnection *, int, X509_STORE_CTX * >::accumulated< if_all_true_acc > verifyPeer
A signal that is emitted on SSL/TLS certificate verification.
SslContext * sslContext(void)
sigc::signal< void, TcpConnection * > sslConnectionReady
A signal that is emitted when the SSL connection is ready.
bool isConnected(void) const
Check if the connection is established or not.
IpAddress localHost(void) const
Get the local IP address associated with this connection.
TcpConnection(size_t recv_buf_len=DEFAULT_RECV_BUF_LEN)
Constructor.
sigc::signal< void, TcpConnection *, DisconnectReason > disconnected
Get common name for the SSL connection.
void setRemoteAddr(const IpAddress &remote_addr)
Setup information about the connection.
virtual void closeConnection(void)
Disconnect from the remote peer.
Namespace for the asynchronous programming classes.
A sigc return value accumulator for signals returning bool.
result_type operator()(I first, I last)