src/protocols/sametime/meanwhile/srvc_place.c

changeset 12496
788b20ccec91
parent 12495
4b2c27ae504a
child 12497
a17568773be3
--- a/src/protocols/sametime/meanwhile/srvc_place.c	Fri Dec 16 03:34:01 2005 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1075 +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 "mw_channel.h"
-#include "mw_common.h"
-#include "mw_debug.h"
-#include "mw_error.h"
-#include "mw_message.h"
-#include "mw_service.h"
-#include "mw_session.h"
-#include "mw_srvc_place.h"
-#include "mw_util.h"
-
-
-#define PROTOCOL_TYPE  0x00
-#define PROTOCOL_VER   0x05
-
-
-enum incoming_msg {
-  msg_in_JOIN_RESPONSE  = 0x0000,  /* ? */
-  msg_in_INFO           = 0x0002,
-  msg_in_MESSAGE        = 0x0004,
-  msg_in_SECTION        = 0x0014,  /* see in_section_subtype */
-  msg_in_UNKNOWNa       = 0x0015,
-};
-
-
-enum in_section_subtype {
-  msg_in_SECTION_LIST  = 0x0000,  /* list of section members */
-  msg_in_SECTION_PEER  = 0x0001,  /* see in_section_peer_subtye */
-  msg_in_SECTION_PART  = 0x0003,
-};
-
-
-enum in_section_peer_subtype {
-  msg_in_SECTION_PEER_JOIN        = 0x0000,
-  msg_in_SECTION_PEER_PART        = 0x0001,  /* after msg_in_SECTION_PART */
-  msg_in_SECTION_PEER_CLEAR_ATTR  = 0x0003,
-  msg_in_SECTION_PEER_SET_ATTR    = 0x0004,
-};
-
-
-enum outgoing_msg {
-  msg_out_JOIN_PLACE  = 0x0000,  /* ? */
-  msg_out_PEER_INFO   = 0x0002,  /* ? */
-  msg_out_MESSAGE     = 0x0003,
-  msg_out_OLD_INVITE  = 0x0005,  /* old-style conf. invitation */
-  msg_out_SET_ATTR    = 0x000a,
-  msg_out_CLEAR_ATTR  = 0x000b,
-  msg_out_SECTION     = 0x0014,  /* see out_section_subtype */
-  msg_out_UNKNOWNb    = 0x001e,  /* ? maybe enter stage ? */
-};
-
-
-enum out_section_subtype {
-  msg_out_SECTION_LIST  = 0x0002,  /* req list of members */
-  msg_out_SECTION_PART  = 0x0003,
-};
-
-
-/*
-  : allocate section
-  : state = NEW
-
-  : create channel
-  : state = PENDING
-
-  : channel accepted
-  : msg_out_JOIN_PLACE  (maybe create?)
-  : state = JOINING
-
-  : msg_in_JOIN_RESPONSE (contains our place member ID and section ID)
-  : msg_in_INFO (for place, not peer)
-  : state = JOINED
-
-  : msg_out_SECTION_LIST (asking for all sections) (optional)
-  : msg_in_SECTION_LIST (listing all sections, as requested above)
-
-  : msg_out_PEER_INFO (with our place member ID) (optional)
-  : msg_in_INFO (peer info as requested above)
-
-  : msg_out_SECTION_LIST (with our section ID) (sorta optional)
-  : msg_in_SECTION_LIST (section listing as requested above)
-
-  : msg_out_UNKNOWNb
-  : msg_in_SECTION_PEER_JOINED (empty, with our place member ID)
-  : state = OPEN
-
-  : stuff... (invites, joins, parts, messages, attr)
-
-  : state = CLOSING
-  : msg_out_SECTION_PART
-  : destroy channel
-  : deallocate section
-*/
-
-
-struct mwServicePlace {
-  struct mwService service;
-  struct mwPlaceHandler *handler;
-  GList *places;
-};
-
-
-enum mwPlaceState {
-  mwPlace_NEW,
-  mwPlace_PENDING,
-  mwPlace_JOINING,
-  mwPlace_JOINED,
-  mwPlace_OPEN,
-  mwPlace_CLOSING,
-  mwPlace_ERROR,
-  mwPlace_UNKNOWN,
-};
-
-
-struct mwPlace {
-  struct mwServicePlace *service;
-
-  enum mwPlaceState state;
-  struct mwChannel *channel;
-
-  char *name;
-  char *title;
-  GHashTable *members;  /* mapping of member ID: place_member */
-  guint32 our_id;       /* our member ID */
-  guint32 section;      /* the section we're using */
-
-  guint32 requests;     /* counter for requests */
-
-  struct mw_datum client_data;
-};
-
-
-struct place_member {
-  guint32 place_id;
-  guint16 member_type;
-  struct mwIdBlock idb;
-  char *login_id;
-  char *name;
-  guint16 login_type;
-  guint32 unknown_a;
-  guint32 unknown_b;
-};
-
-
-#define GET_MEMBER(place, id) \
-  (g_hash_table_lookup(place->members, GUINT_TO_POINTER(id)))
-
-
-#define PUT_MEMBER(place, member) \
-  (g_hash_table_insert(place->members, \
-                       GUINT_TO_POINTER(member->place_id), member))
-
-
-#define REMOVE_MEMBER_ID(place, id) \
-  (g_hash_table_remove(place->members, GUINT_TO_POINTER(id)))
-
-
-#define REMOVE_MEMBER(place, member) \
-  REMOVE_MEMBER_ID(place, member->place_id)
-
-
-static void member_free(struct place_member *p) {
-  mwIdBlock_clear(&p->idb);
-  g_free(p->login_id);
-  g_free(p->name);
-  g_free(p);
-}
-
-
-__attribute__((used))
-static const struct mwLoginInfo *
-member_as_login_info(struct place_member *p) {
-  static struct mwLoginInfo li;
-  
-  li.login_id = p->login_id;
-  li.type = p->login_type;
-  li.user_id = p->idb.user;
-  li.user_name = p->name;
-  li.community = p->idb.community;
-  li.full = FALSE;
-
-  return &li;
-}
-
-
-static const char *place_state_str(enum mwPlaceState s) {
-  switch(s) {
-  case mwPlace_NEW:      return "new";
-  case mwPlace_PENDING:  return "pending";
-  case mwPlace_JOINING:  return "joining";
-  case mwPlace_JOINED:   return "joined";
-  case mwPlace_OPEN:     return "open";
-  case mwPlace_CLOSING:  return "closing";
-  case mwPlace_ERROR:    return "error";
-
-  case mwPlace_UNKNOWN:  /* fall-through */
-  default:               return "UNKNOWN";
-  }
-}
-
-
-static void place_state(struct mwPlace *place, enum mwPlaceState s) {
-  g_return_if_fail(place != NULL);
-  
-  if(place->state == s) return;
-
-  place->state = s;
-  g_message("place %s state: %s", NSTR(place->name), place_state_str(s));
-}
-
-
-static void place_free(struct mwPlace *place) {
-  struct mwServicePlace *srvc;
-
-  if(! place) return;
-  
-  srvc = place->service;
-  g_return_if_fail(srvc != NULL);
-
-  srvc->places = g_list_remove_all(srvc->places, place);
-
-  mw_datum_clear(&place->client_data);
-
-  g_hash_table_destroy(place->members);
-
-  g_free(place->name);
-  g_free(place->title);
-  g_free(place);
-}
-
-
-static int recv_JOIN_RESPONSE(struct mwPlace *place,
-			      struct mwGetBuffer *b) {
-  
-  int ret = 0;
-  guint32 our_id, section;
-
-  guint32_get(b, &our_id);
-  guint32_get(b, &section);
-
-  place->our_id = our_id;
-  place->section = section;
-
-  return ret;
-}
-
-
-static int send_SECTION_LIST(struct mwPlace *place, guint32 section) {
-  int ret = 0;
-  struct mwOpaque o = {0, 0};
-  struct mwPutBuffer *b;
-
-  b = mwPutBuffer_new();
-  guint16_put(b, msg_out_SECTION_LIST);
-  guint32_put(b, section);
-  gboolean_put(b, FALSE);
-  guint32_put(b, ++place->requests);
-  mwPutBuffer_finalize(&o, b);
-
-  ret = mwChannel_send(place->channel, msg_out_SECTION, &o);
-  mwOpaque_clear(&o);
-
-  return ret;
-}
-
-
-static int recv_INFO(struct mwPlace *place,
-		     struct mwGetBuffer *b) {
-
-  int ret = 0;
-  guint32 skip = 0;
-  guint32 section = 0;
-
-  guint32_get(b, &skip);
-  guint32_get(b, &section);
-  mwGetBuffer_advance(b, skip);
-
-  if(! section) {
-    /* this is a place info rather than member info */
-    if(place->title) g_free(place->title);
-    mwGetBuffer_advance(b, 2);
-    mwString_get(b, &place->title);
-
-    place_state(place, mwPlace_JOINED);
-    ret = send_SECTION_LIST(place, place->section);
-  }
-
-  return ret;
-}
-
-
-static int recv_MESSAGE(struct mwPlace *place,
-			struct mwGetBuffer *b) {
-
-  struct mwServicePlace *srvc;
-  guint32 pm_id;
-  guint32 unkn_a, unkn_b, ign;
-  struct place_member *pm;
-  char *msg = NULL;
-  int ret = 0;
-
-  srvc = place->service;
-
-  /* no messages before becoming fully open, please */
-  g_return_val_if_fail(place->state == mwPlace_OPEN, -1);
-
-  /* regarding unkn_a and unkn_b:
-
-     they're probably a section indicator and a message count, I'm
-     just not sure which is which. Until this implementation supports
-     place sections in the API, it really doesn't matter. */
-  
-  guint32_get(b, &pm_id);
-  pm = GET_MEMBER(place, pm_id);
-  g_return_val_if_fail(pm != NULL, -1);
-
-  guint32_get(b, &unkn_a);
-  guint32_get(b, &ign);     /* actually an opaque length */
-  
-  if(! ign) return ret;
-
-  guint32_get(b, &unkn_b);
-  mwString_get(b, &msg);
-
-  if(srvc->handler && srvc->handler->message)
-    srvc->handler->message(place, &pm->idb, msg);
-
-  g_free(msg);
-
-  return ret;
-}
-
-
-static void place_opened(struct mwPlace *place) {
-    struct mwServicePlace *srvc;
-
-    place_state(place, mwPlace_OPEN);
-
-    srvc = place->service;
-    if(srvc->handler && srvc->handler->opened)
-      srvc->handler->opened(place);
-}
-
-
-static int recv_SECTION_PEER_JOIN(struct mwPlace *place,
-				  struct mwGetBuffer *b) {
-  struct mwServicePlace *srvc;
-  struct place_member *pm;
-  guint32 section;
-  int ret = 0;
-
-  srvc = place->service;
-
-  guint32_get(b, &section);
-  if(! section) {
-    g_info("SECTION_PEER_JOIN with section 0x00");
-    return 0;
-  }
-
-  mwGetBuffer_advance(b, 4);
-
-  pm = g_new0(struct place_member, 1);
-  guint32_get(b, &pm->place_id);
-  guint16_get(b, &pm->member_type);
-  mwIdBlock_get(b, &pm->idb);
-  mwString_get(b, &pm->login_id);
-  mwString_get(b, &pm->name);
-  guint16_get(b, &pm->login_type);
-  guint32_get(b, &pm->unknown_a);
-  guint32_get(b, &pm->unknown_b);
-
-  PUT_MEMBER(place, pm);
-  if(srvc->handler && srvc->handler->peerJoined)
-    srvc->handler->peerJoined(place, &pm->idb);
-
-  if(pm->place_id == place->our_id)
-    place_opened(place);
-
-  return ret;
-}
-
-
-static int recv_SECTION_PEER_PART(struct mwPlace *place,
-				  struct mwGetBuffer *b) {
-  struct mwServicePlace *srvc;
-  int ret = 0;
-  guint32 section, id;
-  struct place_member *pm;
-
-  srvc = place->service;
-
-  guint32_get(b, &section);
-  g_return_val_if_fail(section == place->section, 0);
-
-  guint32_get(b, &id);
-  pm = GET_MEMBER(place, id);
-
-  /* SECTION_PART may have been called already */
-  if(! pm) return 0;
-
-  if(srvc->handler && srvc->handler->peerParted)
-    srvc->handler->peerParted(place, &pm->idb);
-
-  REMOVE_MEMBER(place, pm);
-
-  return ret;
-}
-
-
-static int recv_SECTION_PEER_CLEAR_ATTR(struct mwPlace *place,
-					struct mwGetBuffer *b) {
-  struct mwServicePlace *srvc;
-  int ret = 0;
-  guint32 id, attr;
-  struct place_member *pm;
-  
-  srvc = place->service;
-
-  guint32_get(b, &id);
-  guint32_get(b, &attr);
-
-  pm = GET_MEMBER(place, id);
-  g_return_val_if_fail(pm != NULL, -1);
-
-  if(srvc->handler && srvc->handler->peerUnsetAttribute)
-    srvc->handler->peerUnsetAttribute(place, &pm->idb, attr);
-
-  return ret;
-}
-
-
-static int recv_SECTION_PEER_SET_ATTR(struct mwPlace *place,
-				      struct mwGetBuffer *b) {
-  struct mwServicePlace *srvc;
-  int ret = 0;
-  guint32 id, attr;
-  struct mwOpaque o = {0,0};
-  struct place_member *pm;
-  
-  srvc = place->service;
-
-  guint32_get(b, &id);
-  mwGetBuffer_advance(b, 4);
-  mwOpaque_get(b, &o);
-  mwGetBuffer_advance(b, 4);
-  guint32_get(b, &attr);
-
-  pm = GET_MEMBER(place, id);
-  g_return_val_if_fail(pm != NULL, -1);
-
-  if(srvc->handler && srvc->handler->peerSetAttribute)
-    srvc->handler->peerSetAttribute(place, &pm->idb, attr, &o);
-
-  mwOpaque_clear(&o);
-
-  return ret;
-}
-
-
-static int recv_SECTION_PEER(struct mwPlace *place,
-			      struct mwGetBuffer *b) {
-  guint16 subtype;
-  int res;
-
-  guint16_get(b, &subtype);
-
-  g_return_val_if_fail(! mwGetBuffer_error(b), -1);
-
-  switch(subtype) {
-  case msg_in_SECTION_PEER_JOIN:
-    res = recv_SECTION_PEER_JOIN(place, b);
-    break;
-
-  case msg_in_SECTION_PEER_PART:
-    res = recv_SECTION_PEER_PART(place, b);
-    break;
-
-  case msg_in_SECTION_PEER_CLEAR_ATTR:
-    res = recv_SECTION_PEER_CLEAR_ATTR(place, b);
-    break;
-
-  case msg_in_SECTION_PEER_SET_ATTR:
-    res = recv_SECTION_PEER_SET_ATTR(place, b);
-    break;
-
-  default:
-    res = -1;
-  }
-
-  return res;
-}
-
-
-static int recv_SECTION_LIST(struct mwPlace *place,
-			     struct mwGetBuffer *b) {
-  int ret = 0;
-  guint32 sec, count;
-
-  mwGetBuffer_advance(b, 4);
-  guint32_get(b, &sec);
-
-  g_return_val_if_fail(sec == place->section, -1);
-
-  mwGetBuffer_advance(b, 8);
-  guint32_get(b, &count);
-  mwGetBuffer_advance(b, 8);
-
-  while(count--) {
-    struct place_member *m;
-
-    m = g_new0(struct place_member, 1);
-    mwGetBuffer_advance(b, 4);
-    guint32_get(b, &m->place_id);
-    guint16_get(b, &m->member_type);
-    mwIdBlock_get(b, &m->idb);
-    mwString_get(b, &m->login_id);
-    mwString_get(b, &m->name);
-    guint16_get(b, &m->login_type);
-    guint32_get(b, &m->unknown_a);
-    guint32_get(b, &m->unknown_b);
-
-    PUT_MEMBER(place, m);
-  }
-
-  if(place->state != mwPlace_OPEN)
-    place_opened(place);
-
-  return ret;
-}
-
-
-static int recv_SECTION_PART(struct mwPlace *place,
-			     struct mwGetBuffer *b) {
-  /* look up user in place
-     remove user from place
-     trigger event */
-
-  struct mwServicePlace *srvc;
-  guint32 pm_id;
-  struct place_member *pm;
-
-  srvc = place->service;
-
-  guint32_get(b, &pm_id);
-  pm = GET_MEMBER(place, pm_id);
-
-  /* SECTION_PEER_PART may have been called already */
-  if(! pm) return 0;
-
-  if(srvc->handler && srvc->handler->peerParted)
-    srvc->handler->peerParted(place, &pm->idb);
-
-  REMOVE_MEMBER(place, pm);
-
-  return 0;
-}
-
-
-static int recv_SECTION(struct mwPlace *place, struct mwGetBuffer *b) {
-  guint16 subtype;
-  int res;
-
-  guint16_get(b, &subtype);
-
-  g_return_val_if_fail(! mwGetBuffer_error(b), -1);
-
-  switch(subtype) {
-  case msg_in_SECTION_LIST:
-    res = recv_SECTION_LIST(place, b);
-    break;
-
-  case msg_in_SECTION_PEER:
-    res = recv_SECTION_PEER(place, b);
-    break;
-
-  case msg_in_SECTION_PART:
-    res = recv_SECTION_PART(place, b);
-    break;
-
-  default:
-    res = -1;
-  }
-
-  return res;
-}
-
-
-static int recv_UNKNOWNa(struct mwPlace *place, struct mwGetBuffer *b) {
-  int res = 0;
-
-  if(place->state == mwPlace_JOINING) {
-    ;
-    /* place_state(place, mwPlace_JOINED);
-       res = send_SECTION_LIST(place, place->section); */
-  
-  } else if(place->state == mwPlace_JOINED) {
-    ;
-    /* if(GET_MEMBER(place, place->our_id))
-       place_opened(place); */
-  }
-
-  return res;
-}
-
-
-static void recv(struct mwService *service, struct mwChannel *chan,
-		 guint16 type, struct mwOpaque *data) {
-
-  struct mwPlace *place;
-  struct mwGetBuffer *b;
-  int res = 0;
-
-  place = mwChannel_getServiceData(chan);
-  g_return_if_fail(place != NULL);
-
-  b = mwGetBuffer_wrap(data);
-  switch(type) {
-  case msg_in_JOIN_RESPONSE:
-    res = recv_JOIN_RESPONSE(place, b);
-    break;
-
-  case msg_in_INFO:
-    res = recv_INFO(place, b);
-    break;
-
-  case msg_in_MESSAGE:
-    res = recv_MESSAGE(place, b);
-    break;
-
-  case msg_in_SECTION:
-    res = recv_SECTION(place, b);
-    break;
-
-  case msg_in_UNKNOWNa:
-    res = recv_UNKNOWNa(place, b);
-    break;
-
-  default:
-    mw_mailme_opaque(data, "Received unknown message type 0x%x on place %s",
-		     type, NSTR(place->name));
-  }
-
-  if(res) {
-    mw_mailme_opaque(data, "Troubling parsing message type 0x0%x on place %s",
-		     type, NSTR(place->name));
-  }
-
-  mwGetBuffer_free(b);
-}
-
-
-static void stop(struct mwServicePlace *srvc) {
-  while(srvc->places)
-    mwPlace_destroy(srvc->places->data, ERR_SUCCESS);
-
-  mwService_stopped(MW_SERVICE(srvc));
-}
-
-
-static int send_JOIN_PLACE(struct mwPlace *place) {
-  struct mwOpaque o = {0, 0};
-  struct mwPutBuffer *b;
-  int ret;
-
-  b = mwPutBuffer_new();
-  gboolean_put(b, FALSE);
-  guint16_put(b, 0x01);
-  guint16_put(b, 0x02); /* 0x01 */
-  guint16_put(b, 0x01); /* 0x00 */
-
-  mwPutBuffer_finalize(&o, b);
-
-  ret = mwChannel_send(place->channel, msg_out_JOIN_PLACE, &o);
-
-  mwOpaque_clear(&o);
-
-  if(ret) {
-    place_state(place, mwPlace_ERROR);
-  } else {
-    place_state(place, mwPlace_JOINING);
-  }
-
-  return ret;
-}
-
-
-static void recv_channelAccept(struct mwService *service,
-			       struct mwChannel *chan,
-			       struct mwMsgChannelAccept *msg) {
-  struct mwServicePlace *srvc;
-  struct mwPlace *place;
-  int res;
-
-  srvc = (struct mwServicePlace *) service;
-  g_return_if_fail(srvc != NULL);
-
-  place = mwChannel_getServiceData(chan);
-  g_return_if_fail(place != NULL);
-
-  res = send_JOIN_PLACE(place);
-}
-
-
-static void recv_channelDestroy(struct mwService *service,
-				struct mwChannel *chan,
-				struct mwMsgChannelDestroy *msg) {
-  struct mwServicePlace *srvc;
-  struct mwPlace *place;
-
-  srvc = (struct mwServicePlace *) service;
-  g_return_if_fail(srvc != NULL);
-
-  place = mwChannel_getServiceData(chan);
-  g_return_if_fail(place != NULL);
-
-  place_state(place, mwPlace_ERROR);
-
-  place->channel = NULL;
-
-  if(srvc->handler && srvc->handler->closed)
-    srvc->handler->closed(place, msg->reason);  
-
-  mwPlace_destroy(place, msg->reason);
-}
-
-
-static void clear(struct mwServicePlace *srvc) {
-
-  if(srvc->handler && srvc->handler->clear)
-    srvc->handler->clear(srvc);
-
-  while(srvc->places)
-    place_free(srvc->places->data);
-}
-
-
-static const char *get_name(struct mwService *srvc) {
-  return "Places Conferencing";
-}
-
-
-static const char *get_desc(struct mwService *srvc) {
-  return "Barebones conferencing via Places";
-}
-
-
-struct mwServicePlace *
-mwServicePlace_new(struct mwSession *session,
-		   struct mwPlaceHandler *handler) {
-
-  struct mwServicePlace *srvc_place;
-  struct mwService *srvc;
-
-  g_return_val_if_fail(session != NULL, NULL);
-  g_return_val_if_fail(handler != NULL, NULL);
-
-  srvc_place = g_new0(struct mwServicePlace, 1);
-  srvc_place->handler = handler;
-
-  srvc = MW_SERVICE(srvc_place);
-  mwService_init(srvc, session, mwService_PLACE);
-  srvc->start = NULL;
-  srvc->stop = (mwService_funcStop) stop;
-  srvc->recv_create = NULL;
-  srvc->recv_accept = recv_channelAccept;
-  srvc->recv_destroy = recv_channelDestroy;
-  srvc->recv = recv;
-  srvc->clear = (mwService_funcClear) clear;
-  srvc->get_name = get_name;
-  srvc->get_desc = get_desc;
-
-  return srvc_place;
-}
-
-
-struct mwPlaceHandler *
-mwServicePlace_getHandler(struct mwServicePlace *srvc) {
-  g_return_val_if_fail(srvc != NULL, NULL);
-  return srvc->handler;
-}
-
-
-const GList *mwServicePlace_getPlaces(struct mwServicePlace *srvc) {
-  g_return_val_if_fail(srvc != NULL, NULL);
-  return srvc->places;
-}
-
-
-struct mwPlace *mwPlace_new(struct mwServicePlace *srvc,
-			    const char *name, const char *title) {
-  struct mwPlace *place;
-
-  g_return_val_if_fail(srvc != NULL, NULL);
-  
-  place = g_new0(struct mwPlace, 1);
-  place->service = srvc;
-  place->name = g_strdup(name);
-  place->title = g_strdup(title);
-  place->state = mwPlace_NEW;
-
-  place->members = g_hash_table_new_full(g_direct_hash, g_direct_equal,
-					 NULL, (GDestroyNotify) member_free);
-
-  srvc->places = g_list_prepend(srvc->places, place);
-  
-  return place;
-}
-
-
-struct mwServicePlace *mwPlace_getService(struct mwPlace *place) {
-  g_return_val_if_fail(place != NULL, NULL);
-  return place->service;
-}
-
-
-static char *place_generate_name(const char *user) {
-  guint a, b;
-  char *ret;
-  
-  user = user? user: "meanwhile";
-
-  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;
-}
-
-
-const char *mwPlace_getName(struct mwPlace *place) {
-  g_return_val_if_fail(place != NULL, NULL);
-
-  if(! place->name) {
-    struct mwSession *session;
-    struct mwLoginInfo *li;
-
-    session = mwService_getSession(MW_SERVICE(place->service));
-    li = mwSession_getLoginInfo(session);
-
-    place->name = place_generate_name(li? li->user_id: NULL);
-  }
-
-  return place->name;
-}
-
-
-static char *place_generate_title(const char *user) {
-  char *ret;
-  
-  user = user? user: "Meanwhile";
-  ret = g_strdup_printf("%s's Conference", user);
-  g_debug("generated conference title: %s", ret);
-
-  return ret;
-}
-
-
-const char *mwPlace_getTitle(struct mwPlace *place) {
-  g_return_val_if_fail(place != NULL, NULL);
-
-  if(! place->title) {
-    struct mwSession *session;
-    struct mwLoginInfo *li;
-
-    session = mwService_getSession(MW_SERVICE(place->service));
-    li = mwSession_getLoginInfo(session);
-
-    place->title = place_generate_title(li? li->user_name: NULL);
-  }
-
-  return place->title;
-}
-
-
-int mwPlace_open(struct mwPlace *p) {
-  struct mwSession *session;
-  struct mwChannelSet *cs;
-  struct mwChannel *chan;
-  struct mwPutBuffer *b;
-  int ret;
-
-  g_return_val_if_fail(p != NULL, -1);
-  g_return_val_if_fail(p->service != NULL, -1);
-
-  session = mwService_getSession(MW_SERVICE(p->service));
-  g_return_val_if_fail(session != NULL, -1);
-
-  cs = mwSession_getChannels(session);
-  g_return_val_if_fail(cs != NULL, -1);
-
-  chan = mwChannel_newOutgoing(cs);
-  mwChannel_setService(chan, MW_SERVICE(p->service));
-  mwChannel_setProtoType(chan, PROTOCOL_TYPE);
-  mwChannel_setProtoVer(chan, PROTOCOL_VER);
-
-  mwChannel_populateSupportedCipherInstances(chan);
-
-  b = mwPutBuffer_new();
-  mwString_put(b, mwPlace_getName(p));
-  mwString_put(b, mwPlace_getTitle(p));
-  guint32_put(b, 0x00); /* ? */
-
-  mwPutBuffer_finalize(mwChannel_getAddtlCreate(chan), b);
-
-  ret = mwChannel_create(chan);
-  if(ret) {
-    place_state(p, mwPlace_ERROR);
-  } else {
-    place_state(p, mwPlace_PENDING);
-    p->channel = chan;
-    mwChannel_setServiceData(chan, p, NULL);
-  }
-
-  return ret;
-}
-
-
-int mwPlace_destroy(struct mwPlace *p, guint32 code) {
-  int ret = 0;
-
-  place_state(p, mwPlace_CLOSING);
-
-  if(p->channel) {
-    ret = mwChannel_destroy(p->channel, code, NULL);
-    p->channel = NULL;
-  }
-
-  place_free(p);
-
-  return ret;
-}
-
-
-GList *mwPlace_getMembers(struct mwPlace *place) {
-  GList *l, *ll;
-
-  g_return_val_if_fail(place != NULL, NULL);
-  g_return_val_if_fail(place->members != NULL, NULL);
-
-  ll = map_collect_values(place->members);
-  for(l = ll; l; l = l->next) {
-    struct place_member *pm = l->data;
-    l->data = &pm->idb;
-    g_info("collected member %u: %s, %s", pm->place_id,
-	   NSTR(pm->idb.user), NSTR(pm->idb.community));
-  }
-
-  return ll;
-}
-
-
-int mwPlace_sendText(struct mwPlace *place, const char *msg) {
-  struct mwOpaque o = {0,0};
-  struct mwPutBuffer *b;
-  int ret;
-
-  b = mwPutBuffer_new();
-  guint32_put(b, 0x01);  /* probably a message type */
-  mwString_put(b, msg);
-  mwPutBuffer_finalize(&o, b);
-
-  b = mwPutBuffer_new();
-  guint32_put(b, place->section);
-  mwOpaque_put(b, &o);
-  mwOpaque_clear(&o);
-  mwPutBuffer_finalize(&o, b);
-
-  ret = mwChannel_send(place->channel, msg_out_MESSAGE, &o);
-  mwOpaque_clear(&o);
-  return ret;
-}
-
-
-int mwPlace_legacyInvite(struct mwPlace *place,
-			 struct mwIdBlock *idb,
-			 const char *message) {
-
-  struct mwOpaque o = {0,0};
-  struct mwPutBuffer *b;
-  int ret;
-
-  b = mwPutBuffer_new();
-  mwIdBlock_put(b, idb);
-  mwString_put(b, idb->user);
-  mwString_put(b, idb->user);
-  mwString_put(b, message);
-  gboolean_put(b, FALSE);
-  mwPutBuffer_finalize(&o, b);
-
-  ret = mwChannel_send(place->channel, msg_out_OLD_INVITE, &o);
-  mwOpaque_clear(&o);
-  return ret;
-}
-
-
-int mwPlace_setAttribute(struct mwPlace *place, guint32 attrib,
-			 struct mwOpaque *data) {
-
-  struct mwOpaque o = {0,0};
-  struct mwPutBuffer *b;
-  int ret;
-
-  b = mwPutBuffer_new();
-  guint32_put(b, place->our_id);
-  guint32_put(b, 0x00);
-  guint32_put(b, attrib);
-  mwOpaque_put(b, data);
-  
-  ret = mwChannel_send(place->channel, msg_out_SET_ATTR, &o);
-  mwOpaque_clear(&o);
-  return ret;
-}
-
-
-int mwPlace_unsetAttribute(struct mwPlace *place, guint32 attrib) {
-  struct mwOpaque o = {0,0};
-  struct mwPutBuffer *b;
-  int ret;
-
-  b = mwPutBuffer_new();
-  guint32_put(b, place->our_id);
-  guint32_put(b, attrib);
-  
-  ret = mwChannel_send(place->channel, msg_out_SET_ATTR, &o);
-  mwOpaque_clear(&o);
-  return ret;
-}
-
-
-void mwPlace_setClientData(struct mwPlace *place,
-			   gpointer data, GDestroyNotify clear) {
-
-  g_return_if_fail(place != NULL);
-  mw_datum_set(&place->client_data, data, clear);
-}
-
-
-gpointer mwPlace_getClientData(struct mwPlace *place) {
-  g_return_val_if_fail(place != NULL, NULL);
-  return mw_datum_get(&place->client_data);
-}
-
-
-void mwPlace_removeClientData(struct mwPlace *place) {
-  g_return_if_fail(place != NULL);
-  mw_datum_clear(&place->client_data);
-}

mercurial