libhomegear-base  0.7
Base library for Homegear and Homegear family modules.
TcpSocket.h
Go to the documentation of this file.
1 /* Copyright 2013-2019 Homegear GmbH
2  *
3  * libhomegear-base is free software: you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public License as
5  * published by the Free Software Foundation, either version 3 of the
6  * License, or (at your option) any later version.
7  *
8  * libhomegear-base is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with libhomegear-base. If not, see
15  * <http://www.gnu.org/licenses/>.
16  *
17  * In addition, as a special exception, the copyright holders give
18  * permission to link the code of portions of this program with the
19  * OpenSSL library under certain conditions as described in each
20  * individual source file, and distribute linked combinations
21  * including the two.
22  * You must obey the GNU Lesser General Public License in all respects
23  * for all of the code used other than OpenSSL. If you modify
24  * file(s) with this exception, you may extend this exception to your
25  * version of the file(s), but you are not obligated to do so. If you
26  * do not wish to do so, delete this exception statement from your
27  * version. If you delete this exception statement from all source
28  * files in the program, then also delete it here.
29 */
30 
31 #ifndef TCPSOCKETOPERATIONS_H_
32 #define TCPSOCKETOPERATIONS_H_
33 
34 #include "SocketExceptions.h"
35 #include "../Managers/FileDescriptorManager.h"
36 #include "../IQueue.h"
37 #include "../Encoding/BinaryRpc.h"
38 
39 #include <thread>
40 #include <string>
41 #include <vector>
42 #include <list>
43 #include <iterator>
44 #include <mutex>
45 #include <memory>
46 #include <map>
47 #include <unordered_map>
48 #include <utility>
49 #include <cstring>
50 #include <atomic>
51 #include <functional>
52 
53 #include <fcntl.h>
54 #include <unistd.h>
55 #include <cstring>
56 #include <arpa/inet.h>
57 #include <netinet/tcp.h>
58 #include <netinet/in.h> //Needed for BSD
59 #include <netdb.h>
60 #include <sys/socket.h>
61 #include <sys/epoll.h>
62 #include <sys/un.h>
63 #include <errno.h>
64 #include <poll.h>
65 #include <signal.h>
66 
67 #include <gnutls/x509.h>
68 #include <gnutls/gnutls.h>
69 #include <queue>
70 
71 namespace BaseLib {
72 
73 namespace Security {
74 template<typename T>
75 class SecureVector;
76 }
77 
78 class SharedObjects;
79 
159 class TcpSocket : public IQueue {
160  public:
162  private:
163  gnutls_certificate_credentials_t _credentials = nullptr;
164  //"Note that only a pointer to the parameters are stored in the certificate handle, so you must not deallocate the parameters before the certificate is deallocated."
165  gnutls_dh_params_t _dhParams = nullptr;
166  public:
167  CertificateCredentials(gnutls_certificate_credentials_t credentials, gnutls_datum_t dhParams);
169  gnutls_certificate_credentials_t get();
170  };
171 
172  typedef std::vector<uint8_t> TcpPacket;
173 
174  struct TcpClientData {
175  int32_t thread_index = -1;
176  int32_t id = 0;
178  std::vector<uint8_t> buffer;
179  std::shared_ptr<TcpSocket> socket;
180  std::unordered_map<std::string, std::shared_ptr<CertificateCredentials>> certificateCredentials;
181  std::string clientCertDn;
182  std::string clientCertSerial;
183  int64_t clientCertExpiration = -1;
187  std::mutex backlogMutex;
188  bool busy = false;
189  std::queue<std::shared_ptr<TcpPacket>> backlog;
190 
192  buffer.resize(4096);
193  }
194  };
195  typedef std::shared_ptr<TcpClientData> PTcpClientData;
196 
198  public:
199  QueueEntry() = default;
200 
201  explicit QueueEntry(const PTcpClientData &clientData) {
202  this->clientData = clientData;
203  }
204 
205  ~QueueEntry() override = default;
206 
207  PTcpClientData clientData;
208  };
209 
211  std::string certFile;
212  std::string certData;
213  std::string keyFile;
214  std::shared_ptr<Security::SecureVector<uint8_t>> keyData;
215  std::string caFile; //For client certificate verification
216  std::string caData; //For client certificate verification
217  };
218  typedef std::shared_ptr<CertificateInfo> PCertificateInfo;
219 
220  struct TcpServerInfo {
221  bool useSsl = false;
222  uint32_t connectionBacklogSize = 100;
223  uint32_t maxConnections = 10;
224  uint32_t serverThreads = 1;
225  std::unordered_map<std::string, PCertificateInfo> certificates;
226  std::string dhParamFile;
227  std::string dhParamData;
228  bool requireClientCert = false;
229  std::function<void(int32_t clientId, std::string address, uint16_t port)> newConnectionCallback;
230  std::function<void(int32_t clientId)> connectionClosedCallback;
231  std::function<void(int32_t clientId, int32_t errorCode, const std::string &errorString)> connectionClosedCallbackEx;
232  std::function<void(int32_t clientId, TcpPacket &packet)> packetReceivedCallback;
233  };
234 
235  // {{{ TCP server or client
241  explicit TcpSocket(BaseLib::SharedObjects *baseLib);
242 
249  TcpSocket(BaseLib::SharedObjects *baseLib, std::shared_ptr<FileDescriptor> socketDescriptor);
250  // }}}
251 
252  // {{{ TCP client
260  TcpSocket(BaseLib::SharedObjects *baseLib, std::string hostname, std::string port);
261 
272  TcpSocket(BaseLib::SharedObjects *baseLib, std::string hostname, std::string port, bool useSsl, std::string caFile, bool verifyCertificate);
273 
284  TcpSocket(BaseLib::SharedObjects *baseLib, std::string hostname, std::string port, bool useSsl, bool verifyCertificate, std::string caData);
285 
298  TcpSocket(BaseLib::SharedObjects *baseLib, std::string hostname, std::string port, bool useSsl, std::string caFile, bool verifyCertificate, std::string clientCertFile, std::string clientKeyFile);
299 
312  TcpSocket(BaseLib::SharedObjects *baseLib, std::string hostname, std::string port, bool useSsl, bool verifyCertificate, std::string caData, std::string clientCertData, const std::shared_ptr<Security::SecureVector<uint8_t>> &clientKeyData);
313 
330  std::string hostname,
331  std::string port,
332  bool useSsl,
333  bool verifyCertificate,
334  std::string caFile,
335  std::string caData,
336  std::string clientCertFile,
337  std::string clientCertData,
338  std::string clientKeyFile,
339  const std::shared_ptr<Security::SecureVector<uint8_t>> &);
340  // }}}
341 
342  // {{{ TCP server
346  TcpSocket(BaseLib::SharedObjects *baseLib, TcpServerInfo &serverInfo);
347  // }}}
348 
349  virtual ~TcpSocket();
350 
351  static PFileDescriptor bindAndReturnSocket(FileDescriptorManager &fileDescriptorManager, const std::string &address, const std::string &port, uint32_t connectionBacklogSize, std::string &listenAddress, int32_t &listenPort);
352 
353  PFileDescriptor getFileDescriptor();
354  std::string getIpAddress();
355  int32_t getPort() { return _boundListenPort; }
356  bool getRequireClientCert() { return _requireClientCert; }
357  void setConnectionRetries(int32_t retries) { _connectionRetries = retries; }
358  void setReadTimeout(int64_t timeout) { _readTimeout = timeout; }
359  void setWriteTimeout(int64_t timeout) { _writeTimeout = timeout; }
360  void setAutoConnect(bool autoConnect) { _autoConnect = autoConnect; }
361  void setHostname(std::string hostname) {
362  close();
363  _hostname = hostname;
364  }
365  void setPort(std::string port) {
366  close();
367  _port = port;
368  }
369  void setUseSSL(bool useSsl) {
370  if (!_isServer) {
371  close();
372  _useSsl = useSsl;
373  if (_useSsl) initSsl();
374  }
375  }
376  void setCertificates(std::unordered_map<std::string, PCertificateInfo> &certificates);
377  void reloadCertificates();
378  void setVerifyCertificate(bool verifyCertificate) {
379  close();
380  _verifyCertificate = verifyCertificate;
381  }
382  void setVerifyHostname(bool verifyHostname) {
383  close();
384  _verifyHostname = verifyHostname;
385  }
386 
391  void setVerificationHostname(const std::string &hostname) {
392  close();
393  _verificationHostname = hostname;
394  }
395  std::unordered_map<std::string, std::shared_ptr<CertificateCredentials>> getCredentials() { return _certificateCredentials; }
396 
406  bool connected();
407 
408  double GetPacketsPerMinuteReceived();
409  double GetPacketsPerMinuteSent();
410 
416  double GetServerThreadLoad();
417 
423  double GetProcessingThreadLoad();
424 
430  double GetProcessingThreadLoadMax();
431 
442  int32_t proofread(char *buffer, int32_t bufferSize);
443 
456  int32_t proofread(char *buffer, int32_t bufferSize, bool &moreData, bool skip_poll = false);
457 
467  int32_t proofwrite(const std::shared_ptr<std::vector<char>> &data);
468 
478  int32_t proofwrite(const std::vector<char> &data);
479 
489  int32_t proofwrite(const std::string &data);
490 
500  int32_t proofwrite(const char *buffer, int32_t bytesToWrite);
501 
502  void open();
503  void close();
504 
505  // {{{ Servers only
517  void bindServerSocket(std::string address, std::string port, std::string &listenAddress);
518 
529  void startPreboundServer(std::string &listenAddress, size_t processingThreads = 0);
530 
539  void startServer(std::string address, std::string port, std::string &listenAddress, size_t processingThreads = 0);
540 
549  void startServer(std::string address, std::string &listenAddress, int32_t &listenPort, size_t processingThreads = 0);
550 
554  void stopServer();
555 
559  void waitForServerStopped();
560 
568  bool sendToClient(int32_t clientId, const TcpPacket &packet, bool closeConnection = false);
569 
577  bool sendToClient(int32_t clientId, const std::vector<char> &packet, bool closeConnection = false);
578 
584  void closeClientConnection(int32_t clientId);
585 
590  int32_t clientCount();
591 
596  uint32_t processingQueueSize();
597 
605  std::string getClientCertDn(int32_t clientId);
606 
607  std::string getClientCertSerial(int32_t clientId);
608 
609  int64_t getClientCertExpiration(int32_t clientId);
610  // }}}
611  protected:
613  AverageMeanData() = default;
615  std::atomic<int64_t> last_measurement{0};
616  std::atomic<double> last_output{0.0};
617  };
618 
619  BaseLib::SharedObjects *_bl = nullptr;
620  int32_t _connectionRetries = 3;
621  int64_t _readTimeout = 15000000;
622  int64_t _writeTimeout = 15000000;
623  std::atomic_bool _connecting;
624  bool _autoConnect = true;
625  std::string _ipAddress;
626  std::string _hostname;
628  std::string _port;
629  std::mutex _readMutex;
630  std::mutex _writeMutex;
631  std::unordered_map<std::string, PCertificateInfo> _certificates;
632  bool _verifyCertificate = true;
633  bool _verifyHostname = true;
634 
635  // {{{ For server only
636  bool _isServer = false;
637  uint32_t _backlogSize = 100;
638  uint32_t _maxConnections = 10;
639  std::string _dhParamFile;
640  std::string _dhParamData;
641  bool _requireClientCert = false;
642  std::atomic<uint32_t> server_threads_in_use_{0};
643  std::vector<AverageMeanData> average_packets_per_minute_received_;
644  std::vector<AverageMeanData> average_packets_per_minute_sent_;
645  std::function<void(int32_t clientId, std::string address, uint16_t port)> _newConnectionCallback;
646  std::function<void(int32_t clientId)> _connectionClosedCallback;
647  std::function<void(int32_t clientId, int32_t errorCode, const std::string &errorString)> _connectionClosedCallbackEx;
648  std::function<void(int32_t clientId, TcpPacket &packet)> _packetReceivedCallback;
649 
650  std::string _listenAddress;
651  std::string _listenPort;
652  int32_t _boundListenPort = -1;
653 
654  gnutls_priority_t _tlsPriorityCache = nullptr;
655 
656  std::atomic_bool _stopServer;
657  std::vector<std::thread> server_threads_;
658 
659  int64_t _lastGarbageCollection = 0;
660 
661  std::mutex _clientsMutex;
662  std::map<int32_t, PTcpClientData> _clients;
663  // }}}
664 
667  bool _useSsl = false;
672  std::shared_ptr<CertificateCredentials> _currentClientCertificateCredentials;
676  std::unordered_map<std::string, std::shared_ptr<CertificateCredentials>> _certificateCredentials;
677 
678  void getSocketDescriptor();
679  void getConnection();
680  void getSsl();
681  void initSsl();
682  void initTlsPriorityCache();
683  void autoConnect();
684 
685  // {{{ For server only
686  void bindSocket();
687 
688  void serverThread(uint32_t thread_index);
689  void processQueueEntry(int32_t index, std::shared_ptr<BaseLib::IQueueEntry> &entry) override;
690  void collectGarbage();
691  void collectGarbage(std::unordered_map<int32_t, PTcpClientData> &clients);
692  void initClientSsl(PTcpClientData &clientData);
693  void readClient(const PTcpClientData &client_data, std::unordered_map<int32_t, PTcpClientData> &backlog_clients);
694  // }}}
695 };
696 
697 typedef std::shared_ptr<BaseLib::TcpSocket> PTcpSocket;
698 
699 }
700 #endif
std::mutex _readMutex
Definition: TcpSocket.h:629
PFileDescriptor _socketDescriptor
Definition: TcpSocket.h:666
Definition: TcpSocket.h:210
void setPort(std::string port)
Definition: TcpSocket.h:365
Definition: TcpSocket.h:612
std::queue< std::shared_ptr< TcpPacket > > backlog
Definition: TcpSocket.h:189
void setVerifyCertificate(bool verifyCertificate)
Definition: TcpSocket.h:378
std::function< void(int32_t clientId, TcpPacket &packet)> packetReceivedCallback
Definition: TcpSocket.h:232
std::function< void(int32_t clientId, int32_t errorCode, const std::string &errorString)> _connectionClosedCallbackEx
Definition: TcpSocket.h:647
std::string _listenPort
Definition: TcpSocket.h:651
Definition: FileDescriptorManager.h:54
This is the base library main class.
Definition: BaseLib.h:95
void setReadTimeout(int64_t timeout)
Definition: TcpSocket.h:358
Definition: IQueue.h:41
std::unordered_map< std::string, std::shared_ptr< CertificateCredentials > > _certificateCredentials
Stores the certificate credentials so that they can be replaced at any time.
Definition: TcpSocket.h:676
AverageMeanData(const AverageMeanData &data)
Definition: TcpSocket.h:614
The class only makes sure that the vector is not copyable and the data is zeroed on destruction...
Definition: Io.h:40
std::string caFile
Definition: TcpSocket.h:215
std::function< void(int32_t clientId, int32_t errorCode, const std::string &errorString)> connectionClosedCallbackEx
Definition: TcpSocket.h:231
int32_t getPort()
Definition: TcpSocket.h:355
Definition: BaseLib.cpp:34
std::mutex _socketDescriptorMutex
Definition: TcpSocket.h:665
std::string _listenAddress
Definition: TcpSocket.h:650
void setConnectionRetries(int32_t retries)
Definition: TcpSocket.h:357
std::unordered_map< std::string, std::shared_ptr< CertificateCredentials > > certificateCredentials
Definition: TcpSocket.h:180
std::unordered_map< std::string, PCertificateInfo > _certificates
Definition: TcpSocket.h:631
Class to easily create a TCP server or client.
Definition: TcpSocket.h:159
Definition: TcpSocket.h:174
void setAutoConnect(bool autoConnect)
Definition: TcpSocket.h:360
std::string dhParamFile
Definition: TcpSocket.h:226
std::string certFile
Definition: TcpSocket.h:211
std::string _port
Definition: TcpSocket.h:628
std::vector< AverageMeanData > average_packets_per_minute_sent_
Definition: TcpSocket.h:644
std::string _dhParamFile
Definition: TcpSocket.h:639
std::shared_ptr< CertificateCredentials > _currentClientCertificateCredentials
Contains a copy of the current credentials in case the credentials are replaced while the connection ...
Definition: TcpSocket.h:672
void setUseSSL(bool useSsl)
Definition: TcpSocket.h:369
std::string dhParamData
Definition: TcpSocket.h:227
std::unordered_map< std::string, std::shared_ptr< CertificateCredentials > > getCredentials()
Definition: TcpSocket.h:395
std::string clientCertSerial
Definition: TcpSocket.h:182
std::shared_ptr< CertificateInfo > PCertificateInfo
Definition: TcpSocket.h:218
std::function< void(int32_t clientId, TcpPacket &packet)> _packetReceivedCallback
Definition: TcpSocket.h:648
std::mutex backlogMutex
Mutex for busy and backlog
Definition: TcpSocket.h:187
std::function< void(int32_t clientId, std::string address, uint16_t port)> newConnectionCallback
Definition: TcpSocket.h:229
std::string _hostname
Definition: TcpSocket.h:626
void setHostname(std::string hostname)
Definition: TcpSocket.h:361
std::vector< uint8_t > TcpPacket
Definition: TcpSocket.h:172
void setVerificationHostname(const std::string &hostname)
Only relevant for TLS connections.
Definition: TcpSocket.h:391
std::vector< std::thread > server_threads_
Definition: TcpSocket.h:657
std::string _dhParamData
Definition: TcpSocket.h:640
Definition: TcpSocket.h:220
bool getRequireClientCert()
Definition: TcpSocket.h:356
This class implements a queue after the producer-consumer paradigm.
Definition: IQueue.h:52
std::mutex _certificateCredentialsMutex
Definition: TcpSocket.h:668
std::vector< uint8_t > buffer
Definition: TcpSocket.h:178
void setWriteTimeout(int64_t timeout)
Definition: TcpSocket.h:359
std::vector< AverageMeanData > average_packets_per_minute_received_
Definition: TcpSocket.h:643
std::string caData
Definition: TcpSocket.h:216
std::string _ipAddress
Definition: TcpSocket.h:625
std::shared_ptr< TcpSocket > socket
Definition: TcpSocket.h:179
void setVerifyHostname(bool verifyHostname)
Definition: TcpSocket.h:382
std::string keyFile
Definition: TcpSocket.h:213
std::shared_ptr< FileDescriptor > PFileDescriptor
Definition: FileDescriptorManager.h:52
std::string clientCertDn
Definition: TcpSocket.h:181
std::function< void(int32_t clientId)> _connectionClosedCallback
Definition: TcpSocket.h:646
PTcpClientData clientData
Definition: TcpSocket.h:207
std::string _verificationHostname
Definition: TcpSocket.h:627
PFileDescriptor fileDescriptor
Definition: TcpSocket.h:177
std::atomic_bool _connecting
Definition: TcpSocket.h:623
TcpClientData()
Definition: TcpSocket.h:191
std::map< int32_t, PTcpClientData > _clients
Definition: TcpSocket.h:662
std::string certData
Definition: TcpSocket.h:212
QueueEntry(const PTcpClientData &clientData)
Definition: TcpSocket.h:201
std::function< void(int32_t clientId, std::string address, uint16_t port)> _newConnectionCallback
Definition: TcpSocket.h:645
std::atomic_bool _stopServer
Definition: TcpSocket.h:656
std::shared_ptr< TcpClientData > PTcpClientData
Definition: TcpSocket.h:195
std::mutex _writeMutex
Definition: TcpSocket.h:630
std::function< void(int32_t clientId)> connectionClosedCallback
Definition: TcpSocket.h:230
std::mutex _clientsMutex
Definition: TcpSocket.h:661
std::unordered_map< std::string, PCertificateInfo > certificates
Definition: TcpSocket.h:225
std::shared_ptr< BaseLib::TcpSocket > PTcpSocket
Definition: TcpSocket.h:697
Definition: TcpSocket.h:197
std::shared_ptr< Security::SecureVector< uint8_t > > keyData
Definition: TcpSocket.h:214