src/protocols/sametime/meanwhile/srvc_conf.c

changeset 12957
9af807a5c9e7
parent 12956
39a4efae983c
child 12958
706645a0b944
--- a/src/protocols/sametime/meanwhile/srvc_conf.c	Fri Jan 20 00:19:53 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,865 +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.h>
-#include <glib/ghash.h>
-#include <glib/glist.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include "mw_channel.h"
-#include "mw_debug.h"
-#include "mw_error.h"
-#include "mw_message.h"
-#include "mw_service.h"
-#include "mw_session.h"
-#include "mw_srvc_conf.h"
-#include "mw_util.h"
-
-
-/* This thing needs a re-write. More than anything else, I need to
-   re-examine the conferencing service protocol from more modern
-   clients */
-
-
-#define PROTOCOL_TYPE   0x00000010
-#define PROTOCOL_VER    0x00000002
-
-
-/** @see mwMsgChannelSend::type
-    @see recv */
-enum msg_type {
-  msg_WELCOME  = 0x0000,  /**< welcome message */
-  msg_INVITE   = 0x0001,  /**< outgoing invitation */
-  msg_JOIN     = 0x0002,  /**< someone joined */
-  msg_PART     = 0x0003,  /**< someone left */
-  msg_MESSAGE  = 0x0004,  /**< conference message */
-};
-
-
-/** the conferencing service */
-struct mwServiceConference {
-  struct mwService service;
-
-  /** call-back handler for this service */
-  struct mwConferenceHandler *handler;
-
-  /** collection of conferences in this service */
-  GList *confs;
-};
-
-
-/** a conference and its members */
-struct mwConference {
-  enum mwConferenceState state;   /**< state of the conference */
-  struct mwServiceConference *service;  /**< owning service */
-  struct mwChannel *channel;      /**< conference's channel */
-
-  char *name;   /**< server identifier for the conference */
-  char *title;  /**< topic for the conference */
-
-  struct mwLoginInfo owner;  /**< person who created this conference */
-  GHashTable *members;       /**< mapping guint16:mwLoginInfo */
-  struct mw_datum client_data;
-};
-
-
-#define MEMBER_FIND(conf, id) \
-  g_hash_table_lookup(conf->members, GUINT_TO_POINTER((guint) id))
-
-
-#define MEMBER_ADD(conf, id, member) \
-  g_hash_table_insert(conf->members, GUINT_TO_POINTER((guint) id), member)
-
-
-#define MEMBER_REM(conf, id) \
-  g_hash_table_remove(conf->members, GUINT_TO_POINTER((guint) id));
-
-
-/** clear and free a login info block */
-static void login_free(struct mwLoginInfo *li) {
-  mwLoginInfo_clear(li);
-  g_free(li);
-}
-
-
-/** generates a random conference name built around a user name */
-static char *conf_generate_name(const char *user) {
-  guint a, b;
-  char *ret;
-  
-  user = user? user: "";
-
-  srand(clock() + rand());
-  a = ((rand() & 0xff) << 8) | (rand() & 0xff);
-  b = time(NULL);
-
-  ret = g_strdup_printf("%s(%08x,%04x)", user, b, a);
-  g_debug("generated random conference name: '%s'", ret);
-  return ret;
-}
-
-
-
-
-
-static struct mwConference *conf_new(struct mwServiceConference *srvc) {
-
-  struct mwConference *conf;
-  struct mwSession *session;
-  const char *user;
-
-  conf = g_new0(struct mwConference, 1);
-  conf->state = mwConference_NEW;
-  conf->service = srvc;
-  conf->members = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
-					(GDestroyNotify) login_free);
-
-  session = mwService_getSession(MW_SERVICE(srvc));
-  user = mwSession_getProperty(session, mwSession_AUTH_USER_ID);
-
-  srvc->confs = g_list_prepend(srvc->confs, conf);
-
-  return conf;
-}
-
-
-/** clean and free a conference structure */
-static void conf_free(struct mwConference *conf) {
-  struct mwServiceConference *srvc;
-
-  /* this shouldn't ever happen, but just to be sure */
-  g_return_if_fail(conf != NULL);
-  
-  srvc = conf->service;
-
-  if(conf->members)
-    g_hash_table_destroy(conf->members);
-
-  g_list_remove_all(srvc->confs, conf);
-
-  mw_datum_clear(&conf->client_data);
-  
-  g_free(conf->name);
-  g_free(conf->title);
-  g_free(conf);
-}
-
-
-static struct mwConference *conf_find(struct mwServiceConference *srvc,
-				      struct mwChannel *chan) {
-  GList *l;
-
-  g_return_val_if_fail(srvc != NULL, NULL);
-  g_return_val_if_fail(chan != NULL, NULL);
-  
-  for(l = srvc->confs; l; l = l->next) {
-    struct mwConference *conf = l->data;
-    if(conf->channel == chan) return conf;
-  }
-
-  return NULL;
-}
-
-
-static const char *conf_state_str(enum mwConferenceState state) {
-  switch(state) {
-  case mwConference_NEW:      return "new";
-  case mwConference_PENDING:  return "pending";
-  case mwConference_INVITED:  return "invited";
-  case mwConference_OPEN:     return "open";
-  case mwConference_CLOSING:  return "closing";
-  case mwConference_ERROR:    return "error";
-
-  case mwConference_UNKNOWN:  /* fall through */
-  default:                    return "UNKNOWN";
-  }
-}
-
-
-static void conf_state(struct mwConference *conf,
-		       enum mwConferenceState state) {
-  g_return_if_fail(conf != NULL);
-
-  if(conf->state == state) return;
-
-  conf->state = state;
-  g_message("conference %s state: %s",
-	    NSTR(conf->name), conf_state_str(state));
-}
-
-
-static void recv_channelCreate(struct mwService *srvc,
-			       struct mwChannel *chan,
-			       struct mwMsgChannelCreate *msg) {
-
-  /* - this is how we really receive invitations
-     - create a conference and associate it with the channel
-     - obtain the invite data from the msg addtl info
-     - mark the conference as INVITED
-     - trigger the got_invite event
-  */
-
-  struct mwServiceConference *srvc_conf = (struct mwServiceConference *) srvc;
-  struct mwConference *conf;
-
-  struct mwGetBuffer *b;
-
-  char *invite = NULL;
-  guint tmp;
-
-  conf = conf_new(srvc_conf);
-  conf->channel = chan;
-
-  b = mwGetBuffer_wrap(&msg->addtl);
-
-  guint32_get(b, &tmp);
-  mwString_get(b, &conf->name);
-  mwString_get(b, &conf->title);
-  guint32_get(b, &tmp);
-  mwLoginInfo_get(b, &conf->owner);
-  guint32_get(b, &tmp);
-  mwString_get(b, &invite);
-
-  if(mwGetBuffer_error(b)) {
-    g_warning("failure parsing addtl for conference invite");
-    mwConference_destroy(conf, ERR_FAILURE, NULL);
-
-  } else {
-    struct mwConferenceHandler *h = srvc_conf->handler;
-    conf_state(conf, mwConference_INVITED);
-    if(h->on_invited)
-      h->on_invited(conf, &conf->owner, invite);
-  }
-
-  mwGetBuffer_free(b);
-  g_free(invite);
-}
-
-
-static void recv_channelAccept(struct mwService *srvc,
-			       struct mwChannel *chan,
-			       struct mwMsgChannelAccept *msg) {
-
-  ;
-}
-
-
-static void recv_channelDestroy(struct mwService *srvc,
-				struct mwChannel *chan,
-				struct mwMsgChannelDestroy *msg) {
-
-  /* - find conference from channel
-     - trigger got_closed
-     - remove conference, dealloc
-  */
-
-  struct mwServiceConference *srvc_conf = (struct mwServiceConference *) srvc;
-  struct mwConference *conf = conf_find(srvc_conf, chan);
-  struct mwConferenceHandler *h = srvc_conf->handler;
-
-  /* if there's no such conference, then I guess there's nothing to worry
-     about. Except of course for the fact that we should never receive a
-     channel destroy for a conference that doesn't exist. */
-  if(! conf) return;
-
-  conf->channel = NULL;
-
-  conf_state(conf, msg->reason? mwConference_ERROR: mwConference_CLOSING);
-
-  if(h->conf_closed)
-    h->conf_closed(conf, msg->reason);
-
-  mwConference_destroy(conf, ERR_SUCCESS, NULL);
-}
-
-
-static void WELCOME_recv(struct mwServiceConference *srvc,
-			 struct mwConference *conf,
-			 struct mwGetBuffer *b) {
-
-  struct mwConferenceHandler *h;
-  guint16 tmp16;
-  guint32 tmp32;
-  guint32 count;
-  GList *l = NULL;
-
-  /* re-read name and title */
-  g_free(conf->name);
-  g_free(conf->title);
-  conf->name = NULL;
-  conf->title = NULL;
-  mwString_get(b, &conf->name);
-  mwString_get(b, &conf->title);
-
-  /* some numbers we don't care about, then a count of members */
-  guint16_get(b, &tmp16);
-  guint32_get(b, &tmp32);
-  guint32_get(b, &count);
-
-  if(mwGetBuffer_error(b)) {
-    g_warning("error parsing welcome message for conference");
-    mwConference_destroy(conf, ERR_FAILURE, NULL);
-    return;
-  }
-  
-  while(count--) {
-    guint16 member_id;
-    struct mwLoginInfo *member = g_new0(struct mwLoginInfo, 1);
-
-    guint16_get(b, &member_id);
-    mwLoginInfo_get(b, member);
-
-    if(mwGetBuffer_error(b)) {
-      login_free(member);
-      break;
-    }
-
-    MEMBER_ADD(conf, member_id, member);
-    l = g_list_append(l, member);
-  }
-
-  conf_state(conf, mwConference_OPEN);
-
-  h = srvc->handler;
-  if(h->conf_opened)
-    h->conf_opened(conf, l);
-
-  /* get rid of the GList, but not its contents */
-  g_list_free(l);
-}
-
-
-static void JOIN_recv(struct mwServiceConference *srvc,
-		      struct mwConference *conf,
-		      struct mwGetBuffer *b) {
-
-  struct mwConferenceHandler *h;
-  guint16 m_id;
-  struct mwLoginInfo *m;
-  
-  /* for some inane reason, conferences we create will send a join
-     message for ourselves before the welcome message. Since the
-     welcome message will list our ID among those in the channel,
-     we're going to just pretend that these join messages don't
-     exist */
-  if(conf->state == mwConference_PENDING)
-    return;
-
-  m = g_new0(struct mwLoginInfo, 1);
-
-  guint16_get(b, &m_id);
-  mwLoginInfo_get(b, m);
-
-  if(mwGetBuffer_error(b)) {
-    g_warning("failed parsing JOIN message in conference");
-    login_free(m);
-    return;
-  }
-
-  MEMBER_ADD(conf, m_id, m);
-
-  h = srvc->handler;
-  if(h->on_peer_joined)
-    h->on_peer_joined(conf, m);
-}
-
-
-static void PART_recv(struct mwServiceConference *srvc,
-		      struct mwConference *conf,
-		      struct mwGetBuffer *b) {
-
-  /* - parse who left
-     - look up their membership
-     - remove them from the members list
-     - trigger the event
-  */
-
-  struct mwConferenceHandler *h;
-  guint16 id = 0;
-  struct mwLoginInfo *m;
-
-  guint16_get(b, &id);
-
-  if(mwGetBuffer_error(b)) return;
-
-  m = MEMBER_FIND(conf, id);
-  if(! m) return;
-
-  h = srvc->handler;
-  if(h->on_peer_parted)
-    h->on_peer_parted(conf, m);
-
-  MEMBER_REM(conf, id);
-}
-
-
-static void text_recv(struct mwServiceConference *srvc,
-		      struct mwConference *conf,
-		      struct mwLoginInfo *m,
-		      struct mwGetBuffer *b) {
-
-  /* this function acts a lot like receiving an IM Text message. The text
-     message contains only a string */
-
-  char *text = NULL;
-  struct mwConferenceHandler *h;
-  
-  mwString_get(b, &text);
-
-  if(mwGetBuffer_error(b)) {
-    g_warning("failed to parse text message in conference");
-    g_free(text);
-    return;
-  }
-
-  h = srvc->handler;
-  if(text && h->on_text) {
-    h->on_text(conf, m, text);
-  }
-
-  g_free(text);
-}
-
-
-static void data_recv(struct mwServiceConference *srvc,
-		      struct mwConference *conf,
-		      struct mwLoginInfo *m,
-		      struct mwGetBuffer *b) {
-
-  /* this function acts a lot like receiving an IM Data message. The
-     data message has a type, a subtype, and an opaque. We only
-     support typing notification though. */
-
-  /** @todo it's possible that some clients send text in a data
-      message, as we've seen rarely in the IM service. Have to add
-      support for that here */
-
-  guint32 type, subtype;
-  struct mwConferenceHandler *h;
-
-  guint32_get(b, &type);
-  guint32_get(b, &subtype);
-
-  if(mwGetBuffer_error(b)) return;
-
-  /* don't know how to deal with any others yet */
-  if(type != 0x01) {
-    g_message("unknown data message type (0x%08x, 0x%08x)", type, subtype);
-    return;
-  }
-
-  h = srvc->handler;
-  if(h->on_typing) {
-    h->on_typing(conf, m, !subtype);
-  }
-}
-
-
-static void MESSAGE_recv(struct mwServiceConference *srvc,
-			 struct mwConference *conf,
-			 struct mwGetBuffer *b) {
-
-  /* - look up who send the message by their id
-     - trigger the event
-  */
-
-  guint16 id;
-  guint32 type;
-  struct mwLoginInfo *m;
-
-  /* an empty buffer isn't an error, just ignored */
-  if(! mwGetBuffer_remaining(b)) return;
-
-  guint16_get(b, &id);
-  guint32_get(b, &type); /* reuse type variable */
-  guint32_get(b, &type);
-
-  if(mwGetBuffer_error(b)) return;
-
-  m = MEMBER_FIND(conf, id);
-  if(! m) {
-    g_warning("received message type 0x%04x from"
-	      " unknown conference member %u", type, id);
-    return;
-  }
-  
-  switch(type) {
-  case 0x01:  /* type is text */
-    text_recv(srvc, conf, m, b);
-    break;
-
-  case 0x02:  /* type is data */
-    data_recv(srvc, conf, m, b);
-    break;
-
-  default:
-    g_warning("unknown message type 0x%4x received in conference", type);
-  }
-}
-
-
-static void recv(struct mwService *srvc, struct mwChannel *chan,
-		 guint16 type, struct mwOpaque *data) {
-
-  struct mwServiceConference *srvc_conf = (struct mwServiceConference *) srvc;
-  struct mwConference *conf = conf_find(srvc_conf, chan);
-  struct mwGetBuffer *b;
-
-  g_return_if_fail(conf != NULL);
-
-  b = mwGetBuffer_wrap(data);
-
-  switch(type) {
-  case msg_WELCOME:
-    WELCOME_recv(srvc_conf, conf, b);
-    break;
-
-  case msg_JOIN:
-    JOIN_recv(srvc_conf, conf, b);
-    break;
-
-  case msg_PART:
-    PART_recv(srvc_conf, conf, b);
-    break;
-
-  case msg_MESSAGE:
-    MESSAGE_recv(srvc_conf, conf, b);
-    break;
-
-  default:
-    ; /* hrm. should log this. TODO */
-  }
-}
-
-
-static void clear(struct mwServiceConference *srvc) {
-  struct mwConferenceHandler *h;
-
-  while(srvc->confs)
-    conf_free(srvc->confs->data);
-
-  h = srvc->handler;
-  if(h && h->clear)
-    h->clear(srvc);
-  srvc->handler = NULL;
-}
-
-
-static const char *name(struct mwService *srvc) {
-  return "Basic Conferencing";
-}
-
-
-static const char *desc(struct mwService *srvc) {
-  return "Multi-user plain-text conferencing";
-}
-
-
-static void start(struct mwService *srvc) {
-  mwService_started(srvc);
-}
-
-
-static void stop(struct mwServiceConference *srvc) {
-  while(srvc->confs)
-    mwConference_destroy(srvc->confs->data, ERR_SUCCESS, NULL);
-
-  mwService_stopped(MW_SERVICE(srvc));
-}
-
-
-struct mwServiceConference *
-mwServiceConference_new(struct mwSession *session,
-			struct mwConferenceHandler *handler) {
-
-  struct mwServiceConference *srvc_conf;
-  struct mwService *srvc;
-
-  g_return_val_if_fail(session != NULL, NULL);
-  g_return_val_if_fail(handler != NULL, NULL);
-
-  srvc_conf = g_new0(struct mwServiceConference, 1);
-  srvc = &srvc_conf->service;
-
-  mwService_init(srvc, session, mwService_CONFERENCE);
-  srvc->start = start;
-  srvc->stop = (mwService_funcStop) stop;
-  srvc->recv_create = recv_channelCreate;
-  srvc->recv_accept = recv_channelAccept;
-  srvc->recv_destroy = recv_channelDestroy;
-  srvc->recv = recv;
-  srvc->clear = (mwService_funcClear) clear;
-  srvc->get_name = name;
-  srvc->get_desc = desc;
-
-  srvc_conf->handler = handler;
-
-  return srvc_conf;
-}
-
-
-struct mwConference *mwConference_new(struct mwServiceConference *srvc,
-				      const char *title) {
-  struct mwConference *conf;
-
-  g_return_val_if_fail(srvc != NULL, NULL);
-
-  conf = conf_new(srvc);
-  conf->title = g_strdup(title);
-
-  return conf;
-}
-
-
-struct mwServiceConference *
-mwConference_getService(struct mwConference *conf) {
-  g_return_val_if_fail(conf != NULL, NULL);
-  return conf->service;
-}
-
-
-const char *mwConference_getName(struct mwConference *conf) {
-  g_return_val_if_fail(conf != NULL, NULL);
-  return conf->name;
-}
-
-
-const char *mwConference_getTitle(struct mwConference *conf) {
-  g_return_val_if_fail(conf != NULL, NULL);
-  return conf->title;
-}
-
-
-GList *mwConference_memebers(struct mwConference *conf) {
-  g_return_val_if_fail(conf != NULL, NULL);
-  g_return_val_if_fail(conf->members != NULL, NULL);
-
-  return map_collect_values(conf->members);
-}
-
-
-int mwConference_open(struct mwConference *conf) {
-  struct mwSession *session;
-  struct mwChannel *chan;
-  struct mwPutBuffer *b;
-  int ret;
-  
-  g_return_val_if_fail(conf != NULL, -1);
-  g_return_val_if_fail(conf->service != NULL, -1);
-  g_return_val_if_fail(conf->state == mwConference_NEW, -1);
-  g_return_val_if_fail(conf->channel == NULL, -1);
-
-  session = mwService_getSession(MW_SERVICE(conf->service));
-  g_return_val_if_fail(session != NULL, -1);
-
-  if(! conf->name) {
-    char *user = mwSession_getProperty(session, mwSession_AUTH_USER_ID);
-    conf->name = conf_generate_name(user? user: "meanwhile");
-  }
-
-  chan = mwChannel_newOutgoing(mwSession_getChannels(session));
-  mwChannel_setService(chan, MW_SERVICE(conf->service));
-  mwChannel_setProtoType(chan, PROTOCOL_TYPE);
-  mwChannel_setProtoVer(chan, PROTOCOL_VER);
-  
-  /* offer all known ciphers */
-  mwChannel_populateSupportedCipherInstances(chan);
-
-  b = mwPutBuffer_new();
-  mwString_put(b, conf->name);
-  mwString_put(b, conf->title);
-  guint32_put(b, 0x00);
-  mwPutBuffer_finalize(mwChannel_getAddtlCreate(chan), b);
-
-  ret = mwChannel_create(chan);
-  if(ret) {
-    conf_state(conf, mwConference_ERROR);
-  } else {
-    conf_state(conf, mwConference_PENDING);
-    conf->channel = chan;
-  }
-
-  return ret;
-}
-
-
-int mwConference_destroy(struct mwConference *conf,
-			 guint32 reason, const char *text) {
-
-  struct mwServiceConference *srvc;
-  struct mwOpaque info = { 0, 0 };
-  int ret = 0;
-
-  g_return_val_if_fail(conf != NULL, -1);
-
-  srvc = conf->service;
-  g_return_val_if_fail(srvc != NULL, -1);
-
-  /* remove conference from the service */
-  srvc->confs = g_list_remove_all(srvc->confs, conf);
-
-  /* close the channel if applicable */
-  if(conf->channel) {
-    if(text && *text) {
-      info.len = strlen(text);
-      info.data = (guchar *) text;
-    }
-
-    ret = mwChannel_destroy(conf->channel, reason, &info);
-  }
-  
-  /* free the conference */
-  conf_free(conf);
-
-  return ret;
-}
-
-
-int mwConference_accept(struct mwConference *conf) {
-  /* - if conference is not INVITED, return -1
-     - accept the conference channel
-     - send an empty JOIN message
-  */
-
-  struct mwChannel *chan;
-  int ret;
-
-  g_return_val_if_fail(conf != NULL, -1);
-  g_return_val_if_fail(conf->state == mwConference_INVITED, -1);
-
-  chan = conf->channel;
-  ret = mwChannel_accept(chan);
-
-  if(! ret)
-    ret = mwChannel_sendEncrypted(chan, msg_JOIN, NULL, FALSE);
-
-  return ret;
-}
-
-
-int mwConference_invite(struct mwConference *conf,
-			struct mwIdBlock *who,
-			const char *text) {
-
-  struct mwPutBuffer *b;
-  struct mwOpaque o;
-  int ret;
-
-  g_return_val_if_fail(conf != NULL, -1);
-  g_return_val_if_fail(conf->channel != NULL, -1);
-  g_return_val_if_fail(who != NULL, -1);
-
-  b = mwPutBuffer_new();
-
-  mwIdBlock_put(b, who);
-  guint16_put(b, 0x00);
-  guint32_put(b, 0x00);
-  mwString_put(b, text);
-  mwString_put(b, who->user);
-
-  mwPutBuffer_finalize(&o, b);
-  ret = mwChannel_sendEncrypted(conf->channel, msg_INVITE, &o, FALSE);
-  mwOpaque_clear(&o);
-
-  return ret;
-}
-
-
-int mwConference_sendText(struct mwConference *conf, const char *text) {
-  struct mwPutBuffer *b;
-  struct mwOpaque o;
-  int ret;
-
-  g_return_val_if_fail(conf != NULL, -1);
-  g_return_val_if_fail(conf->channel != NULL, -1);
-
-  b = mwPutBuffer_new();
-
-  guint32_put(b, 0x01);
-  mwString_put(b, text);
-
-  mwPutBuffer_finalize(&o, b);
-  ret = mwChannel_sendEncrypted(conf->channel, msg_MESSAGE, &o, FALSE);
-  mwOpaque_clear(&o);
-
-  return ret;
-}
-
-
-int mwConference_sendTyping(struct mwConference *conf, gboolean typing) {
-  struct mwPutBuffer *b;
-  struct mwOpaque o;
-  int ret;
-
-  g_return_val_if_fail(conf != NULL, -1);
-  g_return_val_if_fail(conf->channel != NULL, -1);
-  g_return_val_if_fail(conf->state == mwConference_OPEN, -1);
-
-  b = mwPutBuffer_new();
-
-  guint32_put(b, 0x02);
-  guint32_put(b, 0x01);
-  guint32_put(b, !typing);
-  mwOpaque_put(b, NULL);
-
-  mwPutBuffer_finalize(&o, b);
-  ret = mwChannel_sendEncrypted(conf->channel, msg_MESSAGE, &o, FALSE);
-  mwOpaque_clear(&o);
-
-  return ret;
-}
-
-
-void mwConference_setClientData(struct mwConference *conference,
-			     gpointer data, GDestroyNotify clear) {
-
-  g_return_if_fail(conference != NULL);
-  mw_datum_set(&conference->client_data, data, clear);
-}
-
-
-gpointer mwConference_getClientData(struct mwConference *conference) {
-  g_return_val_if_fail(conference != NULL, NULL);
-  return mw_datum_get(&conference->client_data);
-}
-
-
-void mwConference_removeClientData(struct mwConference *conference) {
-  g_return_if_fail(conference != NULL);
-  mw_datum_clear(&conference->client_data);
-}
-
-
-struct mwConferenceHandler *
-mwServiceConference_getHandler(struct mwServiceConference *srvc) {
-  g_return_val_if_fail(srvc != NULL, NULL);
-  return srvc->handler;
-}
-
-
-GList *mwServiceConference_getConferences(struct mwServiceConference *srvc) {
-  g_return_val_if_fail(srvc != NULL, NULL);
-  return g_list_copy(srvc->confs);
-}
-

mercurial