diff --git a/librepo/CMakeLists.txt b/librepo/CMakeLists.txt index 4f00a5ec..0f5a9cfb 100644 --- a/librepo/CMakeLists.txt +++ b/librepo/CMakeLists.txt @@ -52,6 +52,7 @@ TARGET_LINK_LIBRARIES(librepo ${LIBCRYPTO_LIBRARIES} ${GPGME_VANILLA_LIBRARIES} ${GLIB2_LIBRARIES} + ${GIO2_LIBRARIES} ) IF (WITH_ZCHUNK) TARGET_LINK_LIBRARIES(librepo ${ZCHUNKLIB_LIBRARIES}) diff --git a/librepo/handle.c b/librepo/handle.c index 2c23ed09..7acd0228 100644 --- a/librepo/handle.c +++ b/librepo/handle.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include "handle_internal.h" @@ -264,6 +266,26 @@ lr_handle_remote_sources_changed(LrHandle *handle, LrChangedRemoteSource type) } } +struct callback_data { + GMainLoop *loop; + long input_seconds; + time_t begin; + GNetworkMonitor *monitor; + GSocketConnectable *connectable; + GCancellable *cancellable; +}; + +gboolean timeout_callback(gpointer data) +{ + struct callback_data *dt = (struct callback_data*)data; + if(!g_network_monitor_can_reach(dt->monitor, dt->connectable, dt->cancellable, NULL) && + time(NULL) - dt->begin <= dt->input_seconds){ + return TRUE; + } + g_main_loop_quit(dt->loop); + return FALSE; +} + gboolean lr_handle_setopt(LrHandle *handle, GError **err, @@ -812,6 +834,10 @@ lr_handle_setopt(LrHandle *handle, c_rc = curl_easy_setopt(c_h, CURLOPT_FILETIME, handle->preservetime); break; + case LRO_NETWORK_WAIT: + assert(lr_handle_network_wait(handle, err, va_arg(arg, long))); + break; + default: g_set_error(err, LR_HANDLE_ERROR, LRE_BADOPTARG, "Unknown option"); @@ -841,7 +867,57 @@ lr_handle_setopt(LrHandle *handle, return ret; } -static gboolean +gboolean +lr_handle_network_wait(LrHandle *handle, GError **err, guint seconds) +{ + + assert(!err || *err == NULL); + + if (!handle) { + g_set_error(err, LR_HANDLE_ERROR, LRE_BADFUNCARG, + "No handle specified"); + return FALSE; + } + + GNetworkMonitor *monitor = g_network_monitor_get_default(); + GCancellable *cancellable = g_cancellable_new (); + + struct callback_data data_struct; + data_struct.input_seconds = seconds; + data_struct.begin = time(NULL); + data_struct.cancellable = cancellable; + data_struct.monitor = monitor; + + gchar *baseurl; + if(handle->metalinkurl) + baseurl = handle->metalinkurl; + else if(handle->mirrorlisturl) + baseurl = handle->mirrorlisturl; + else if(handle->urls) + baseurl = handle->urls[0]; + assert(baseurl); + + GUri *uri = g_uri_parse(baseurl, G_URI_FLAGS_NONE, NULL); + if(uri == NULL){ + return FALSE; + } + const gchar* host = g_uri_get_host(uri); + guint16 port = g_uri_get_port(uri); + GSocketConnectable *connectable = g_network_address_new(host, port); + data_struct.connectable = connectable; + GMainLoop *loop; + loop = g_main_loop_new(NULL, FALSE); + data_struct.loop = loop; + g_timeout_add(200, timeout_callback, &data_struct); + g_main_loop_run(loop); + g_main_loop_unref(loop); + + //Check for handle->metalinkurl and handle->mirrorlisturl + + return TRUE; +} + +gboolean lr_handle_prepare_urls(LrHandle *handle, GError **err) { assert(!handle->urls_mirrors); diff --git a/librepo/handle.h b/librepo/handle.h index 7c55a95b..abadc4a1 100644 --- a/librepo/handle.h +++ b/librepo/handle.h @@ -430,6 +430,9 @@ typedef enum { LRO_SENTINEL, /*!< Sentinel */ + LRO_NETWORK_WAIT, /*!< (long) + This option waits time t until the baseurl is reachable.*/ + } LrHandleOption; /*!< Handle config options */ /** Handle options for the ::lr_handle_getinfo function. */ @@ -560,6 +563,10 @@ lr_handle_getinfo(LrHandle *handle, gboolean lr_handle_perform(LrHandle *handle, LrResult *result, GError **err); + +gboolean +lr_handle_network_wait(LrHandle *handle, GError **err, guint seconds); + /** @} */ G_END_DECLS diff --git a/librepo/python/handle-py.c b/librepo/python/handle-py.c index 32bf4e19..e10d4e5d 100644 --- a/librepo/python/handle-py.c +++ b/librepo/python/handle-py.c @@ -470,6 +470,7 @@ py_setopt(_HandleObject *self, PyObject *args) case LRO_MAXDOWNLOADSPERMIRROR: case LRO_HTTPAUTHMETHODS: case LRO_PROXYAUTHMETHODS: + case LRO_NETWORK_WAIT: { long d;