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