aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/http/fetch/http_socket.cpp
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/http/fetch/http_socket.cpp
downloadydb-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.cpp206
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;
+/************************************************************/