http_socket.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #include "httpload.h"
  2. #include "http_digest.h"
  3. /************************************************************/
  4. #ifdef USE_GNUTLS
  5. #include <gcrypt.h>
  6. #include <gnutls/gnutls.h>
  7. #include <util/network/init.h>
  8. #include <util/network/socket.h>
  9. #include <util/system/mutex.h>
  10. /********************************************************/
  11. // HTTPS handler is used as implementation of
  12. // socketAbstractHandler for work through HTTPS protocol
  13. class socketSecureHandler: public socketRegularHandler {
  14. protected:
  15. bool IsValid_;
  16. gnutls_session Session_;
  17. gnutls_certificate_credentials Credits_;
  18. public:
  19. socketSecureHandler();
  20. virtual ~socketSecureHandler();
  21. virtual bool Good();
  22. virtual int Connect(const TAddrList& addrs, TDuration Timeout);
  23. virtual void Disconnect();
  24. virtual void shutdown();
  25. virtual bool send(const char* message, ssize_t messlen);
  26. virtual bool peek();
  27. virtual ssize_t read(void* buffer, ssize_t buflen);
  28. };
  29. /********************************************************/
  30. /********************************************************/
  31. static int gcry_pthread_mutex_init(void** priv) {
  32. int err = 0;
  33. try {
  34. TMutex* lock = new TMutex;
  35. *priv = lock;
  36. } catch (...) {
  37. err = -1;
  38. }
  39. return err;
  40. }
  41. static int gcry_pthread_mutex_destroy(void** lock) {
  42. delete static_cast<TMutex*>(*lock);
  43. return 0;
  44. }
  45. static int gcry_pthread_mutex_lock(void** lock) {
  46. static_cast<TMutex*>(*lock)->Acquire();
  47. return 0;
  48. }
  49. static int gcry_pthread_mutex_unlock(void** lock) {
  50. static_cast<TMutex*>(*lock)->Release();
  51. return 0;
  52. }
  53. static struct gcry_thread_cbs gcry_threads_pthread =
  54. {
  55. GCRY_THREAD_OPTION_PTHREAD, NULL,
  56. gcry_pthread_mutex_init, gcry_pthread_mutex_destroy,
  57. gcry_pthread_mutex_lock, gcry_pthread_mutex_unlock,
  58. NULL, NULL, NULL, NULL,
  59. NULL, NULL, NULL, NULL};
  60. /********************************************************/
  61. struct https_initor {
  62. https_initor() {
  63. gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
  64. gnutls_global_init();
  65. InitNetworkSubSystem();
  66. }
  67. ~https_initor() {
  68. gnutls_global_deinit();
  69. }
  70. };
  71. static https_initor _initor;
  72. /********************************************************/
  73. socketSecureHandler::socketSecureHandler()
  74. : socketRegularHandler()
  75. , IsValid_(false)
  76. , Session_()
  77. , Credits_()
  78. {
  79. }
  80. /********************************************************/
  81. socketSecureHandler::~socketSecureHandler() {
  82. if (IsValid_)
  83. Disconnect();
  84. }
  85. /********************************************************/
  86. bool socketSecureHandler::Good() {
  87. return Socket_.Good() && IsValid_;
  88. }
  89. /********************************************************/
  90. int socketSecureHandler::Connect(const TAddrList& addrs, TDuration Timeout) {
  91. IsValid_ = false;
  92. int ret = socketRegularHandler::Connect(addrs, Timeout);
  93. if (ret)
  94. return ret;
  95. gnutls_certificate_allocate_credentials(&Credits_);
  96. gnutls_init(&Session_, GNUTLS_CLIENT);
  97. gnutls_set_default_priority(Session_);
  98. gnutls_credentials_set(Session_, GNUTLS_CRD_CERTIFICATE, Credits_);
  99. SOCKET fd = Socket_;
  100. gnutls_transport_set_ptr(Session_, (gnutls_transport_ptr)fd);
  101. ret = gnutls_handshake(Session_);
  102. if (ret < 0) {
  103. fprintf(stderr, "*** Handshake failed\n");
  104. gnutls_perror(ret);
  105. gnutls_deinit(Session_);
  106. if (Credits_) {
  107. gnutls_certificate_free_credentials(Credits_);
  108. Credits_ = 0;
  109. }
  110. return 1;
  111. }
  112. IsValid_ = true;
  113. return !IsValid_;
  114. }
  115. /********************************************************/
  116. void socketSecureHandler::Disconnect() {
  117. if (IsValid_) {
  118. gnutls_bye(Session_, GNUTLS_SHUT_RDWR);
  119. IsValid_ = false;
  120. gnutls_deinit(Session_);
  121. }
  122. if (Credits_) {
  123. gnutls_certificate_free_credentials(Credits_);
  124. Credits_ = 0;
  125. }
  126. socketRegularHandler::Disconnect();
  127. }
  128. /********************************************************/
  129. void socketSecureHandler::shutdown() {
  130. }
  131. /********************************************************/
  132. bool socketSecureHandler::send(const char* message, ssize_t messlen) {
  133. if (!IsValid_)
  134. return false;
  135. ssize_t rv = gnutls_record_send(Session_, message, messlen);
  136. return rv >= 0;
  137. }
  138. /********************************************************/
  139. bool socketSecureHandler::peek() {
  140. //ssize_t rv = gnutls_record_check_pending(mSession);
  141. //return rv>0;
  142. return true;
  143. }
  144. /********************************************************/
  145. ssize_t socketSecureHandler::read(void* buffer, ssize_t buflen) {
  146. if (!IsValid_)
  147. return false;
  148. return gnutls_record_recv(Session_, (char*)buffer, buflen);
  149. }
  150. #endif
  151. /************************************************************/
  152. socketAbstractHandler* socketHandlerFactory::chooseHandler(const THttpURL& url) {
  153. if (url.IsValidGlobal() && url.GetScheme() == THttpURL::SchemeHTTP)
  154. return new socketRegularHandler;
  155. #ifdef USE_GNUTLS
  156. if (url.IsValidGlobal() && url.GetScheme() == THttpURL::SchemeHTTPS)
  157. return new socketSecureHandler;
  158. #endif
  159. return nullptr;
  160. }
  161. /************************************************************/
  162. socketHandlerFactory socketHandlerFactory::sInstance;
  163. /************************************************************/