249 lines
6.4 KiB
C
249 lines
6.4 KiB
C
#include <glib-object.h>
|
|
#include <string.h>
|
|
|
|
#include "gm-mcp-negotiate.h"
|
|
#include "gm-mcp.h"
|
|
#include "gm-mcp-session.h"
|
|
#include "gm-mcp-package.h"
|
|
#include "../gm-debug.h"
|
|
#include "../gm-support.h"
|
|
|
|
#define GM_MCP_NEGOTIATE_GET_PRIVATE(object)( \
|
|
G_TYPE_INSTANCE_GET_PRIVATE((object), \
|
|
GM_TYPE_MCP_NEGOTIATE, GmMcpNegotiatePrivate))
|
|
|
|
typedef struct _PackageInfo {
|
|
GmMcpPackageClass *klass;
|
|
gdouble version;
|
|
} PackageInfo;
|
|
|
|
struct _GmMcpNegotiatePrivate {
|
|
GList *packages;
|
|
};
|
|
|
|
/* Signals
|
|
|
|
enum {
|
|
PROTO
|
|
NUM_SIGNALS
|
|
};
|
|
|
|
static guint gm_mcp_negotiate_signals[NUM_SIGNALS] = {0};*/
|
|
|
|
void gm_mcp_negotiate_handle_simple(GmMcpPackage *package, gchar *suffix,
|
|
GList *fields);
|
|
|
|
G_DEFINE_TYPE(GmMcpNegotiate, gm_mcp_negotiate, GM_TYPE_MCP_PACKAGE);
|
|
|
|
static void
|
|
gm_mcp_negotiate_finalize(GObject *object) {
|
|
//GmMcpNegotiate *obj = GM_MCP_NEGOTIATE(object);
|
|
|
|
G_OBJECT_CLASS(gm_mcp_negotiate_parent_class)->finalize(object);
|
|
}
|
|
|
|
static void
|
|
gm_mcp_negotiate_class_init(GmMcpNegotiateClass *klass) {
|
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
|
GmMcpPackageClass *pklass = GM_MCP_PACKAGE_CLASS(klass);
|
|
|
|
object_class->finalize = gm_mcp_negotiate_finalize;
|
|
|
|
/*gm_mcp_negotiate_signals[PROTO] =
|
|
g_signal_new("proto",
|
|
G_OBJECT_CLASS_TYPE(object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET(GmMcpNegotiateClass, proto),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__VOID,
|
|
G_TYPE_NONE,
|
|
0);*/
|
|
|
|
pklass->name = "mcp-negotiate";
|
|
pklass->handle_simple = &gm_mcp_negotiate_handle_simple;
|
|
|
|
g_type_class_add_private(object_class, sizeof(GmMcpNegotiatePrivate));
|
|
}
|
|
|
|
static void
|
|
gm_mcp_negotiate_init(GmMcpNegotiate *obj) {
|
|
obj->priv = GM_MCP_NEGOTIATE_GET_PRIVATE(obj);
|
|
obj->priv->packages = NULL;
|
|
}
|
|
|
|
PackageInfo *
|
|
gm_mcp_negotiate_find_package(GmMcpNegotiate *package, gchar *name) {
|
|
PackageInfo *pinfo;
|
|
GList *elem;
|
|
|
|
for (elem = package->priv->packages; elem; elem = elem->next) {
|
|
pinfo = (PackageInfo *)(elem->data);
|
|
|
|
if (strcasecmp(pinfo->klass->name, name) == 0) {
|
|
return pinfo;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
void
|
|
gm_mcp_negotiate_fix_overrides(GmMcpNegotiate *package) {
|
|
GList *l, *item, *over;
|
|
PackageInfo *pinfo, *pover;
|
|
gchar *name;
|
|
|
|
l = g_list_copy(package->priv->packages);
|
|
|
|
for (item = l; item; item = item->next) {
|
|
pinfo = (PackageInfo *)(item->data);
|
|
|
|
for (over = pinfo->klass->overrides; over; over = over->next) {
|
|
name = (gchar *)(over->data);
|
|
|
|
if ((pover = gm_mcp_negotiate_find_package(package, name))) {
|
|
gm_debug_msg(DEBUG_MCP, "GmMcpNegotiate.FixOverrides: package %s "
|
|
"overrides %s", pinfo->klass->name, pover->klass->name);
|
|
package->priv->packages = g_list_remove(
|
|
package->priv->packages, pover);
|
|
}
|
|
}
|
|
}
|
|
|
|
g_list_free(l);
|
|
}
|
|
|
|
void
|
|
gm_mcp_negotiate_fix_depends(GmMcpNegotiate *package) {
|
|
PackageInfo *pinfo, *pdep;
|
|
GList *l, *item, *dep;
|
|
gchar *name;
|
|
|
|
l = g_list_copy(package->priv->packages);
|
|
|
|
for (item = l; item; item = item->next) {
|
|
pinfo = (PackageInfo *)(item->data);
|
|
|
|
for (dep = pinfo->klass->depends; dep; dep = dep->next) {
|
|
name = (gchar *)(dep->data);
|
|
|
|
if (!(pdep = gm_mcp_negotiate_find_package(package, name))) {
|
|
gm_debug_msg(DEBUG_MCP, "GmMcpNegotiate.FixDepends: package %s depends "
|
|
"on %s, but %s is not supported", pinfo->klass->name,
|
|
name, name);
|
|
|
|
// Remove package because depencendies are not met
|
|
package->priv->packages = g_list_remove(
|
|
package->priv->packages, pinfo);
|
|
break;
|
|
} else {
|
|
// Make sure this dependency is loaded before the package
|
|
package->priv->packages = g_list_remove(
|
|
package->priv->packages, pdep);
|
|
package->priv->packages = g_list_insert_before(
|
|
package->priv->packages,
|
|
g_list_find(package->priv->packages, pinfo), pdep);
|
|
}
|
|
}
|
|
}
|
|
|
|
g_list_free(l);
|
|
}
|
|
|
|
/* Public */
|
|
GmMcpNegotiate *
|
|
gm_mcp_negotiate_new() {
|
|
GmMcpNegotiate *obj = GM_MCP_NEGOTIATE(g_object_new(GM_TYPE_MCP_NEGOTIATE,
|
|
NULL));
|
|
|
|
return obj;
|
|
}
|
|
|
|
/* Private */
|
|
gboolean
|
|
gm_mcp_negotiate_send_can(GmMcpPackageClass *klass, gpointer user_data) {
|
|
GmMcpNegotiate *package = GM_MCP_NEGOTIATE(user_data);
|
|
gchar min_v[16], max_v[16];
|
|
|
|
g_ascii_formatd(min_v, 16, "%.1f", klass->min_version);
|
|
g_ascii_formatd(max_v, 16, "%.1f", klass->max_version);
|
|
|
|
gm_mcp_session_send_simple(GM_MCP_PACKAGE_SESSION(package),
|
|
"mcp-negotiate-can", "package", klass->name, "min-version",
|
|
min_v, "max-version", max_v, NULL);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
gm_mcp_negotiate_handle_simple(GmMcpPackage *package, gchar *suffix,
|
|
GList *fields) {
|
|
gchar const *pname;
|
|
GmMcpPackageClass *pklass;
|
|
GmMcpNegotiate *negotiate = GM_MCP_NEGOTIATE(package);
|
|
PackageInfo *pinfo;
|
|
double version;
|
|
gchar const *min_v, *max_v;
|
|
gdouble cmin = 0.0, cmax = 0.0;
|
|
GList *elem;
|
|
|
|
if (strcasecmp(suffix, "can") == 0) {
|
|
// Fields has package, min-version, max-version
|
|
pname = gm_mcp_find_value(fields, "package");
|
|
pklass = gm_mcp_session_find_package_class(pname);
|
|
|
|
if (pklass) {
|
|
min_v = gm_mcp_find_value(fields, "min-version");
|
|
|
|
if (min_v) {
|
|
cmin = g_ascii_strtod(min_v, NULL);
|
|
}
|
|
|
|
max_v = gm_mcp_find_value(fields, "max-version");
|
|
|
|
if (max_v) {
|
|
cmax = g_ascii_strtod(max_v, NULL);
|
|
}
|
|
|
|
version = gm_mcp_get_version(pklass->min_version,
|
|
pklass->max_version, cmin, cmax);
|
|
|
|
if (version > 0.0) {
|
|
gm_debug_msg(DEBUG_MCP, "GmMcpNegotiate.HandleSimple: %s, "
|
|
"package is supported", pname);
|
|
pinfo = g_new(PackageInfo, 1);
|
|
pinfo->klass = pklass;
|
|
pinfo->version = version;
|
|
|
|
negotiate->priv->packages = g_list_append(
|
|
negotiate->priv->packages, pinfo);
|
|
} else {
|
|
gm_debug_msg(DEBUG_MCP, "GmMcpNegotiate.HandleSimple: %s, package "
|
|
"supported but wrong version!", pname);
|
|
}
|
|
} else {
|
|
gm_debug_msg(DEBUG_MCP, "GmMcpNegotiate.HandleSimple: %s, package is not "
|
|
"supported!", pname);
|
|
}
|
|
} else if (strcasecmp(suffix, "end") == 0) {
|
|
gm_mcp_session_package_class_for_each(gm_mcp_negotiate_send_can,
|
|
(gpointer)(negotiate));
|
|
|
|
gm_mcp_session_send_simple(GM_MCP_PACKAGE_SESSION(negotiate),
|
|
"mcp-negotiate-end", NULL);
|
|
|
|
gm_mcp_negotiate_fix_overrides(negotiate);
|
|
gm_mcp_negotiate_fix_depends(negotiate);
|
|
|
|
for (elem = negotiate->priv->packages; elem; elem = elem->next) {
|
|
pinfo = (PackageInfo *)(elem->data);
|
|
gm_mcp_session_create_package(GM_MCP_PACKAGE_SESSION(negotiate),
|
|
pinfo->klass, pinfo->version);
|
|
g_free(pinfo);
|
|
}
|
|
|
|
g_list_free(negotiate->priv->packages);
|
|
negotiate->priv->packages = NULL;
|
|
}
|
|
}
|