Async 1.9.1
AsyncTcpConnection.h
Go to the documentation of this file.
1
29
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)
239 {
242 }
243
250 virtual int write(const void *buf, int count);
251
256 IpAddress localHost(void) const;
257
262 uint16_t localPort(void) const;
263
270 const IpAddress& remoteHost(void) const { return remote_addr; }
271
276 uint16_t remotePort(void) const { return remote_port; }
277
283 bool isConnected(void) const { return sock != -1; }
284
291 bool isIdle(void) const { return sock == -1; }
292
297 void enableSsl(bool enable);
298
309
313
318 long sslVerifyResult(void) const;
319
328 void setSslContext(SslContext& ctx, bool is_server);
329
330 SslContext* sslContext(void) { return m_ssl_ctx; }
331
332 bool isServer(void) const { return m_ssl_is_server; }
333
340 void freeze(void);
341
349 void unfreeze(void);
350
355 //std::string sslCommonName(void) const;
356
363
378 sigc::signal<int(TcpConnection*, void*, int)> dataReceived;
379
394 X509_STORE_CTX*)>::accumulated<if_all_true_acc> verifyPeer;
395
403 sigc::signal<void(TcpConnection*)> sslConnectionReady;
404
405 protected:
412 void setSocket(int sock);
413
420 void setRemoteAddr(const IpAddress& remote_addr);
421
428 void setRemotePort(uint16_t remote_port);
429
437 int socket(void) const { return sock; }
438
445 virtual void closeConnection(void);
446
454 virtual void onDisconnected(DisconnectReason reason)
455 {
456 if (reason != DR_ORDERED_DISCONNECT)
457 {
458 emitDisconnected(reason);
459 }
460 }
461
476 virtual int onDataReceived(void *buf, int count)
477 {
478 return dataReceived(this, buf, count);
479 }
480
486 {
487 disconnected(this, reason);
488 }
489
496 virtual int emitVerifyPeer(int preverify_ok, X509_STORE_CTX* store_ctx)
497 {
498 if (verifyPeer.empty())
499 {
500 return preverify_ok;
501 }
502 return verifyPeer(this, preverify_ok, store_ctx);
503 }
504
505 private:
506 friend class TcpClientBase;
507
508 enum SslStatus { SSLSTATUS_OK, SSLSTATUS_WANT_IO, SSLSTATUS_FAIL };
509 struct Char
510 {
511 char value;
512 Char(void) noexcept
513 {
514 // Do nothing to suppress automatic initialization on container resize
515 // for m_recv_buf.
516 static_assert(sizeof *this == sizeof value, "invalid size");
517 static_assert(__alignof *this == __alignof value, "invalid alignment");
518 }
519 };
520
521 static constexpr const size_t DEFAULT_BUF_SIZE = 1024;
522
523 static std::map<SSL*, TcpConnection*> ssl_con_map;
524
525 IpAddress remote_addr;
526 uint16_t remote_port = 0;
527 int sock = -1;
528 FdWatch rd_watch;
529 std::vector<Char> m_recv_buf;
530 Async::FdWatch m_wr_watch;
531 std::vector<char> m_write_buf;
532
533 SslContext* m_ssl_ctx = nullptr;
534 bool m_ssl_is_server = false;
535 SSL* m_ssl = nullptr;
536 BIO* m_ssl_rd_bio = nullptr; // SSL reads, we write
537 BIO* m_ssl_wr_bio = nullptr; // SSL writes, we read
538 std::vector<char> m_ssl_encrypt_buf;
539
540 bool m_freezed = false;
541
542 static TcpConnection* lookupConnection(SSL* ssl)
543 {
544 auto it = ssl_con_map.find(ssl);
545 return (it != ssl_con_map.end()) ? it->second : nullptr;
546 }
547 static int sslVerifyCallback(int preverify_ok,
548 X509_STORE_CTX* x509_store_ctx);
549
550 void recvHandler(FdWatch *watch);
551 void processRecvBuf(void);
552 void addToWriteBuf(const char *buf, size_t len);
553 void onWriteSpaceAvailable(Async::FdWatch* w);
554 int rawWrite(const void* buf, int count);
555
556 SslStatus sslGetStatus(int n);
557 int sslRecvHandler(char* src, int count);
558 SslStatus sslDoHandshake(void);
559 int sslEncrypt(void);
560 int sslWrite(const void* buf, int count);
561
562}; /* class TcpConnection */
563
564
565} /* namespace */
566
567#endif /* ASYNC_TCP_CONNECTION_INCLUDED */
568
569
570
571/*
572 * This file has not been truncated
573 */
574
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 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.
sigc::signal< void(TcpConnection *)> sslConnectionReady
A signal that is emitted when the SSL connection is ready.
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.
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.
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
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.
sigc::signal< void(TcpConnection *, DisconnectReason)> disconnected
Get common name for the SSL connection.
uint16_t localPort(void) const
Get the local TCP port associated with this connection.
sigc::signal< int(TcpConnection *, void *, int)> dataReceived
A signal that is emitted when data has been received on the 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.
SslContext * sslContext(void)
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.
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)