Blame src/srvc_place.c

Packit Service 37472d
Packit Service 37472d
/*
Packit Service 37472d
  Meanwhile - Unofficial Lotus Sametime Community Client Library
Packit Service 37472d
  Copyright (C) 2004  Christopher (siege) O'Brien
Packit Service 37472d
  
Packit Service 37472d
  This library is free software; you can redistribute it and/or
Packit Service 37472d
  modify it under the terms of the GNU Library General Public
Packit Service 37472d
  License as published by the Free Software Foundation; either
Packit Service 37472d
  version 2 of the License, or (at your option) any later version.
Packit Service 37472d
  
Packit Service 37472d
  This library is distributed in the hope that it will be useful,
Packit Service 37472d
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 37472d
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 37472d
  Library General Public License for more details.
Packit Service 37472d
  
Packit Service 37472d
  You should have received a copy of the GNU Library General Public
Packit Service 37472d
  License along with this library; if not, write to the Free
Packit Service 37472d
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Packit Service 37472d
*/
Packit Service 37472d
Packit Service 37472d
#include <glib.h>
Packit Service 37472d
Packit Service 37472d
#include <stdio.h>
Packit Service 37472d
#include <stdlib.h>
Packit Service 37472d
Packit Service 37472d
#include "mw_channel.h"
Packit Service 37472d
#include "mw_common.h"
Packit Service 37472d
#include "mw_debug.h"
Packit Service 37472d
#include "mw_error.h"
Packit Service 37472d
#include "mw_message.h"
Packit Service 37472d
#include "mw_service.h"
Packit Service 37472d
#include "mw_session.h"
Packit Service 37472d
#include "mw_srvc_place.h"
Packit Service 37472d
#include "mw_util.h"
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
#define PROTOCOL_TYPE  0x00
Packit Service 37472d
#define PROTOCOL_VER   0x05
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
enum incoming_msg {
Packit Service 37472d
  msg_in_JOIN_RESPONSE  = 0x0000,  /* ? */
Packit Service 37472d
  msg_in_INFO           = 0x0002,
Packit Service 37472d
  msg_in_MESSAGE        = 0x0004,
Packit Service 37472d
  msg_in_SECTION        = 0x0014,  /* see in_section_subtype */
Packit Service 37472d
  msg_in_UNKNOWNa       = 0x0015,
Packit Service 37472d
};
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
enum in_section_subtype {
Packit Service 37472d
  msg_in_SECTION_LIST  = 0x0000,  /* list of section members */
Packit Service 37472d
  msg_in_SECTION_PEER  = 0x0001,  /* see in_section_peer_subtye */
Packit Service 37472d
  msg_in_SECTION_PART  = 0x0003,
Packit Service 37472d
};
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
enum in_section_peer_subtype {
Packit Service 37472d
  msg_in_SECTION_PEER_JOIN        = 0x0000,
Packit Service 37472d
  msg_in_SECTION_PEER_PART        = 0x0001,  /* after msg_in_SECTION_PART */
Packit Service 37472d
  msg_in_SECTION_PEER_CLEAR_ATTR  = 0x0003,
Packit Service 37472d
  msg_in_SECTION_PEER_SET_ATTR    = 0x0004,
Packit Service 37472d
};
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
enum outgoing_msg {
Packit Service 37472d
  msg_out_JOIN_PLACE  = 0x0000,  /* ? */
Packit Service 37472d
  msg_out_PEER_INFO   = 0x0002,  /* ? */
Packit Service 37472d
  msg_out_MESSAGE     = 0x0003,
Packit Service 37472d
  msg_out_OLD_INVITE  = 0x0005,  /* old-style conf. invitation */
Packit Service 37472d
  msg_out_SET_ATTR    = 0x000a,
Packit Service 37472d
  msg_out_CLEAR_ATTR  = 0x000b,
Packit Service 37472d
  msg_out_SECTION     = 0x0014,  /* see out_section_subtype */
Packit Service 37472d
  msg_out_UNKNOWNb    = 0x001e,  /* ? maybe enter stage ? */
Packit Service 37472d
};
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
enum out_section_subtype {
Packit Service 37472d
  msg_out_SECTION_LIST  = 0x0002,  /* req list of members */
Packit Service 37472d
  msg_out_SECTION_PART  = 0x0003,
Packit Service 37472d
};
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/*
Packit Service 37472d
  : allocate section
Packit Service 37472d
  : state = NEW
Packit Service 37472d
Packit Service 37472d
  : create channel
Packit Service 37472d
  : state = PENDING
Packit Service 37472d
Packit Service 37472d
  : channel accepted
Packit Service 37472d
  : msg_out_JOIN_PLACE  (maybe create?)
Packit Service 37472d
  : state = JOINING
Packit Service 37472d
Packit Service 37472d
  : msg_in_JOIN_RESPONSE (contains our place member ID and section ID)
Packit Service 37472d
  : msg_in_INFO (for place, not peer)
Packit Service 37472d
  : state = JOINED
Packit Service 37472d
Packit Service 37472d
  : msg_out_SECTION_LIST (asking for all sections) (optional)
Packit Service 37472d
  : msg_in_SECTION_LIST (listing all sections, as requested above)
Packit Service 37472d
Packit Service 37472d
  : msg_out_PEER_INFO (with our place member ID) (optional)
Packit Service 37472d
  : msg_in_INFO (peer info as requested above)
Packit Service 37472d
Packit Service 37472d
  : msg_out_SECTION_LIST (with our section ID) (sorta optional)
Packit Service 37472d
  : msg_in_SECTION_LIST (section listing as requested above)
Packit Service 37472d
Packit Service 37472d
  : msg_out_UNKNOWNb
Packit Service 37472d
  : msg_in_SECTION_PEER_JOINED (empty, with our place member ID)
Packit Service 37472d
  : state = OPEN
Packit Service 37472d
Packit Service 37472d
  : stuff... (invites, joins, parts, messages, attr)
Packit Service 37472d
Packit Service 37472d
  : state = CLOSING
Packit Service 37472d
  : msg_out_SECTION_PART
Packit Service 37472d
  : destroy channel
Packit Service 37472d
  : deallocate section
Packit Service 37472d
*/
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
struct mwServicePlace {
Packit Service 37472d
  struct mwService service;
Packit Service 37472d
  struct mwPlaceHandler *handler;
Packit Service 37472d
  GList *places;
Packit Service 37472d
};
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
enum mwPlaceState {
Packit Service 37472d
  mwPlace_NEW,
Packit Service 37472d
  mwPlace_PENDING,
Packit Service 37472d
  mwPlace_JOINING,
Packit Service 37472d
  mwPlace_JOINED,
Packit Service 37472d
  mwPlace_OPEN,
Packit Service 37472d
  mwPlace_CLOSING,
Packit Service 37472d
  mwPlace_ERROR,
Packit Service 37472d
  mwPlace_UNKNOWN,
Packit Service 37472d
};
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
struct mwPlace {
Packit Service 37472d
  struct mwServicePlace *service;
Packit Service 37472d
Packit Service 37472d
  enum mwPlaceState state;
Packit Service 37472d
  struct mwChannel *channel;
Packit Service 37472d
Packit Service 37472d
  char *name;
Packit Service 37472d
  char *title;
Packit Service 37472d
  GHashTable *members;  /* mapping of member ID: place_member */
Packit Service 37472d
  guint32 our_id;       /* our member ID */
Packit Service 37472d
  guint32 section;      /* the section we're using */
Packit Service 37472d
Packit Service 37472d
  guint32 requests;     /* counter for requests */
Packit Service 37472d
Packit Service 37472d
  struct mw_datum client_data;
Packit Service 37472d
};
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
struct place_member {
Packit Service 37472d
  guint32 place_id;
Packit Service 37472d
  guint16 member_type;
Packit Service 37472d
  struct mwIdBlock idb;
Packit Service 37472d
  char *login_id;
Packit Service 37472d
  char *name;
Packit Service 37472d
  guint16 login_type;
Packit Service 37472d
  guint32 unknown_a;
Packit Service 37472d
  guint32 unknown_b;
Packit Service 37472d
};
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
#define GET_MEMBER(place, id) \
Packit Service 37472d
  (g_hash_table_lookup(place->members, GUINT_TO_POINTER(id)))
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
#define PUT_MEMBER(place, member) \
Packit Service 37472d
  (g_hash_table_insert(place->members, \
Packit Service 37472d
                       GUINT_TO_POINTER(member->place_id), member))
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
#define REMOVE_MEMBER_ID(place, id) \
Packit Service 37472d
  (g_hash_table_remove(place->members, GUINT_TO_POINTER(id)))
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
#define REMOVE_MEMBER(place, member) \
Packit Service 37472d
  REMOVE_MEMBER_ID(place, member->place_id)
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void member_free(struct place_member *p) {
Packit Service 37472d
  mwIdBlock_clear(&p->idb);
Packit Service 37472d
  g_free(p->login_id);
Packit Service 37472d
  g_free(p->name);
Packit Service 37472d
  g_free(p);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
__attribute__((used))
Packit Service 37472d
static const struct mwLoginInfo *
Packit Service 37472d
member_as_login_info(struct place_member *p) {
Packit Service 37472d
  static struct mwLoginInfo li;
Packit Service 37472d
  
Packit Service 37472d
  li.login_id = p->login_id;
Packit Service 37472d
  li.type = p->login_type;
Packit Service 37472d
  li.user_id = p->idb.user;
Packit Service 37472d
  li.user_name = p->name;
Packit Service 37472d
  li.community = p->idb.community;
Packit Service 37472d
  li.full = FALSE;
Packit Service 37472d
Packit Service 37472d
  return &li;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static const char *place_state_str(enum mwPlaceState s) {
Packit Service 37472d
  switch(s) {
Packit Service 37472d
  case mwPlace_NEW:      return "new";
Packit Service 37472d
  case mwPlace_PENDING:  return "pending";
Packit Service 37472d
  case mwPlace_JOINING:  return "joining";
Packit Service 37472d
  case mwPlace_JOINED:   return "joined";
Packit Service 37472d
  case mwPlace_OPEN:     return "open";
Packit Service 37472d
  case mwPlace_CLOSING:  return "closing";
Packit Service 37472d
  case mwPlace_ERROR:    return "error";
Packit Service 37472d
Packit Service 37472d
  case mwPlace_UNKNOWN:  /* fall-through */
Packit Service 37472d
  default:               return "UNKNOWN";
Packit Service 37472d
  }
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void place_state(struct mwPlace *place, enum mwPlaceState s) {
Packit Service 37472d
  g_return_if_fail(place != NULL);
Packit Service 37472d
  
Packit Service 37472d
  if(place->state == s) return;
Packit Service 37472d
Packit Service 37472d
  place->state = s;
Packit Service 37472d
  g_message("place %s state: %s", NSTR(place->name), place_state_str(s));
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void place_free(struct mwPlace *place) {
Packit Service 37472d
  struct mwServicePlace *srvc;
Packit Service 37472d
Packit Service 37472d
  if(! place) return;
Packit Service 37472d
  
Packit Service 37472d
  srvc = place->service;
Packit Service 37472d
  g_return_if_fail(srvc != NULL);
Packit Service 37472d
Packit Service 37472d
  srvc->places = g_list_remove_all(srvc->places, place);
Packit Service 37472d
Packit Service 37472d
  mw_datum_clear(&place->client_data);
Packit Service 37472d
Packit Service 37472d
  g_hash_table_destroy(place->members);
Packit Service 37472d
Packit Service 37472d
  g_free(place->name);
Packit Service 37472d
  g_free(place->title);
Packit Service 37472d
  g_free(place);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static int recv_JOIN_RESPONSE(struct mwPlace *place,
Packit Service 37472d
			      struct mwGetBuffer *b) {
Packit Service 37472d
  
Packit Service 37472d
  int ret = 0;
Packit Service 37472d
  guint32 our_id, section;
Packit Service 37472d
Packit Service 37472d
  guint32_get(b, &our_id);
Packit Service 37472d
  guint32_get(b, &section);
Packit Service 37472d
Packit Service 37472d
  place->our_id = our_id;
Packit Service 37472d
  place->section = section;
Packit Service 37472d
Packit Service 37472d
  return ret;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static int send_SECTION_LIST(struct mwPlace *place, guint32 section) {
Packit Service 37472d
  int ret = 0;
Packit Service 37472d
  struct mwOpaque o = {0, 0};
Packit Service 37472d
  struct mwPutBuffer *b;
Packit Service 37472d
Packit Service 37472d
  b = mwPutBuffer_new();
Packit Service 37472d
  guint16_put(b, msg_out_SECTION_LIST);
Packit Service 37472d
  guint32_put(b, section);
Packit Service 37472d
  gboolean_put(b, FALSE);
Packit Service 37472d
  guint32_put(b, ++place->requests);
Packit Service 37472d
  mwPutBuffer_finalize(&o, b);
Packit Service 37472d
Packit Service 37472d
  ret = mwChannel_send(place->channel, msg_out_SECTION, &o);
Packit Service 37472d
  mwOpaque_clear(&o);
Packit Service 37472d
Packit Service 37472d
  return ret;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static int recv_INFO(struct mwPlace *place,
Packit Service 37472d
		     struct mwGetBuffer *b) {
Packit Service 37472d
Packit Service 37472d
  int ret = 0;
Packit Service 37472d
  guint32 skip = 0;
Packit Service 37472d
  guint32 section = 0;
Packit Service 37472d
Packit Service 37472d
  guint32_get(b, &skip);
Packit Service 37472d
  guint32_get(b, &section);
Packit Service 37472d
  mwGetBuffer_advance(b, skip);
Packit Service 37472d
Packit Service 37472d
  if(! section) {
Packit Service 37472d
    /* this is a place info rather than member info */
Packit Service 37472d
    if(place->title) g_free(place->title);
Packit Service 37472d
    mwGetBuffer_advance(b, 2);
Packit Service 37472d
    mwString_get(b, &place->title);
Packit Service 37472d
Packit Service 37472d
    place_state(place, mwPlace_JOINED);
Packit Service 37472d
    ret = send_SECTION_LIST(place, place->section);
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  return ret;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static int recv_MESSAGE(struct mwPlace *place,
Packit Service 37472d
			struct mwGetBuffer *b) {
Packit Service 37472d
Packit Service 37472d
  struct mwServicePlace *srvc;
Packit Service 37472d
  guint32 pm_id;
Packit Service 37472d
  guint32 unkn_a, unkn_b, ign;
Packit Service 37472d
  struct place_member *pm;
Packit Service 37472d
  char *msg = NULL;
Packit Service 37472d
  int ret = 0;
Packit Service 37472d
Packit Service 37472d
  srvc = place->service;
Packit Service 37472d
Packit Service 37472d
  /* no messages before becoming fully open, please */
Packit Service 37472d
  g_return_val_if_fail(place->state == mwPlace_OPEN, -1);
Packit Service 37472d
Packit Service 37472d
  /* regarding unkn_a and unkn_b:
Packit Service 37472d
Packit Service 37472d
     they're probably a section indicator and a message count, I'm
Packit Service 37472d
     just not sure which is which. Until this implementation supports
Packit Service 37472d
     place sections in the API, it really doesn't matter. */
Packit Service 37472d
  
Packit Service 37472d
  guint32_get(b, &pm_id);
Packit Service 37472d
  pm = GET_MEMBER(place, pm_id);
Packit Service 37472d
  g_return_val_if_fail(pm != NULL, -1);
Packit Service 37472d
Packit Service 37472d
  guint32_get(b, &unkn_a);
Packit Service 37472d
  guint32_get(b, &ign;;     /* actually an opaque length */
Packit Service 37472d
  
Packit Service 37472d
  if(! ign) return ret;
Packit Service 37472d
Packit Service 37472d
  guint32_get(b, &unkn_b);
Packit Service 37472d
  mwString_get(b, &msg;;
Packit Service 37472d
Packit Service 37472d
  if(srvc->handler && srvc->handler->message)
Packit Service 37472d
    srvc->handler->message(place, &pm->idb, msg);
Packit Service 37472d
Packit Service 37472d
  g_free(msg);
Packit Service 37472d
Packit Service 37472d
  return ret;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void place_opened(struct mwPlace *place) {
Packit Service 37472d
    struct mwServicePlace *srvc;
Packit Service 37472d
Packit Service 37472d
    place_state(place, mwPlace_OPEN);
Packit Service 37472d
Packit Service 37472d
    srvc = place->service;
Packit Service 37472d
    if(srvc->handler && srvc->handler->opened)
Packit Service 37472d
      srvc->handler->opened(place);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static int recv_SECTION_PEER_JOIN(struct mwPlace *place,
Packit Service 37472d
				  struct mwGetBuffer *b) {
Packit Service 37472d
  struct mwServicePlace *srvc;
Packit Service 37472d
  struct place_member *pm;
Packit Service 37472d
  guint32 section;
Packit Service 37472d
  int ret = 0;
Packit Service 37472d
Packit Service 37472d
  srvc = place->service;
Packit Service 37472d
Packit Service 37472d
  guint32_get(b, &section);
Packit Service 37472d
  if(! section) {
Packit Service 37472d
    g_info("SECTION_PEER_JOIN with section 0x00");
Packit Service 37472d
    return 0;
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  mwGetBuffer_advance(b, 4);
Packit Service 37472d
Packit Service 37472d
  pm = g_new0(struct place_member, 1);
Packit Service 37472d
  guint32_get(b, &pm->place_id);
Packit Service 37472d
  guint16_get(b, &pm->member_type);
Packit Service 37472d
  mwIdBlock_get(b, &pm->idb);
Packit Service 37472d
  mwString_get(b, &pm->login_id);
Packit Service 37472d
  mwString_get(b, &pm->name);
Packit Service 37472d
  guint16_get(b, &pm->login_type);
Packit Service 37472d
  guint32_get(b, &pm->unknown_a);
Packit Service 37472d
  guint32_get(b, &pm->unknown_b);
Packit Service 37472d
Packit Service 37472d
  PUT_MEMBER(place, pm);
Packit Service 37472d
  if(srvc->handler && srvc->handler->peerJoined)
Packit Service 37472d
    srvc->handler->peerJoined(place, &pm->idb);
Packit Service 37472d
Packit Service 37472d
  if(pm->place_id == place->our_id)
Packit Service 37472d
    place_opened(place);
Packit Service 37472d
Packit Service 37472d
  return ret;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static int recv_SECTION_PEER_PART(struct mwPlace *place,
Packit Service 37472d
				  struct mwGetBuffer *b) {
Packit Service 37472d
  struct mwServicePlace *srvc;
Packit Service 37472d
  int ret = 0;
Packit Service 37472d
  guint32 section, id;
Packit Service 37472d
  struct place_member *pm;
Packit Service 37472d
Packit Service 37472d
  srvc = place->service;
Packit Service 37472d
Packit Service 37472d
  guint32_get(b, &section);
Packit Service 37472d
  g_return_val_if_fail(section == place->section, 0);
Packit Service 37472d
Packit Service 37472d
  guint32_get(b, &id;;
Packit Service 37472d
  pm = GET_MEMBER(place, id);
Packit Service 37472d
Packit Service 37472d
  /* SECTION_PART may have been called already */
Packit Service 37472d
  if(! pm) return 0;
Packit Service 37472d
Packit Service 37472d
  if(srvc->handler && srvc->handler->peerParted)
Packit Service 37472d
    srvc->handler->peerParted(place, &pm->idb);
Packit Service 37472d
Packit Service 37472d
  REMOVE_MEMBER(place, pm);
Packit Service 37472d
Packit Service 37472d
  return ret;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static int recv_SECTION_PEER_CLEAR_ATTR(struct mwPlace *place,
Packit Service 37472d
					struct mwGetBuffer *b) {
Packit Service 37472d
  struct mwServicePlace *srvc;
Packit Service 37472d
  int ret = 0;
Packit Service 37472d
  guint32 id, attr;
Packit Service 37472d
  struct place_member *pm;
Packit Service 37472d
  
Packit Service 37472d
  srvc = place->service;
Packit Service 37472d
Packit Service 37472d
  guint32_get(b, &id;;
Packit Service 37472d
  guint32_get(b, &attr);
Packit Service 37472d
Packit Service 37472d
  pm = GET_MEMBER(place, id);
Packit Service 37472d
  g_return_val_if_fail(pm != NULL, -1);
Packit Service 37472d
Packit Service 37472d
  if(srvc->handler && srvc->handler->peerUnsetAttribute)
Packit Service 37472d
    srvc->handler->peerUnsetAttribute(place, &pm->idb, attr);
Packit Service 37472d
Packit Service 37472d
  return ret;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static int recv_SECTION_PEER_SET_ATTR(struct mwPlace *place,
Packit Service 37472d
				      struct mwGetBuffer *b) {
Packit Service 37472d
  struct mwServicePlace *srvc;
Packit Service 37472d
  int ret = 0;
Packit Service 37472d
  guint32 id, attr;
Packit Service 37472d
  struct mwOpaque o = {0,0};
Packit Service 37472d
  struct place_member *pm;
Packit Service 37472d
  
Packit Service 37472d
  srvc = place->service;
Packit Service 37472d
Packit Service 37472d
  guint32_get(b, &id;;
Packit Service 37472d
  mwGetBuffer_advance(b, 4);
Packit Service 37472d
  mwOpaque_get(b, &o);
Packit Service 37472d
  mwGetBuffer_advance(b, 4);
Packit Service 37472d
  guint32_get(b, &attr);
Packit Service 37472d
Packit Service 37472d
  pm = GET_MEMBER(place, id);
Packit Service 37472d
  g_return_val_if_fail(pm != NULL, -1);
Packit Service 37472d
Packit Service 37472d
  if(srvc->handler && srvc->handler->peerSetAttribute)
Packit Service 37472d
    srvc->handler->peerSetAttribute(place, &pm->idb, attr, &o);
Packit Service 37472d
Packit Service 37472d
  mwOpaque_clear(&o);
Packit Service 37472d
Packit Service 37472d
  return ret;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static int recv_SECTION_PEER(struct mwPlace *place,
Packit Service 37472d
			      struct mwGetBuffer *b) {
Packit Service 37472d
  guint16 subtype;
Packit Service 37472d
  int res;
Packit Service 37472d
Packit Service 37472d
  guint16_get(b, &subtype);
Packit Service 37472d
Packit Service 37472d
  g_return_val_if_fail(! mwGetBuffer_error(b), -1);
Packit Service 37472d
Packit Service 37472d
  switch(subtype) {
Packit Service 37472d
  case msg_in_SECTION_PEER_JOIN:
Packit Service 37472d
    res = recv_SECTION_PEER_JOIN(place, b);
Packit Service 37472d
    break;
Packit Service 37472d
Packit Service 37472d
  case msg_in_SECTION_PEER_PART:
Packit Service 37472d
    res = recv_SECTION_PEER_PART(place, b);
Packit Service 37472d
    break;
Packit Service 37472d
Packit Service 37472d
  case msg_in_SECTION_PEER_CLEAR_ATTR:
Packit Service 37472d
    res = recv_SECTION_PEER_CLEAR_ATTR(place, b);
Packit Service 37472d
    break;
Packit Service 37472d
Packit Service 37472d
  case msg_in_SECTION_PEER_SET_ATTR:
Packit Service 37472d
    res = recv_SECTION_PEER_SET_ATTR(place, b);
Packit Service 37472d
    break;
Packit Service 37472d
Packit Service 37472d
  default:
Packit Service 37472d
    res = -1;
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  return res;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static int recv_SECTION_LIST(struct mwPlace *place,
Packit Service 37472d
			     struct mwGetBuffer *b) {
Packit Service 37472d
  int ret = 0;
Packit Service 37472d
  guint32 sec, count;
Packit Service 37472d
Packit Service 37472d
  mwGetBuffer_advance(b, 4);
Packit Service 37472d
  guint32_get(b, &sec);
Packit Service 37472d
Packit Service 37472d
  g_return_val_if_fail(sec == place->section, -1);
Packit Service 37472d
Packit Service 37472d
  mwGetBuffer_advance(b, 8);
Packit Service 37472d
  guint32_get(b, &count);
Packit Service 37472d
  mwGetBuffer_advance(b, 8);
Packit Service 37472d
Packit Service 37472d
  while(count--) {
Packit Service 37472d
    struct place_member *m;
Packit Service 37472d
Packit Service 37472d
    m = g_new0(struct place_member, 1);
Packit Service 37472d
    mwGetBuffer_advance(b, 4);
Packit Service 37472d
    guint32_get(b, &m->place_id);
Packit Service 37472d
    guint16_get(b, &m->member_type);
Packit Service 37472d
    mwIdBlock_get(b, &m->idb);
Packit Service 37472d
    mwString_get(b, &m->login_id);
Packit Service 37472d
    mwString_get(b, &m->name);
Packit Service 37472d
    guint16_get(b, &m->login_type);
Packit Service 37472d
    guint32_get(b, &m->unknown_a);
Packit Service 37472d
    guint32_get(b, &m->unknown_b);
Packit Service 37472d
Packit Service 37472d
    PUT_MEMBER(place, m);
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  if(place->state != mwPlace_OPEN)
Packit Service 37472d
    place_opened(place);
Packit Service 37472d
Packit Service 37472d
  return ret;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static int recv_SECTION_PART(struct mwPlace *place,
Packit Service 37472d
			     struct mwGetBuffer *b) {
Packit Service 37472d
  /* look up user in place
Packit Service 37472d
     remove user from place
Packit Service 37472d
     trigger event */
Packit Service 37472d
Packit Service 37472d
  struct mwServicePlace *srvc;
Packit Service 37472d
  guint32 pm_id;
Packit Service 37472d
  struct place_member *pm;
Packit Service 37472d
Packit Service 37472d
  srvc = place->service;
Packit Service 37472d
Packit Service 37472d
  guint32_get(b, &pm_id);
Packit Service 37472d
  pm = GET_MEMBER(place, pm_id);
Packit Service 37472d
Packit Service 37472d
  /* SECTION_PEER_PART may have been called already */
Packit Service 37472d
  if(! pm) return 0;
Packit Service 37472d
Packit Service 37472d
  if(srvc->handler && srvc->handler->peerParted)
Packit Service 37472d
    srvc->handler->peerParted(place, &pm->idb);
Packit Service 37472d
Packit Service 37472d
  REMOVE_MEMBER(place, pm);
Packit Service 37472d
Packit Service 37472d
  return 0;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static int recv_SECTION(struct mwPlace *place, struct mwGetBuffer *b) {
Packit Service 37472d
  guint16 subtype;
Packit Service 37472d
  int res;
Packit Service 37472d
Packit Service 37472d
  guint16_get(b, &subtype);
Packit Service 37472d
Packit Service 37472d
  g_return_val_if_fail(! mwGetBuffer_error(b), -1);
Packit Service 37472d
Packit Service 37472d
  switch(subtype) {
Packit Service 37472d
  case msg_in_SECTION_LIST:
Packit Service 37472d
    res = recv_SECTION_LIST(place, b);
Packit Service 37472d
    break;
Packit Service 37472d
Packit Service 37472d
  case msg_in_SECTION_PEER:
Packit Service 37472d
    res = recv_SECTION_PEER(place, b);
Packit Service 37472d
    break;
Packit Service 37472d
Packit Service 37472d
  case msg_in_SECTION_PART:
Packit Service 37472d
    res = recv_SECTION_PART(place, b);
Packit Service 37472d
    break;
Packit Service 37472d
Packit Service 37472d
  default:
Packit Service 37472d
    res = -1;
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  return res;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static int recv_UNKNOWNa(struct mwPlace *place, struct mwGetBuffer *b) {
Packit Service 37472d
  int res = 0;
Packit Service 37472d
Packit Service 37472d
  if(place->state == mwPlace_JOINING) {
Packit Service 37472d
    ;
Packit Service 37472d
    /* place_state(place, mwPlace_JOINED);
Packit Service 37472d
       res = send_SECTION_LIST(place, place->section); */
Packit Service 37472d
  
Packit Service 37472d
  } else if(place->state == mwPlace_JOINED) {
Packit Service 37472d
    ;
Packit Service 37472d
    /* if(GET_MEMBER(place, place->our_id))
Packit Service 37472d
       place_opened(place); */
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  return res;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void recv(struct mwService *service, struct mwChannel *chan,
Packit Service 37472d
		 guint16 type, struct mwOpaque *data) {
Packit Service 37472d
Packit Service 37472d
  struct mwPlace *place;
Packit Service 37472d
  struct mwGetBuffer *b;
Packit Service 37472d
  int res = 0;
Packit Service 37472d
Packit Service 37472d
  place = mwChannel_getServiceData(chan);
Packit Service 37472d
  g_return_if_fail(place != NULL);
Packit Service 37472d
Packit Service 37472d
  b = mwGetBuffer_wrap(data);
Packit Service 37472d
  switch(type) {
Packit Service 37472d
  case msg_in_JOIN_RESPONSE:
Packit Service 37472d
    res = recv_JOIN_RESPONSE(place, b);
Packit Service 37472d
    break;
Packit Service 37472d
Packit Service 37472d
  case msg_in_INFO:
Packit Service 37472d
    res = recv_INFO(place, b);
Packit Service 37472d
    break;
Packit Service 37472d
Packit Service 37472d
  case msg_in_MESSAGE:
Packit Service 37472d
    res = recv_MESSAGE(place, b);
Packit Service 37472d
    break;
Packit Service 37472d
Packit Service 37472d
  case msg_in_SECTION:
Packit Service 37472d
    res = recv_SECTION(place, b);
Packit Service 37472d
    break;
Packit Service 37472d
Packit Service 37472d
  case msg_in_UNKNOWNa:
Packit Service 37472d
    res = recv_UNKNOWNa(place, b);
Packit Service 37472d
    break;
Packit Service 37472d
Packit Service 37472d
  default:
Packit Service 37472d
    mw_mailme_opaque(data, "Received unknown message type 0x%x on place %s",
Packit Service 37472d
		     type, NSTR(place->name));
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  if(res) {
Packit Service 37472d
    mw_mailme_opaque(data, "Troubling parsing message type 0x0%x on place %s",
Packit Service 37472d
		     type, NSTR(place->name));
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  mwGetBuffer_free(b);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void stop(struct mwServicePlace *srvc) {
Packit Service 37472d
  while(srvc->places)
Packit Service 37472d
    mwPlace_destroy(srvc->places->data, ERR_SUCCESS);
Packit Service 37472d
Packit Service 37472d
  mwService_stopped(MW_SERVICE(srvc));
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static int send_JOIN_PLACE(struct mwPlace *place) {
Packit Service 37472d
  struct mwOpaque o = {0, 0};
Packit Service 37472d
  struct mwPutBuffer *b;
Packit Service 37472d
  int ret;
Packit Service 37472d
Packit Service 37472d
  b = mwPutBuffer_new();
Packit Service 37472d
  gboolean_put(b, FALSE);
Packit Service 37472d
  guint16_put(b, 0x01);
Packit Service 37472d
  guint16_put(b, 0x02); /* 0x01 */
Packit Service 37472d
  guint16_put(b, 0x01); /* 0x00 */
Packit Service 37472d
Packit Service 37472d
  mwPutBuffer_finalize(&o, b);
Packit Service 37472d
Packit Service 37472d
  ret = mwChannel_send(place->channel, msg_out_JOIN_PLACE, &o);
Packit Service 37472d
Packit Service 37472d
  mwOpaque_clear(&o);
Packit Service 37472d
Packit Service 37472d
  if(ret) {
Packit Service 37472d
    place_state(place, mwPlace_ERROR);
Packit Service 37472d
  } else {
Packit Service 37472d
    place_state(place, mwPlace_JOINING);
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  return ret;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void recv_channelAccept(struct mwService *service,
Packit Service 37472d
			       struct mwChannel *chan,
Packit Service 37472d
			       struct mwMsgChannelAccept *msg) {
Packit Service 37472d
  struct mwServicePlace *srvc;
Packit Service 37472d
  struct mwPlace *place;
Packit Service 37472d
  int res;
Packit Service 37472d
Packit Service 37472d
  srvc = (struct mwServicePlace *) service;
Packit Service 37472d
  g_return_if_fail(srvc != NULL);
Packit Service 37472d
Packit Service 37472d
  place = mwChannel_getServiceData(chan);
Packit Service 37472d
  g_return_if_fail(place != NULL);
Packit Service 37472d
Packit Service 37472d
  res = send_JOIN_PLACE(place);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void recv_channelDestroy(struct mwService *service,
Packit Service 37472d
				struct mwChannel *chan,
Packit Service 37472d
				struct mwMsgChannelDestroy *msg) {
Packit Service 37472d
  struct mwServicePlace *srvc;
Packit Service 37472d
  struct mwPlace *place;
Packit Service 37472d
Packit Service 37472d
  srvc = (struct mwServicePlace *) service;
Packit Service 37472d
  g_return_if_fail(srvc != NULL);
Packit Service 37472d
Packit Service 37472d
  place = mwChannel_getServiceData(chan);
Packit Service 37472d
  g_return_if_fail(place != NULL);
Packit Service 37472d
Packit Service 37472d
  place_state(place, mwPlace_ERROR);
Packit Service 37472d
Packit Service 37472d
  place->channel = NULL;
Packit Service 37472d
Packit Service 37472d
  if(srvc->handler && srvc->handler->closed)
Packit Service 37472d
    srvc->handler->closed(place, msg->reason);  
Packit Service 37472d
Packit Service 37472d
  mwPlace_destroy(place, msg->reason);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void clear(struct mwServicePlace *srvc) {
Packit Service 37472d
Packit Service 37472d
  if(srvc->handler && srvc->handler->clear)
Packit Service 37472d
    srvc->handler->clear(srvc);
Packit Service 37472d
Packit Service 37472d
  while(srvc->places)
Packit Service 37472d
    place_free(srvc->places->data);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static const char *get_name(struct mwService *srvc) {
Packit Service 37472d
  return "Places Conferencing";
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static const char *get_desc(struct mwService *srvc) {
Packit Service 37472d
  return "Barebones conferencing via Places";
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
struct mwServicePlace *
Packit Service 37472d
mwServicePlace_new(struct mwSession *session,
Packit Service 37472d
		   struct mwPlaceHandler *handler) {
Packit Service 37472d
Packit Service 37472d
  struct mwServicePlace *srvc_place;
Packit Service 37472d
  struct mwService *srvc;
Packit Service 37472d
Packit Service 37472d
  g_return_val_if_fail(session != NULL, NULL);
Packit Service 37472d
  g_return_val_if_fail(handler != NULL, NULL);
Packit Service 37472d
Packit Service 37472d
  srvc_place = g_new0(struct mwServicePlace, 1);
Packit Service 37472d
  srvc_place->handler = handler;
Packit Service 37472d
Packit Service 37472d
  srvc = MW_SERVICE(srvc_place);
Packit Service 37472d
  mwService_init(srvc, session, mwService_PLACE);
Packit Service 37472d
  srvc->start = NULL;
Packit Service 37472d
  srvc->stop = (mwService_funcStop) stop;
Packit Service 37472d
  srvc->recv_create = NULL;
Packit Service 37472d
  srvc->recv_accept = recv_channelAccept;
Packit Service 37472d
  srvc->recv_destroy = recv_channelDestroy;
Packit Service 37472d
  srvc->recv = recv;
Packit Service 37472d
  srvc->clear = (mwService_funcClear) clear;
Packit Service 37472d
  srvc->get_name = get_name;
Packit Service 37472d
  srvc->get_desc = get_desc;
Packit Service 37472d
Packit Service 37472d
  return srvc_place;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
struct mwPlaceHandler *
Packit Service 37472d
mwServicePlace_getHandler(struct mwServicePlace *srvc) {
Packit Service 37472d
  g_return_val_if_fail(srvc != NULL, NULL);
Packit Service 37472d
  return srvc->handler;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
const GList *mwServicePlace_getPlaces(struct mwServicePlace *srvc) {
Packit Service 37472d
  g_return_val_if_fail(srvc != NULL, NULL);
Packit Service 37472d
  return srvc->places;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
struct mwPlace *mwPlace_new(struct mwServicePlace *srvc,
Packit Service 37472d
			    const char *name, const char *title) {
Packit Service 37472d
  struct mwPlace *place;
Packit Service 37472d
Packit Service 37472d
  g_return_val_if_fail(srvc != NULL, NULL);
Packit Service 37472d
  
Packit Service 37472d
  place = g_new0(struct mwPlace, 1);
Packit Service 37472d
  place->service = srvc;
Packit Service 37472d
  place->name = g_strdup(name);
Packit Service 37472d
  place->title = g_strdup(title);
Packit Service 37472d
  place->state = mwPlace_NEW;
Packit Service 37472d
Packit Service 37472d
  place->members = g_hash_table_new_full(g_direct_hash, g_direct_equal,
Packit Service 37472d
					 NULL, (GDestroyNotify) member_free);
Packit Service 37472d
Packit Service 37472d
  srvc->places = g_list_prepend(srvc->places, place);
Packit Service 37472d
  
Packit Service 37472d
  return place;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
struct mwServicePlace *mwPlace_getService(struct mwPlace *place) {
Packit Service 37472d
  g_return_val_if_fail(place != NULL, NULL);
Packit Service 37472d
  return place->service;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static char *place_generate_name(const char *user) {
Packit Service 37472d
  guint a, b;
Packit Service 37472d
  char *ret;
Packit Service 37472d
  
Packit Service 37472d
  user = user? user: "meanwhile";
Packit Service 37472d
Packit Service 37472d
  srand(clock() + rand());
Packit Service 37472d
  a = ((rand() & 0xff) << 8) | (rand() & 0xff);
Packit Service 37472d
  b = time(NULL);
Packit Service 37472d
Packit Service 37472d
  ret = g_strdup_printf("%s(%08x,%04x)", user, b, a);
Packit Service 37472d
  g_debug("generated random conference name: '%s'", ret);
Packit Service 37472d
  return ret;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
const char *mwPlace_getName(struct mwPlace *place) {
Packit Service 37472d
  g_return_val_if_fail(place != NULL, NULL);
Packit Service 37472d
Packit Service 37472d
  if(! place->name) {
Packit Service 37472d
    struct mwSession *session;
Packit Service 37472d
    struct mwLoginInfo *li;
Packit Service 37472d
Packit Service 37472d
    session = mwService_getSession(MW_SERVICE(place->service));
Packit Service 37472d
    li = mwSession_getLoginInfo(session);
Packit Service 37472d
Packit Service 37472d
    place->name = place_generate_name(li? li->user_id: NULL);
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  return place->name;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static char *place_generate_title(const char *user) {
Packit Service 37472d
  char *ret;
Packit Service 37472d
  
Packit Service 37472d
  user = user? user: "Meanwhile";
Packit Service 37472d
  ret = g_strdup_printf("%s's Conference", user);
Packit Service 37472d
  g_debug("generated conference title: %s", ret);
Packit Service 37472d
Packit Service 37472d
  return ret;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
const char *mwPlace_getTitle(struct mwPlace *place) {
Packit Service 37472d
  g_return_val_if_fail(place != NULL, NULL);
Packit Service 37472d
Packit Service 37472d
  if(! place->title) {
Packit Service 37472d
    struct mwSession *session;
Packit Service 37472d
    struct mwLoginInfo *li;
Packit Service 37472d
Packit Service 37472d
    session = mwService_getSession(MW_SERVICE(place->service));
Packit Service 37472d
    li = mwSession_getLoginInfo(session);
Packit Service 37472d
Packit Service 37472d
    place->title = place_generate_title(li? li->user_name: NULL);
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  return place->title;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
int mwPlace_open(struct mwPlace *p) {
Packit Service 37472d
  struct mwSession *session;
Packit Service 37472d
  struct mwChannelSet *cs;
Packit Service 37472d
  struct mwChannel *chan;
Packit Service 37472d
  struct mwPutBuffer *b;
Packit Service 37472d
  int ret;
Packit Service 37472d
Packit Service 37472d
  g_return_val_if_fail(p != NULL, -1);
Packit Service 37472d
  g_return_val_if_fail(p->service != NULL, -1);
Packit Service 37472d
Packit Service 37472d
  session = mwService_getSession(MW_SERVICE(p->service));
Packit Service 37472d
  g_return_val_if_fail(session != NULL, -1);
Packit Service 37472d
Packit Service 37472d
  cs = mwSession_getChannels(session);
Packit Service 37472d
  g_return_val_if_fail(cs != NULL, -1);
Packit Service 37472d
Packit Service 37472d
  chan = mwChannel_newOutgoing(cs);
Packit Service 37472d
  mwChannel_setService(chan, MW_SERVICE(p->service));
Packit Service 37472d
  mwChannel_setProtoType(chan, PROTOCOL_TYPE);
Packit Service 37472d
  mwChannel_setProtoVer(chan, PROTOCOL_VER);
Packit Service 37472d
Packit Service 37472d
  mwChannel_populateSupportedCipherInstances(chan);
Packit Service 37472d
Packit Service 37472d
  b = mwPutBuffer_new();
Packit Service 37472d
  mwString_put(b, mwPlace_getName(p));
Packit Service 37472d
  mwString_put(b, mwPlace_getTitle(p));
Packit Service 37472d
  guint32_put(b, 0x00); /* ? */
Packit Service 37472d
Packit Service 37472d
  mwPutBuffer_finalize(mwChannel_getAddtlCreate(chan), b);
Packit Service 37472d
Packit Service 37472d
  ret = mwChannel_create(chan);
Packit Service 37472d
  if(ret) {
Packit Service 37472d
    place_state(p, mwPlace_ERROR);
Packit Service 37472d
  } else {
Packit Service 37472d
    place_state(p, mwPlace_PENDING);
Packit Service 37472d
    p->channel = chan;
Packit Service 37472d
    mwChannel_setServiceData(chan, p, NULL);
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  return ret;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
int mwPlace_destroy(struct mwPlace *p, guint32 code) {
Packit Service 37472d
  int ret = 0;
Packit Service 37472d
Packit Service 37472d
  place_state(p, mwPlace_CLOSING);
Packit Service 37472d
Packit Service 37472d
  if(p->channel) {
Packit Service 37472d
    ret = mwChannel_destroy(p->channel, code, NULL);
Packit Service 37472d
    p->channel = NULL;
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  place_free(p);
Packit Service 37472d
Packit Service 37472d
  return ret;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
GList *mwPlace_getMembers(struct mwPlace *place) {
Packit Service 37472d
  GList *l, *ll;
Packit Service 37472d
Packit Service 37472d
  g_return_val_if_fail(place != NULL, NULL);
Packit Service 37472d
  g_return_val_if_fail(place->members != NULL, NULL);
Packit Service 37472d
Packit Service 37472d
  ll = map_collect_values(place->members);
Packit Service 37472d
  for(l = ll; l; l = l->next) {
Packit Service 37472d
    struct place_member *pm = l->data;
Packit Service 37472d
    l->data = &pm->idb;
Packit Service 37472d
    g_info("collected member %u: %s, %s", pm->place_id,
Packit Service 37472d
	   NSTR(pm->idb.user), NSTR(pm->idb.community));
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  return ll;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
int mwPlace_sendText(struct mwPlace *place, const char *msg) {
Packit Service 37472d
  struct mwOpaque o = {0,0};
Packit Service 37472d
  struct mwPutBuffer *b;
Packit Service 37472d
  int ret;
Packit Service 37472d
Packit Service 37472d
  b = mwPutBuffer_new();
Packit Service 37472d
  guint32_put(b, 0x01);  /* probably a message type */
Packit Service 37472d
  mwString_put(b, msg);
Packit Service 37472d
  mwPutBuffer_finalize(&o, b);
Packit Service 37472d
Packit Service 37472d
  b = mwPutBuffer_new();
Packit Service 37472d
  guint32_put(b, place->section);
Packit Service 37472d
  mwOpaque_put(b, &o);
Packit Service 37472d
  mwOpaque_clear(&o);
Packit Service 37472d
  mwPutBuffer_finalize(&o, b);
Packit Service 37472d
Packit Service 37472d
  ret = mwChannel_send(place->channel, msg_out_MESSAGE, &o);
Packit Service 37472d
  mwOpaque_clear(&o);
Packit Service 37472d
  return ret;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
int mwPlace_legacyInvite(struct mwPlace *place,
Packit Service 37472d
			 struct mwIdBlock *idb,
Packit Service 37472d
			 const char *message) {
Packit Service 37472d
Packit Service 37472d
  struct mwOpaque o = {0,0};
Packit Service 37472d
  struct mwPutBuffer *b;
Packit Service 37472d
  int ret;
Packit Service 37472d
Packit Service 37472d
  b = mwPutBuffer_new();
Packit Service 37472d
  mwIdBlock_put(b, idb);
Packit Service 37472d
  mwString_put(b, idb->user);
Packit Service 37472d
  mwString_put(b, idb->user);
Packit Service 37472d
  mwString_put(b, message);
Packit Service 37472d
  gboolean_put(b, FALSE);
Packit Service 37472d
  mwPutBuffer_finalize(&o, b);
Packit Service 37472d
Packit Service 37472d
  ret = mwChannel_send(place->channel, msg_out_OLD_INVITE, &o);
Packit Service 37472d
  mwOpaque_clear(&o);
Packit Service 37472d
  return ret;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
int mwPlace_setAttribute(struct mwPlace *place, guint32 attrib,
Packit Service 37472d
			 struct mwOpaque *data) {
Packit Service 37472d
Packit Service 37472d
  struct mwOpaque o = {0,0};
Packit Service 37472d
  struct mwPutBuffer *b;
Packit Service 37472d
  int ret;
Packit Service 37472d
Packit Service 37472d
  b = mwPutBuffer_new();
Packit Service 37472d
  guint32_put(b, place->our_id);
Packit Service 37472d
  guint32_put(b, 0x00);
Packit Service 37472d
  guint32_put(b, attrib);
Packit Service 37472d
  mwOpaque_put(b, data);
Packit Service 37472d
  
Packit Service 37472d
  ret = mwChannel_send(place->channel, msg_out_SET_ATTR, &o);
Packit Service 37472d
  mwOpaque_clear(&o);
Packit Service 37472d
  return ret;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
int mwPlace_unsetAttribute(struct mwPlace *place, guint32 attrib) {
Packit Service 37472d
  struct mwOpaque o = {0,0};
Packit Service 37472d
  struct mwPutBuffer *b;
Packit Service 37472d
  int ret;
Packit Service 37472d
Packit Service 37472d
  b = mwPutBuffer_new();
Packit Service 37472d
  guint32_put(b, place->our_id);
Packit Service 37472d
  guint32_put(b, attrib);
Packit Service 37472d
  
Packit Service 37472d
  ret = mwChannel_send(place->channel, msg_out_SET_ATTR, &o);
Packit Service 37472d
  mwOpaque_clear(&o);
Packit Service 37472d
  return ret;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
void mwPlace_setClientData(struct mwPlace *place,
Packit Service 37472d
			   gpointer data, GDestroyNotify clear) {
Packit Service 37472d
Packit Service 37472d
  g_return_if_fail(place != NULL);
Packit Service 37472d
  mw_datum_set(&place->client_data, data, clear);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
gpointer mwPlace_getClientData(struct mwPlace *place) {
Packit Service 37472d
  g_return_val_if_fail(place != NULL, NULL);
Packit Service 37472d
  return mw_datum_get(&place->client_data);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
void mwPlace_removeClientData(struct mwPlace *place) {
Packit Service 37472d
  g_return_if_fail(place != NULL);
Packit Service 37472d
  mw_datum_clear(&place->client_data);
Packit Service 37472d
}