--- 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, §ion); - - 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, §ion); - 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, §ion); - 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, §ion); - 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); -}