Skip to content

Commit

Permalink
CMakeLists.txt: added requirement for gio-2.0 library
Browse files Browse the repository at this point in the history
handle.h: function signature for lr_handle_network_wait
handle.c: Added callback function required for GMainEventLoop

Adds API support for waiting on network in an event driven manner:
This waits for clients network interfaces till the specified time.
lr_handle_network_wait(priv->repo_handle, error, timeout_seconds)
This parses metalinkurl/baseurl and upon network-available signal,
it polls g_network_monitor_can_reach() with the help of
GMainEventLoop.
  • Loading branch information
RishabhSaini authored and m-blaha committed Oct 14, 2022
1 parent f4b915b commit 5dec492
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 1 deletion.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
# Find necessare libraries

FIND_PACKAGE(PkgConfig)
PKG_CHECK_MODULES(GLIB2 glib-2.0>=2.28 REQUIRED)
PKG_CHECK_MODULES(GLIB2 glib-2.0>=2.28 gio-2.0 REQUIRED)
PKG_SEARCH_MODULE(LIBCRYPTO REQUIRED libcrypto openssl)
PKG_CHECK_MODULES(LIBXML2 libxml-2.0 REQUIRED)
FIND_PACKAGE(CURL 7.52.0 REQUIRED)
Expand Down
101 changes: 101 additions & 0 deletions librepo/handle.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <gio/gio.h>


#include "handle_internal.h"
Expand Down Expand Up @@ -264,6 +266,51 @@ lr_handle_remote_sources_changed(LrHandle *handle, LrChangedRemoteSource type)
}
}

struct callback_data {
GMainLoop *loop;
guint64 deadline_millis;
guint timeout_id;
GNetworkMonitor *monitor;
GSocketConnectable *connectable;
GCancellable *cancellable;
};

gboolean
timeout_callback(gpointer data)
{
struct callback_data *dt = (struct callback_data*)data;

//if past deadline, exit
if (g_get_monotonic_time() >= dt->deadline_millis) {
g_main_loop_quit(dt->loop);
return G_SOURCE_REMOVE;
}

//if no internet, remove source
if (!g_network_monitor_get_network_available(dt->monitor)) {
return G_SOURCE_REMOVE;
}

//if url reached, quit loop and remove source
if (g_network_monitor_can_reach (dt->monitor, dt->connectable, dt->cancellable, NULL)) {
g_main_loop_quit(dt->loop);
return G_SOURCE_REMOVE;
}

//Still waiting on the URL to be availbale, keep polling
return G_SOURCE_CONTINUE;
}

void
on_network_available(GObject *object, GParamSpec *pspec, gpointer data)
{
struct callback_data *dt = (struct callback_data*)data;
if (dt->timeout_id == 0 && g_network_monitor_get_network_available(dt->monitor)) {
dt->timeout_id = g_timeout_add(200, timeout_callback, dt);
}
g_main_loop_run(dt->loop);
}

gboolean
lr_handle_setopt(LrHandle *handle,
GError **err,
Expand Down Expand Up @@ -841,6 +888,60 @@ lr_handle_setopt(LrHandle *handle,
return ret;
}

gboolean
lr_handle_network_wait(LrHandle *handle, GError **err, guint seconds, GCancellable *cancellable)
{
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();

struct callback_data data_struct;
data_struct.cancellable = cancellable;
data_struct.monitor = monitor;

const 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);

g_autoptr(GUri) uri = g_uri_parse(baseurl, G_URI_FLAGS_NONE, NULL);
if (uri == NULL) {
return FALSE;
}
const gchar* scheme = g_uri_get_scheme(uri);
if (!g_strcmp0(scheme, "file")) {
return TRUE;
}
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;
data_struct.deadline_millis = g_get_monotonic_time() + seconds * G_USEC_PER_SEC;
g_autoptr(GMainLoop) loop;
loop = g_main_loop_new(NULL, FALSE);
data_struct.loop = loop;
data_struct.timeout_id = 0;

if (g_network_monitor_get_network_available(data_struct.monitor)) {
data_struct.timeout_id = g_timeout_add(200, timeout_callback, &data_struct);
g_main_loop_run(data_struct.loop);
}
else{
g_signal_connect(monitor, "notify::network-available", G_CALLBACK(on_network_available), &data_struct);
}
return TRUE;
}

static gboolean
lr_handle_prepare_urls(LrHandle *handle, GError **err)
{
Expand Down
11 changes: 11 additions & 0 deletions librepo/handle.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#define __LR_HANDLE_H__

#include <glib.h>
#include <gio/gio.h>

#include "result.h"

Expand Down Expand Up @@ -560,6 +561,16 @@ lr_handle_getinfo(LrHandle *handle,
gboolean
lr_handle_perform(LrHandle *handle, LrResult *result, GError **err);

/** Handle waiting on network for LRO_URLS.
* @param handle Librepo handle.
* @param seconds Network timeout seconds
* @param err GError **
* @param cancellable GCancellable *
* @return TRUE if everything is ok, FALSE if err is set.
*/
gboolean
lr_handle_network_wait(LrHandle *handle, GError **err, guint seconds, GCancellable *cancellable);

/** @} */

G_END_DECLS
Expand Down

0 comments on commit 5dec492

Please sign in to comment.