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 committed Sep 7, 2022
1 parent 66d4f81 commit 6ccecfa
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 2 deletions.
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
103 changes: 102 additions & 1 deletion 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,50 @@ 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 no internet, remove source
if(!g_network_monitor_get_network_available(dt->monitor)){
return G_SOURCE_REMOVE;
}

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

//if url not reached and time exists, keep source and poll
if(!g_network_monitor_can_reach (dt->monitor, dt->connectable, dt->cancellable, NULL) &&
g_get_monotonic_time() < dt->deadline_millis){
return G_SOURCE_CONTINUE;
}

//if time does not exist, remove source and exit
g_main_loop_quit(dt->loop);
return G_SOURCE_REMOVE;
}

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,7 +887,62 @@ lr_handle_setopt(LrHandle *handle,
return ret;
}

static gboolean
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;
}

gboolean
lr_handle_prepare_urls(LrHandle *handle, GError **err)
{
assert(!handle->urls_mirrors);
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 6ccecfa

Please sign in to comment.