diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/http/fetch/http_socket.cpp | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/http/fetch/http_socket.cpp')
-rw-r--r-- | library/cpp/http/fetch/http_socket.cpp | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/library/cpp/http/fetch/http_socket.cpp b/library/cpp/http/fetch/http_socket.cpp new file mode 100644 index 0000000000..1524ef04a8 --- /dev/null +++ b/library/cpp/http/fetch/http_socket.cpp @@ -0,0 +1,206 @@ +#include "httpload.h" +#include "http_digest.h" + +/************************************************************/ + +#ifdef USE_GNUTLS + +#include <gcrypt.h> +#include <gnutls/gnutls.h> +#include <util/network/init.h> +#include <util/network/socket.h> +#include <util/system/mutex.h> + +/********************************************************/ +// HTTPS handler is used as implementation of +// socketAbstractHandler for work through HTTPS protocol + +class socketSecureHandler: public socketRegularHandler { +protected: + bool IsValid_; + gnutls_session Session_; + gnutls_certificate_credentials Credits_; + +public: + socketSecureHandler(); + virtual ~socketSecureHandler(); + + virtual bool Good(); + virtual int Connect(const TAddrList& addrs, TDuration Timeout); + virtual void Disconnect(); + virtual void shutdown(); + virtual bool send(const char* message, ssize_t messlen); + virtual bool peek(); + virtual ssize_t read(void* buffer, ssize_t buflen); +}; + +/********************************************************/ +/********************************************************/ +static int gcry_pthread_mutex_init(void** priv) { + int err = 0; + + try { + TMutex* lock = new TMutex; + *priv = lock; + } catch (...) { + err = -1; + } + + return err; +} + +static int gcry_pthread_mutex_destroy(void** lock) { + delete static_cast<TMutex*>(*lock); + + return 0; +} + +static int gcry_pthread_mutex_lock(void** lock) { + static_cast<TMutex*>(*lock)->Acquire(); + + return 0; +} + +static int gcry_pthread_mutex_unlock(void** lock) { + static_cast<TMutex*>(*lock)->Release(); + + return 0; +} + +static struct gcry_thread_cbs gcry_threads_pthread = + { + GCRY_THREAD_OPTION_PTHREAD, NULL, + gcry_pthread_mutex_init, gcry_pthread_mutex_destroy, + gcry_pthread_mutex_lock, gcry_pthread_mutex_unlock, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL}; + +/********************************************************/ +struct https_initor { + https_initor() { + gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); + gnutls_global_init(); + InitNetworkSubSystem(); + } + + ~https_initor() { + gnutls_global_deinit(); + } +}; + +static https_initor _initor; + +/********************************************************/ +socketSecureHandler::socketSecureHandler() + : socketRegularHandler() + , IsValid_(false) + , Session_() + , Credits_() +{ +} + +/********************************************************/ +socketSecureHandler::~socketSecureHandler() { + if (IsValid_) + Disconnect(); +} + +/********************************************************/ +bool socketSecureHandler::Good() { + return Socket_.Good() && IsValid_; +} + +/********************************************************/ +int socketSecureHandler::Connect(const TAddrList& addrs, TDuration Timeout) { + IsValid_ = false; + + int ret = socketRegularHandler::Connect(addrs, Timeout); + if (ret) + return ret; + + gnutls_certificate_allocate_credentials(&Credits_); + gnutls_init(&Session_, GNUTLS_CLIENT); + gnutls_set_default_priority(Session_); + gnutls_credentials_set(Session_, GNUTLS_CRD_CERTIFICATE, Credits_); + + SOCKET fd = Socket_; + gnutls_transport_set_ptr(Session_, (gnutls_transport_ptr)fd); + + ret = gnutls_handshake(Session_); + + if (ret < 0) { + fprintf(stderr, "*** Handshake failed\n"); + gnutls_perror(ret); + + gnutls_deinit(Session_); + if (Credits_) { + gnutls_certificate_free_credentials(Credits_); + Credits_ = 0; + } + return 1; + } + + IsValid_ = true; + return !IsValid_; +} + +/********************************************************/ +void socketSecureHandler::Disconnect() { + if (IsValid_) { + gnutls_bye(Session_, GNUTLS_SHUT_RDWR); + IsValid_ = false; + gnutls_deinit(Session_); + } + + if (Credits_) { + gnutls_certificate_free_credentials(Credits_); + Credits_ = 0; + } + + socketRegularHandler::Disconnect(); +} + +/********************************************************/ +void socketSecureHandler::shutdown() { +} + +/********************************************************/ +bool socketSecureHandler::send(const char* message, ssize_t messlen) { + if (!IsValid_) + return false; + ssize_t rv = gnutls_record_send(Session_, message, messlen); + return rv >= 0; +} + +/********************************************************/ +bool socketSecureHandler::peek() { + //ssize_t rv = gnutls_record_check_pending(mSession); + //return rv>0; + return true; +} + +/********************************************************/ +ssize_t socketSecureHandler::read(void* buffer, ssize_t buflen) { + if (!IsValid_) + return false; + return gnutls_record_recv(Session_, (char*)buffer, buflen); +} + +#endif + +/************************************************************/ +socketAbstractHandler* socketHandlerFactory::chooseHandler(const THttpURL& url) { + if (url.IsValidGlobal() && url.GetScheme() == THttpURL::SchemeHTTP) + return new socketRegularHandler; + +#ifdef USE_GNUTLS + if (url.IsValidGlobal() && url.GetScheme() == THttpURL::SchemeHTTPS) + return new socketSecureHandler; +#endif + + return nullptr; +} + +/************************************************************/ +socketHandlerFactory socketHandlerFactory::sInstance; +/************************************************************/ |