Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Network wait API support #264

Merged
merged 1 commit into from
Oct 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
RishabhSaini marked this conversation as resolved.
Show resolved Hide resolved
}

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