|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
/*
|
|
Packit |
ee6627 |
Meanwhile - Unofficial Lotus Sametime Community Client Library
|
|
Packit |
ee6627 |
Copyright (C) 2004 Christopher (siege) O'Brien
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
This library is free software; you can redistribute it and/or
|
|
Packit |
ee6627 |
modify it under the terms of the GNU Library General Public
|
|
Packit |
ee6627 |
License as published by the Free Software Foundation; either
|
|
Packit |
ee6627 |
version 2 of the License, or (at your option) any later version.
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
This library is distributed in the hope that it will be useful,
|
|
Packit |
ee6627 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
ee6627 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
ee6627 |
Library General Public License for more details.
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
You should have received a copy of the GNU Library General Public
|
|
Packit |
ee6627 |
License along with this library; if not, write to the Free
|
|
Packit |
ee6627 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
Packit |
ee6627 |
*/
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
#include <glib/ghash.h>
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
#include "mw_channel.h"
|
|
Packit |
ee6627 |
#include "mw_common.h"
|
|
Packit |
ee6627 |
#include "mw_debug.h"
|
|
Packit |
ee6627 |
#include "mw_error.h"
|
|
Packit |
ee6627 |
#include "mw_service.h"
|
|
Packit |
ee6627 |
#include "mw_session.h"
|
|
Packit |
ee6627 |
#include "mw_srvc_resolve.h"
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
#define PROTOCOL_TYPE 0x00000015
|
|
Packit |
ee6627 |
#define PROTOCOL_VER 0x00000000
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
/** oddly, there is only one message type in this service */
|
|
Packit |
ee6627 |
#define RESOLVE_ACTION 0x02
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwServiceResolve {
|
|
Packit |
ee6627 |
struct mwService service;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwChannel *channel; /**< channel for this service */
|
|
Packit |
ee6627 |
GHashTable *searches; /**< guint32:struct mw_search */
|
|
Packit |
ee6627 |
guint32 counter; /**< incremented to provide searche IDs */
|
|
Packit |
ee6627 |
};
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
/** structure representing an active search. keeps track of the ID,
|
|
Packit |
ee6627 |
the handler, and the optional user data and cleanup */
|
|
Packit |
ee6627 |
struct mw_search {
|
|
Packit |
ee6627 |
struct mwServiceResolve *service;
|
|
Packit |
ee6627 |
guint32 id;
|
|
Packit |
ee6627 |
mwResolveHandler handler;
|
|
Packit |
ee6627 |
gpointer data;
|
|
Packit |
ee6627 |
GDestroyNotify cleanup;
|
|
Packit |
ee6627 |
};
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static struct mw_search *search_new(struct mwServiceResolve *srvc,
|
|
Packit |
ee6627 |
mwResolveHandler handler,
|
|
Packit |
ee6627 |
gpointer data, GDestroyNotify cleanup) {
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mw_search *search = g_new0(struct mw_search, 1);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
search->service = srvc;
|
|
Packit |
ee6627 |
search->handler = handler;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
/* we want search IDs that aren't SEARCH_ERROR */
|
|
Packit |
ee6627 |
do {
|
|
Packit |
ee6627 |
search->id = srvc->counter++;
|
|
Packit |
ee6627 |
} while(search->id == SEARCH_ERROR);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
search->data = data;
|
|
Packit |
ee6627 |
search->cleanup = cleanup;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
return search;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
/** called whenever a mw_search is removed from the searches table of
|
|
Packit |
ee6627 |
the service */
|
|
Packit |
ee6627 |
static void search_free(struct mw_search *search) {
|
|
Packit |
ee6627 |
g_return_if_fail(search != NULL);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(search->cleanup)
|
|
Packit |
ee6627 |
search->cleanup(search->data);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_free(search);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static const char *get_name(struct mwService *srvc) {
|
|
Packit |
ee6627 |
return "Identity Resolution";
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static const char *get_desc(struct mwService *srvc) {
|
|
Packit |
ee6627 |
return "Resolves short IDs to full IDs";
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static struct mwChannel *make_channel(struct mwServiceResolve *srvc) {
|
|
Packit |
ee6627 |
struct mwSession *session;
|
|
Packit |
ee6627 |
struct mwChannelSet *cs;
|
|
Packit |
ee6627 |
struct mwChannel *chan;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
session = mwService_getSession(MW_SERVICE(srvc));
|
|
Packit |
ee6627 |
cs = mwSession_getChannels(session);
|
|
Packit |
ee6627 |
chan = mwChannel_newOutgoing(cs);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwChannel_setService(chan, MW_SERVICE(srvc));
|
|
Packit |
ee6627 |
mwChannel_setProtoType(chan, PROTOCOL_TYPE);
|
|
Packit |
ee6627 |
mwChannel_setProtoVer(chan, PROTOCOL_VER);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
return mwChannel_create(chan)? NULL: chan;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void start(struct mwServiceResolve *srvc) {
|
|
Packit |
ee6627 |
struct mwChannel *chan;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_return_if_fail(srvc != NULL);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
chan = make_channel(srvc);
|
|
Packit |
ee6627 |
if(chan) {
|
|
Packit |
ee6627 |
srvc->channel = chan;
|
|
Packit |
ee6627 |
} else {
|
|
Packit |
ee6627 |
mwService_stopped(MW_SERVICE(srvc));
|
|
Packit |
ee6627 |
return;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
/* semi-lazily create the searches table */
|
|
Packit |
ee6627 |
srvc->searches = g_hash_table_new_full(g_direct_hash, g_direct_equal,
|
|
Packit |
ee6627 |
NULL, (GDestroyNotify) search_free);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void stop(struct mwServiceResolve *srvc) {
|
|
Packit |
ee6627 |
g_return_if_fail(srvc != NULL);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(srvc->channel) {
|
|
Packit |
ee6627 |
mwChannel_destroy(srvc->channel, ERR_SUCCESS, NULL);
|
|
Packit |
ee6627 |
srvc->channel = NULL;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
/* destroy all the pending requests. */
|
|
Packit |
ee6627 |
g_hash_table_destroy(srvc->searches);
|
|
Packit |
ee6627 |
srvc->searches = NULL;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwService_stopped(MW_SERVICE(srvc));
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void clear(struct mwServiceResolve *srvc) {
|
|
Packit |
ee6627 |
if(srvc->searches) {
|
|
Packit |
ee6627 |
g_hash_table_destroy(srvc->searches);
|
|
Packit |
ee6627 |
srvc->searches = NULL;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void recv_create(struct mwServiceResolve *srvc,
|
|
Packit |
ee6627 |
struct mwChannel *chan,
|
|
Packit |
ee6627 |
struct mwMsgChannelCreate *msg) {
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
/* you serve me, not the other way around */
|
|
Packit |
ee6627 |
mwChannel_destroy(chan, ERR_FAILURE, NULL);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void recv_accept(struct mwServiceResolve *srvc,
|
|
Packit |
ee6627 |
struct mwChannel *chan,
|
|
Packit |
ee6627 |
struct mwMsgChannelAccept *msg) {
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_return_if_fail(srvc != NULL);
|
|
Packit |
ee6627 |
g_return_if_fail(chan != NULL);
|
|
Packit |
ee6627 |
g_return_if_fail(chan == srvc->channel);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwService_started(MW_SERVICE(srvc));
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void recv_destroy(struct mwServiceResolve *srvc,
|
|
Packit |
ee6627 |
struct mwChannel *chan,
|
|
Packit |
ee6627 |
struct mwMsgChannelDestroy *msg) {
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwSession *session;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_return_if_fail(srvc != NULL);
|
|
Packit |
ee6627 |
g_return_if_fail(chan != NULL);
|
|
Packit |
ee6627 |
g_return_if_fail(chan == srvc->channel);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
srvc->channel = NULL;
|
|
Packit |
ee6627 |
mwService_stop(MW_SERVICE(srvc));
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
session = mwService_getSession(MW_SERVICE(srvc));
|
|
Packit |
ee6627 |
g_return_if_fail(session != NULL);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwSession_senseService(session, mwService_getType(MW_SERVICE(srvc)));
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static GList *load_matches(struct mwGetBuffer *b, guint32 count) {
|
|
Packit |
ee6627 |
GList *matches = NULL;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
while(count--) {
|
|
Packit |
ee6627 |
struct mwResolveMatch *m = g_new0(struct mwResolveMatch, 1);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwString_get(b, &m->id);
|
|
Packit |
ee6627 |
mwString_get(b, &m->name);
|
|
Packit |
ee6627 |
mwString_get(b, &m->desc);
|
|
Packit |
ee6627 |
guint32_get(b, &m->type);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
matches = g_list_append(matches, m);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
return matches;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static GList *load_results(struct mwGetBuffer *b, guint32 count) {
|
|
Packit |
ee6627 |
GList *results = NULL;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
while(count--) {
|
|
Packit |
ee6627 |
struct mwResolveResult *r = g_new0(struct mwResolveResult, 1);
|
|
Packit |
ee6627 |
guint32 junk, matches;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
guint32_get(b, &junk);
|
|
Packit |
ee6627 |
guint32_get(b, &r->code);
|
|
Packit |
ee6627 |
mwString_get(b, &r->name);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
guint32_get(b, &matches);
|
|
Packit |
ee6627 |
r->matches = load_matches(b, matches);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
results = g_list_append(results, r);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
return results;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void free_matches(GList *matches) {
|
|
Packit |
ee6627 |
for(; matches; matches = g_list_delete_link(matches, matches)) {
|
|
Packit |
ee6627 |
struct mwResolveMatch *m = matches->data;
|
|
Packit |
ee6627 |
g_free(m->id);
|
|
Packit |
ee6627 |
g_free(m->name);
|
|
Packit |
ee6627 |
g_free(m->desc);
|
|
Packit |
ee6627 |
g_free(m);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void free_results(GList *results) {
|
|
Packit |
ee6627 |
for(; results; results = g_list_delete_link(results, results)) {
|
|
Packit |
ee6627 |
struct mwResolveResult *r = results->data;
|
|
Packit |
ee6627 |
g_free(r->name);
|
|
Packit |
ee6627 |
free_matches(r->matches);
|
|
Packit |
ee6627 |
g_free(r);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void recv(struct mwServiceResolve *srvc,
|
|
Packit |
ee6627 |
struct mwChannel *chan,
|
|
Packit |
ee6627 |
guint16 type, struct mwOpaque *data) {
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwGetBuffer *b;
|
|
Packit |
ee6627 |
guint32 junk, id, code, count;
|
|
Packit |
ee6627 |
struct mw_search *search;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_return_if_fail(srvc != NULL);
|
|
Packit |
ee6627 |
g_return_if_fail(chan != NULL);
|
|
Packit |
ee6627 |
g_return_if_fail(chan == srvc->channel);
|
|
Packit |
ee6627 |
g_return_if_fail(data != NULL);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(type != RESOLVE_ACTION) {
|
|
Packit |
ee6627 |
mw_mailme_opaque(data, "unknown message in resolve service: 0x%04x", type);
|
|
Packit |
ee6627 |
return;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
b = mwGetBuffer_wrap(data);
|
|
Packit |
ee6627 |
guint32_get(b, &junk);
|
|
Packit |
ee6627 |
guint32_get(b, &id;;
|
|
Packit |
ee6627 |
guint32_get(b, &code);
|
|
Packit |
ee6627 |
guint32_get(b, &count);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(mwGetBuffer_error(b)) {
|
|
Packit |
ee6627 |
g_warning("error parsing search result");
|
|
Packit |
ee6627 |
mwGetBuffer_free(b);
|
|
Packit |
ee6627 |
return;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
search = g_hash_table_lookup(srvc->searches, GUINT_TO_POINTER(id));
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(search) {
|
|
Packit |
ee6627 |
GList *results = load_results(b, count);
|
|
Packit |
ee6627 |
if(mwGetBuffer_error(b)) {
|
|
Packit |
ee6627 |
g_warning("error parsing search results");
|
|
Packit |
ee6627 |
} else {
|
|
Packit |
ee6627 |
g_debug("triggering handler");
|
|
Packit |
ee6627 |
search->handler(srvc, id, code, results, search->data);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
free_results(results);
|
|
Packit |
ee6627 |
g_hash_table_remove(srvc->searches, GUINT_TO_POINTER(id));
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
} else {
|
|
Packit |
ee6627 |
g_debug("no search found: 0x%x", id);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwGetBuffer_free(b);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwServiceResolve *mwServiceResolve_new(struct mwSession *session) {
|
|
Packit |
ee6627 |
struct mwServiceResolve *srvc_resolve;
|
|
Packit |
ee6627 |
struct mwService *srvc;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_return_val_if_fail(session != NULL, NULL);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
srvc_resolve = g_new0(struct mwServiceResolve, 1);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
srvc = MW_SERVICE(srvc_resolve);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwService_init(srvc, session, mwService_RESOLVE);
|
|
Packit |
ee6627 |
srvc->get_name = get_name;
|
|
Packit |
ee6627 |
srvc->get_desc = get_desc;
|
|
Packit |
ee6627 |
srvc->recv_create = (mwService_funcRecvCreate) recv_create;
|
|
Packit |
ee6627 |
srvc->recv_accept = (mwService_funcRecvAccept) recv_accept;
|
|
Packit |
ee6627 |
srvc->recv_destroy = (mwService_funcRecvDestroy) recv_destroy;
|
|
Packit |
ee6627 |
srvc->recv = (mwService_funcRecv) recv;
|
|
Packit |
ee6627 |
srvc->start = (mwService_funcStart) start;
|
|
Packit |
ee6627 |
srvc->stop = (mwService_funcStop) stop;
|
|
Packit |
ee6627 |
srvc->clear = (mwService_funcClear) clear;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
return srvc_resolve;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
guint32 mwServiceResolve_resolve(struct mwServiceResolve *srvc,
|
|
Packit |
ee6627 |
GList *queries, enum mwResolveFlag flags,
|
|
Packit |
ee6627 |
mwResolveHandler handler,
|
|
Packit |
ee6627 |
gpointer data, GDestroyNotify cleanup) {
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mw_search *search;
|
|
Packit |
ee6627 |
struct mwPutBuffer *b;
|
|
Packit |
ee6627 |
struct mwOpaque o = { 0, 0 };
|
|
Packit |
ee6627 |
int ret, count = 0;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_return_val_if_fail(srvc != NULL, SEARCH_ERROR);
|
|
Packit |
ee6627 |
g_return_val_if_fail(handler != NULL, SEARCH_ERROR);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
count = g_list_length(queries);
|
|
Packit |
ee6627 |
g_return_val_if_fail(count > 0, SEARCH_ERROR);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
search = search_new(srvc, handler, data, cleanup);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
b = mwPutBuffer_new();
|
|
Packit |
ee6627 |
guint32_put(b, 0x00); /* to be overwritten */
|
|
Packit |
ee6627 |
guint32_put(b, search->id);
|
|
Packit |
ee6627 |
guint32_put(b, count);
|
|
Packit |
ee6627 |
for(; queries; queries = queries->next)
|
|
Packit |
ee6627 |
mwString_put(b, queries->data);
|
|
Packit |
ee6627 |
guint32_put(b, flags);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwPutBuffer_finalize(&o, b);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
ret = mwChannel_send(srvc->channel, RESOLVE_ACTION, &o);
|
|
Packit |
ee6627 |
if(ret) {
|
|
Packit |
ee6627 |
search_free(search);
|
|
Packit |
ee6627 |
return SEARCH_ERROR;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
} else {
|
|
Packit |
ee6627 |
g_hash_table_insert(srvc->searches,
|
|
Packit |
ee6627 |
GUINT_TO_POINTER(search->id), search);
|
|
Packit |
ee6627 |
return search->id;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
void mwServiceResolve_cancelResolve(struct mwServiceResolve *srvc,
|
|
Packit |
ee6627 |
guint32 id) {
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_return_if_fail(srvc != NULL);
|
|
Packit |
ee6627 |
g_return_if_fail(srvc->searches != NULL);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_hash_table_remove(srvc->searches, GUINT_TO_POINTER(id));
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|