Blame src/message.c

Packit 16808d
Packit 16808d
/*
Packit 16808d
  Meanwhile - Unofficial Lotus Sametime Community Client Library
Packit 16808d
  Copyright (C) 2004  Christopher (siege) O'Brien
Packit 16808d
  
Packit 16808d
  This library is free software; you can redistribute it and/or
Packit 16808d
  modify it under the terms of the GNU Library General Public
Packit 16808d
  License as published by the Free Software Foundation; either
Packit 16808d
  version 2 of the License, or (at your option) any later version.
Packit 16808d
  
Packit 16808d
  This library is distributed in the hope that it will be useful,
Packit 16808d
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 16808d
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 16808d
  Library General Public License for more details.
Packit 16808d
  
Packit 16808d
  You should have received a copy of the GNU Library General Public
Packit 16808d
  License along with this library; if not, write to the Free
Packit 16808d
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Packit 16808d
*/
Packit 16808d
Packit 16808d
#include <glib.h>
Packit 16808d
Packit 16808d
#include "mw_debug.h"
Packit 16808d
#include "mw_message.h"
Packit 16808d
Packit 16808d
Packit 16808d
/* 7.1 Layering and message encapsulation */
Packit 16808d
/* 7.1.1 The Sametime Message Header */
Packit 16808d
Packit 16808d
Packit 16808d
static void mwMessageHead_put(struct mwPutBuffer *b, struct mwMessage *msg) {
Packit 16808d
  guint16_put(b, msg->type);
Packit 16808d
  guint16_put(b, msg->options);
Packit 16808d
  guint32_put(b, msg->channel);
Packit 16808d
  
Packit 16808d
  if(msg->options & mwMessageOption_HAS_ATTRIBS)
Packit 16808d
    mwOpaque_put(b, &msg->attribs);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void mwMessageHead_get(struct mwGetBuffer *b, struct mwMessage *msg) {
Packit 16808d
Packit 16808d
  if(mwGetBuffer_error(b)) return;
Packit 16808d
Packit 16808d
  guint16_get(b, &msg->type);
Packit 16808d
  guint16_get(b, &msg->options);
Packit 16808d
  guint32_get(b, &msg->channel);
Packit 16808d
Packit 16808d
  if(msg->options & mwMessageOption_HAS_ATTRIBS)
Packit 16808d
    mwOpaque_get(b, &msg->attribs);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void mwMessageHead_clone(struct mwMessage *to,
Packit 16808d
				struct mwMessage *from) {
Packit 16808d
Packit 16808d
  to->type = from->type;
Packit 16808d
  to->options = from->options;
Packit 16808d
  to->channel = from->channel;
Packit 16808d
  mwOpaque_clone(&to->attribs, &from->attribs);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void mwMessageHead_clear(struct mwMessage *msg) {
Packit 16808d
  mwOpaque_clear(&msg->attribs);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/* 8.4 Messages */
Packit 16808d
/* 8.4.1 Basic Community Messages */
Packit 16808d
/* 8.4.1.1 Handshake */
Packit 16808d
Packit 16808d
Packit 16808d
static void HANDSHAKE_put(struct mwPutBuffer *b, struct mwMsgHandshake *msg) {
Packit 16808d
  guint16_put(b, msg->major);
Packit 16808d
  guint16_put(b, msg->minor);
Packit 16808d
  guint32_put(b, msg->head.channel);
Packit 16808d
  guint32_put(b, msg->srvrcalc_addr);
Packit 16808d
  guint16_put(b, msg->login_type);
Packit 16808d
  guint32_put(b, msg->loclcalc_addr);
Packit 16808d
  
Packit 16808d
  if(msg->major >= 0x001e && msg->minor >= 0x001d) {
Packit 16808d
    guint16_put(b, msg->unknown_a);
Packit 16808d
    guint32_put(b, msg->unknown_b);
Packit 16808d
    mwString_put(b, msg->local_host);
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void HANDSHAKE_get(struct mwGetBuffer *b, struct mwMsgHandshake *msg) {
Packit 16808d
  if(mwGetBuffer_error(b)) return;
Packit 16808d
Packit 16808d
  guint16_get(b, &msg->major);
Packit 16808d
  guint16_get(b, &msg->minor);
Packit 16808d
  guint32_get(b, &msg->head.channel);
Packit 16808d
  guint32_get(b, &msg->srvrcalc_addr);
Packit 16808d
  guint16_get(b, &msg->login_type);
Packit 16808d
  guint32_get(b, &msg->loclcalc_addr);
Packit 16808d
Packit 16808d
  if(msg->major >= 0x001e && msg->minor >= 0x001d) {
Packit 16808d
    guint16_get(b, &msg->unknown_a);
Packit 16808d
    guint32_get(b, &msg->unknown_b);
Packit 16808d
    mwString_get(b, &msg->local_host);
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void HANDSHAKE_clear(struct mwMsgHandshake *msg) {
Packit 16808d
  ; /* nothing to clean up */
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/* 8.4.1.2 HandshakeAck */
Packit 16808d
Packit 16808d
Packit 16808d
static void HANDSHAKE_ACK_get(struct mwGetBuffer *b,
Packit 16808d
			      struct mwMsgHandshakeAck *msg) {
Packit 16808d
Packit 16808d
  if(mwGetBuffer_error(b)) return;
Packit 16808d
Packit 16808d
  guint16_get(b, &msg->major);
Packit 16808d
  guint16_get(b, &msg->minor);
Packit 16808d
  guint32_get(b, &msg->srvrcalc_addr);
Packit 16808d
Packit 16808d
  /** @todo: get a better handle on what versions support what parts
Packit 16808d
      of this message. eg: minor version 0x0018 doesn't send the
Packit 16808d
      following */
Packit 16808d
  if(msg->major >= 0x1e && msg->minor > 0x18) {
Packit 16808d
    guint32_get(b, &msg->magic);
Packit 16808d
    mwOpaque_get(b, &msg->data);
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void HANDSHAKE_ACK_put(struct mwPutBuffer *b,
Packit 16808d
			      struct mwMsgHandshakeAck *msg) {
Packit 16808d
Packit 16808d
  guint16_put(b, msg->major);
Packit 16808d
  guint16_put(b, msg->minor);
Packit 16808d
  guint32_put(b, msg->srvrcalc_addr);
Packit 16808d
Packit 16808d
  if(msg->major >= 0x1e && msg->minor > 0x18) {
Packit 16808d
    guint32_put(b, msg->magic);
Packit 16808d
    mwOpaque_put(b, &msg->data);
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void HANDSHAKE_ACK_clear(struct mwMsgHandshakeAck *msg) {
Packit 16808d
  mwOpaque_clear(&msg->data);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/* 8.4.1.3 Login */
Packit 16808d
Packit 16808d
Packit 16808d
static void LOGIN_put(struct mwPutBuffer *b, struct mwMsgLogin *msg) {
Packit 16808d
  guint16_put(b, msg->login_type);
Packit 16808d
  mwString_put(b, msg->name);
Packit 16808d
Packit 16808d
  /* ordering reversed from houri draft?? */
Packit 16808d
  mwOpaque_put(b, &msg->auth_data);
Packit 16808d
  guint16_put(b, msg->auth_type);
Packit 16808d
Packit 16808d
  guint16_put(b, 0x0000); /* unknown */
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void LOGIN_get(struct mwGetBuffer *b, struct mwMsgLogin *msg) {
Packit 16808d
  if(mwGetBuffer_error(b)) return;
Packit 16808d
Packit 16808d
  guint16_get(b, &msg->login_type);
Packit 16808d
  mwString_get(b, &msg->name);
Packit 16808d
  mwOpaque_get(b, &msg->auth_data);
Packit 16808d
  guint16_get(b, &msg->auth_type);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void LOGIN_clear(struct mwMsgLogin *msg) {
Packit 16808d
  g_free(msg->name);  msg->name = NULL;
Packit 16808d
  mwOpaque_clear(&msg->auth_data);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/* 8.4.1.4 LoginAck */
Packit 16808d
Packit 16808d
Packit 16808d
static void LOGIN_ACK_get(struct mwGetBuffer *b, struct mwMsgLoginAck *msg) {
Packit 16808d
  guint16 junk;
Packit 16808d
Packit 16808d
  if(mwGetBuffer_error(b)) return;
Packit 16808d
Packit 16808d
  mwLoginInfo_get(b, &msg->login);
Packit 16808d
  guint16_get(b, &junk);
Packit 16808d
  mwPrivacyInfo_get(b, &msg->privacy);
Packit 16808d
  mwUserStatus_get(b, &msg->status);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void LOGIN_ACK_clear(struct mwMsgLoginAck *msg) {
Packit 16808d
  mwLoginInfo_clear(&msg->login);
Packit 16808d
  mwPrivacyInfo_clear(&msg->privacy);
Packit 16808d
  mwUserStatus_clear(&msg->status);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/* 8.4.1.5 LoginCont */
Packit 16808d
Packit 16808d
Packit 16808d
static void LOGIN_CONTINUE_put(struct mwPutBuffer *b,
Packit 16808d
			       struct mwMsgLoginContinue *msg) {
Packit 16808d
Packit 16808d
  ; /* nothing but a message header */
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void LOGIN_CONTINUE_get(struct mwGetBuffer *b,
Packit 16808d
			       struct mwMsgLoginContinue *msg) {
Packit 16808d
Packit 16808d
  ; /* nothing but a message header */
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void LOGIN_CONTINUE_clear(struct mwMsgLoginContinue *msg) {
Packit 16808d
  ; /* this is a very simple message */
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/* 8.4.1.6 AuthPassed */
Packit 16808d
Packit 16808d
Packit 16808d
static void LOGIN_REDIRECT_get(struct mwGetBuffer *b,
Packit 16808d
			       struct mwMsgLoginRedirect *msg) {
Packit 16808d
Packit 16808d
  if(mwGetBuffer_error(b)) return;
Packit 16808d
  mwString_get(b, &msg->host);
Packit 16808d
  mwString_get(b, &msg->server_id);  
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void LOGIN_REDIRECT_put(struct mwPutBuffer *b,
Packit 16808d
			       struct mwMsgLoginRedirect *msg) {
Packit 16808d
  mwString_put(b, msg->host);
Packit 16808d
  mwString_put(b, msg->server_id);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void LOGIN_REDIRECT_clear(struct mwMsgLoginRedirect *msg) {
Packit 16808d
  g_free(msg->host);
Packit 16808d
  msg->host = NULL;
Packit 16808d
Packit 16808d
  g_free(msg->server_id);
Packit 16808d
  msg->server_id = NULL;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/* 8.4.1.7 CreateCnl */
Packit 16808d
Packit 16808d
Packit 16808d
static void enc_offer_put(struct mwPutBuffer *b, struct mwEncryptOffer *enc) {
Packit 16808d
  guint16_put(b, enc->mode);
Packit 16808d
Packit 16808d
  if(enc->items) {
Packit 16808d
    guint32 count;
Packit 16808d
    struct mwPutBuffer *p;
Packit 16808d
    struct mwOpaque o;
Packit 16808d
    GList *list;
Packit 16808d
Packit 16808d
    /* write the count, items, extra, and flag into a tmp buffer,
Packit 16808d
       render that buffer into an opaque, and write it into b */
Packit 16808d
Packit 16808d
    count = g_list_length(enc->items);
Packit 16808d
    p = mwPutBuffer_new();
Packit 16808d
Packit 16808d
    guint32_put(p, count);
Packit 16808d
    for(list = enc->items; list; list = list->next) {
Packit 16808d
      mwEncryptItem_put(p, list->data);
Packit 16808d
    }
Packit 16808d
Packit 16808d
    guint16_put(p, enc->extra);
Packit 16808d
    gboolean_put(p, enc->flag);
Packit 16808d
Packit 16808d
    mwPutBuffer_finalize(&o, p);
Packit 16808d
    mwOpaque_put(b, &o);
Packit 16808d
    mwOpaque_clear(&o);
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void CHANNEL_CREATE_put(struct mwPutBuffer *b,
Packit 16808d
			       struct mwMsgChannelCreate *msg) {
Packit 16808d
Packit 16808d
  guint32_put(b, msg->reserved);
Packit 16808d
  guint32_put(b, msg->channel);
Packit 16808d
  mwIdBlock_put(b, &msg->target);
Packit 16808d
  guint32_put(b, msg->service);
Packit 16808d
  guint32_put(b, msg->proto_type);
Packit 16808d
  guint32_put(b, msg->proto_ver);
Packit 16808d
  guint32_put(b, msg->options);
Packit 16808d
  mwOpaque_put(b, &msg->addtl);
Packit 16808d
  gboolean_put(b, msg->creator_flag);
Packit 16808d
Packit 16808d
  if(msg->creator_flag)
Packit 16808d
    mwLoginInfo_put(b, &msg->creator);
Packit 16808d
Packit 16808d
  enc_offer_put(b, &msg->encrypt);
Packit 16808d
Packit 16808d
  guint32_put(b, 0x00);
Packit 16808d
  guint32_put(b, 0x00);
Packit 16808d
  guint16_put(b, 0x07);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void enc_offer_get(struct mwGetBuffer *b,
Packit 16808d
			  struct mwEncryptOffer *enc) {
Packit 16808d
  guint32 skip;
Packit 16808d
Packit 16808d
  if(mwGetBuffer_error(b)) return;
Packit 16808d
Packit 16808d
  guint16_get(b, &enc->mode);
Packit 16808d
  guint32_get(b, &skip);
Packit 16808d
Packit 16808d
  if(skip >= 7) {
Packit 16808d
    guint32 count;
Packit 16808d
Packit 16808d
    guint32_get(b, &count);
Packit 16808d
Packit 16808d
    while(count-- && (! mwGetBuffer_error(b))) {
Packit 16808d
      struct mwEncryptItem *ei = g_new0(struct mwEncryptItem, 1);
Packit 16808d
      mwEncryptItem_get(b, ei);
Packit 16808d
      enc->items = g_list_append(enc->items, ei);
Packit 16808d
    }
Packit 16808d
Packit 16808d
    guint16_get(b, &enc->extra);
Packit 16808d
    gboolean_get(b, &enc->flag);
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void CHANNEL_CREATE_get(struct mwGetBuffer *b,
Packit 16808d
			       struct mwMsgChannelCreate *msg) {
Packit 16808d
Packit 16808d
  if(mwGetBuffer_error(b)) return;
Packit 16808d
Packit 16808d
  guint32_get(b, &msg->reserved);
Packit 16808d
  guint32_get(b, &msg->channel);
Packit 16808d
  mwIdBlock_get(b, &msg->target);
Packit 16808d
  guint32_get(b, &msg->service);
Packit 16808d
  guint32_get(b, &msg->proto_type);
Packit 16808d
  guint32_get(b, &msg->proto_ver);
Packit 16808d
  guint32_get(b, &msg->options);
Packit 16808d
  mwOpaque_get(b, &msg->addtl);
Packit 16808d
  gboolean_get(b, &msg->creator_flag);
Packit 16808d
  
Packit 16808d
  if(msg->creator_flag)
Packit 16808d
    mwLoginInfo_get(b, &msg->creator);
Packit 16808d
  
Packit 16808d
  enc_offer_get(b, &msg->encrypt);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void CHANNEL_CREATE_clear(struct mwMsgChannelCreate *msg) {
Packit 16808d
  GList *list;
Packit 16808d
Packit 16808d
  mwIdBlock_clear(&msg->target);
Packit 16808d
  mwOpaque_clear(&msg->addtl);
Packit 16808d
  mwLoginInfo_clear(&msg->creator);
Packit 16808d
  
Packit 16808d
  for(list = msg->encrypt.items; list; list = list->next) {
Packit 16808d
    mwEncryptItem_clear(list->data);
Packit 16808d
    g_free(list->data);
Packit 16808d
  }
Packit 16808d
  g_list_free(msg->encrypt.items);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/* 8.4.1.8 AcceptCnl */
Packit 16808d
Packit 16808d
Packit 16808d
static void enc_accept_put(struct mwPutBuffer *b,
Packit 16808d
			   struct mwEncryptAccept *enc) {
Packit 16808d
Packit 16808d
  guint16_put(b, enc->mode);
Packit 16808d
Packit 16808d
  if(enc->item) {
Packit 16808d
    struct mwPutBuffer *p;
Packit 16808d
    struct mwOpaque o;
Packit 16808d
Packit 16808d
    p = mwPutBuffer_new();
Packit 16808d
Packit 16808d
    mwEncryptItem_put(p, enc->item);
Packit 16808d
    guint16_put(p, enc->extra);
Packit 16808d
    gboolean_put(p, enc->flag);
Packit 16808d
Packit 16808d
    mwPutBuffer_finalize(&o, p);
Packit 16808d
    mwOpaque_put(b, &o);
Packit 16808d
    mwOpaque_clear(&o);
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void CHANNEL_ACCEPT_put(struct mwPutBuffer *b,
Packit 16808d
			       struct mwMsgChannelAccept *msg) {
Packit 16808d
  
Packit 16808d
  guint32_put(b, msg->service);
Packit 16808d
  guint32_put(b, msg->proto_type);
Packit 16808d
  guint32_put(b, msg->proto_ver);
Packit 16808d
  mwOpaque_put(b, &msg->addtl);
Packit 16808d
  gboolean_put(b, msg->acceptor_flag);
Packit 16808d
  
Packit 16808d
  if(msg->acceptor_flag)
Packit 16808d
    mwLoginInfo_put(b, &msg->acceptor);
Packit 16808d
  
Packit 16808d
  enc_accept_put(b, &msg->encrypt);
Packit 16808d
Packit 16808d
  guint32_put(b, 0x00);
Packit 16808d
  guint32_put(b, 0x00);
Packit 16808d
  guint16_put(b, 0x07);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void enc_accept_get(struct mwGetBuffer *b,
Packit 16808d
			   struct mwEncryptAccept *enc) {
Packit 16808d
  guint32 skip;
Packit 16808d
Packit 16808d
  if(mwGetBuffer_error(b)) return;
Packit 16808d
Packit 16808d
  guint16_get(b, &enc->mode);
Packit 16808d
  guint32_get(b, &skip);
Packit 16808d
Packit 16808d
  if(skip >= 6) {
Packit 16808d
    enc->item = g_new0(struct mwEncryptItem, 1);
Packit 16808d
    mwEncryptItem_get(b, enc->item);
Packit 16808d
  }
Packit 16808d
Packit 16808d
  if(skip >= 9) {
Packit 16808d
    guint16_get(b, &enc->extra);
Packit 16808d
    gboolean_get(b, &enc->flag);
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void CHANNEL_ACCEPT_get(struct mwGetBuffer *b,
Packit 16808d
			       struct mwMsgChannelAccept *msg) {
Packit 16808d
Packit 16808d
  if(mwGetBuffer_error(b)) return;
Packit 16808d
Packit 16808d
  guint32_get(b, &msg->service);
Packit 16808d
  guint32_get(b, &msg->proto_type);
Packit 16808d
  guint32_get(b, &msg->proto_ver);
Packit 16808d
  mwOpaque_get(b, &msg->addtl);
Packit 16808d
  gboolean_get(b, &msg->acceptor_flag);
Packit 16808d
Packit 16808d
  if(msg->acceptor_flag)
Packit 16808d
    mwLoginInfo_get(b, &msg->acceptor);
Packit 16808d
Packit 16808d
  enc_accept_get(b, &msg->encrypt);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void CHANNEL_ACCEPT_clear(struct mwMsgChannelAccept *msg) {
Packit 16808d
  mwOpaque_clear(&msg->addtl);
Packit 16808d
  mwLoginInfo_clear(&msg->acceptor);
Packit 16808d
Packit 16808d
  if(msg->encrypt.item) {
Packit 16808d
    mwEncryptItem_clear(msg->encrypt.item);
Packit 16808d
    g_free(msg->encrypt.item);
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/* 8.4.1.9 SendOnCnl */
Packit 16808d
Packit 16808d
Packit 16808d
static void CHANNEL_SEND_put(struct mwPutBuffer *b,
Packit 16808d
			     struct mwMsgChannelSend *msg) {
Packit 16808d
Packit 16808d
  guint16_put(b, msg->type);
Packit 16808d
  mwOpaque_put(b, &msg->data);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void CHANNEL_SEND_get(struct mwGetBuffer *b,
Packit 16808d
			     struct mwMsgChannelSend *msg) {
Packit 16808d
Packit 16808d
  if(mwGetBuffer_error(b)) return;
Packit 16808d
Packit 16808d
  guint16_get(b, &msg->type);
Packit 16808d
  mwOpaque_get(b, &msg->data);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void CHANNEL_SEND_clear(struct mwMsgChannelSend *msg) {
Packit 16808d
  mwOpaque_clear(&msg->data);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/* 8.4.1.10 DestroyCnl */
Packit 16808d
Packit 16808d
Packit 16808d
static void CHANNEL_DESTROY_put(struct mwPutBuffer *b,
Packit 16808d
				struct mwMsgChannelDestroy *msg) {
Packit 16808d
  guint32_put(b, msg->reason);
Packit 16808d
  mwOpaque_put(b, &msg->data);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void CHANNEL_DESTROY_get(struct mwGetBuffer *b,
Packit 16808d
				struct mwMsgChannelDestroy *msg) {
Packit 16808d
Packit 16808d
  if(mwGetBuffer_error(b)) return;
Packit 16808d
Packit 16808d
  guint32_get(b, &msg->reason);
Packit 16808d
  mwOpaque_get(b, &msg->data);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void CHANNEL_DESTROY_clear(struct mwMsgChannelDestroy *msg) {
Packit 16808d
  mwOpaque_clear(&msg->data);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/* 8.4.1.11 SetUserStatus */
Packit 16808d
Packit 16808d
Packit 16808d
static void SET_USER_STATUS_put(struct mwPutBuffer *b,
Packit 16808d
				struct mwMsgSetUserStatus *msg) {
Packit 16808d
  mwUserStatus_put(b, &msg->status);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void SET_USER_STATUS_get(struct mwGetBuffer *b,
Packit 16808d
				struct mwMsgSetUserStatus *msg) {
Packit 16808d
Packit 16808d
  if(mwGetBuffer_error(b)) return;
Packit 16808d
  mwUserStatus_get(b, &msg->status);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void SET_USER_STATUS_clear(struct mwMsgSetUserStatus *msg) {
Packit 16808d
  mwUserStatus_clear(&msg->status);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/* 8.4.1.12 SetPrivacyList */
Packit 16808d
Packit 16808d
Packit 16808d
static void SET_PRIVACY_LIST_put(struct mwPutBuffer *b,
Packit 16808d
				 struct mwMsgSetPrivacyList *msg) {
Packit 16808d
  mwPrivacyInfo_put(b, &msg->privacy);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void SET_PRIVACY_LIST_get(struct mwGetBuffer *b,
Packit 16808d
				 struct mwMsgSetPrivacyList *msg) {
Packit 16808d
Packit 16808d
  if(mwGetBuffer_error(b)) return;
Packit 16808d
  mwPrivacyInfo_get(b, &msg->privacy);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void SET_PRIVACY_LIST_clear(struct mwMsgSetPrivacyList *msg) {
Packit 16808d
  mwPrivacyInfo_clear(&msg->privacy);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/* Sense Service messages */
Packit 16808d
Packit 16808d
Packit 16808d
static void SENSE_SERVICE_put(struct mwPutBuffer *b,
Packit 16808d
			      struct mwMsgSenseService *msg) {
Packit 16808d
  guint32_put(b, msg->service);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void SENSE_SERVICE_get(struct mwGetBuffer *b,
Packit 16808d
			      struct mwMsgSenseService *msg) {
Packit 16808d
Packit 16808d
  if(mwGetBuffer_error(b)) return;
Packit 16808d
  guint32_get(b, &msg->service);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void SENSE_SERVICE_clear(struct mwMsgSenseService *msg) {
Packit 16808d
  ;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/* Admin messages */
Packit 16808d
Packit 16808d
Packit 16808d
static void ADMIN_get(struct mwGetBuffer *b, struct mwMsgAdmin *msg) {
Packit 16808d
  mwString_get(b, &msg->text);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void ADMIN_clear(struct mwMsgAdmin *msg) {
Packit 16808d
  g_free(msg->text);
Packit 16808d
  msg->text = NULL;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/* Announcement messages */
Packit 16808d
Packit 16808d
Packit 16808d
static void ANNOUNCE_get(struct mwGetBuffer *b, struct mwMsgAnnounce *msg) {
Packit 16808d
  struct mwOpaque o = { 0, 0 };
Packit 16808d
  struct mwGetBuffer *gb;
Packit 16808d
  guint32 count;
Packit 16808d
Packit 16808d
  gboolean_get(b, &msg->sender_present);
Packit 16808d
  if(msg->sender_present)
Packit 16808d
    mwLoginInfo_get(b, &msg->sender);
Packit 16808d
  guint16_get(b, &msg->unknown_a);
Packit 16808d
  
Packit 16808d
  mwOpaque_get(b, &o);
Packit 16808d
  gb = mwGetBuffer_wrap(&o);
Packit 16808d
Packit 16808d
  gboolean_get(gb, &msg->may_reply);
Packit 16808d
  mwString_get(gb, &msg->text);
Packit 16808d
Packit 16808d
  mwGetBuffer_free(gb);
Packit 16808d
  mwOpaque_clear(&o);
Packit 16808d
Packit 16808d
  guint32_get(b, &count);
Packit 16808d
  while(count--) {
Packit 16808d
    char *r = NULL;
Packit 16808d
    mwString_get(b, &r);
Packit 16808d
    msg->recipients = g_list_prepend(msg->recipients, r);
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void ANNOUNCE_put(struct mwPutBuffer *b, struct mwMsgAnnounce *msg) {
Packit 16808d
  struct mwOpaque o = { 0, 0 };
Packit 16808d
  struct mwPutBuffer *pb;
Packit 16808d
  GList *l;
Packit 16808d
  
Packit 16808d
  gboolean_put(b, msg->sender_present);
Packit 16808d
  if(msg->sender_present)
Packit 16808d
    mwLoginInfo_put(b, &msg->sender);
Packit 16808d
  guint16_put(b, msg->unknown_a);
Packit 16808d
Packit 16808d
  pb = mwPutBuffer_new();
Packit 16808d
  
Packit 16808d
  gboolean_put(pb, msg->may_reply);
Packit 16808d
  mwString_put(pb, msg->text);
Packit 16808d
Packit 16808d
  mwPutBuffer_finalize(&o, pb);
Packit 16808d
  mwOpaque_put(b, &o);
Packit 16808d
  mwOpaque_clear(&o);
Packit 16808d
Packit 16808d
  guint32_put(b, g_list_length(msg->recipients));
Packit 16808d
  for(l = msg->recipients; l; l = l->next) {
Packit 16808d
    mwString_put(b, l->data);
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void ANNOUNCE_clear(struct mwMsgAnnounce *msg) {
Packit 16808d
  mwLoginInfo_clear(&msg->sender);
Packit 16808d
Packit 16808d
  g_free(msg->text);
Packit 16808d
  msg->text = NULL;
Packit 16808d
  
Packit 16808d
  while(msg->recipients) {
Packit 16808d
    g_free(msg->recipients->data);
Packit 16808d
    msg->recipients = g_list_delete_link(msg->recipients, msg->recipients);
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/* general functions */
Packit 16808d
Packit 16808d
Packit 16808d
#define CASE(v, t) \
Packit 16808d
case mwMessage_ ## v: \
Packit 16808d
  msg = (struct mwMessage *) g_new0(struct t, 1); \
Packit 16808d
  msg->type = type; \
Packit 16808d
  break;
Packit 16808d
Packit 16808d
Packit 16808d
struct mwMessage *mwMessage_new(enum mwMessageType type) {
Packit 16808d
  struct mwMessage *msg = NULL;
Packit 16808d
  
Packit 16808d
  switch(type) {
Packit 16808d
    CASE(HANDSHAKE, mwMsgHandshake);
Packit 16808d
    CASE(HANDSHAKE_ACK, mwMsgHandshakeAck);
Packit 16808d
    CASE(LOGIN, mwMsgLogin);
Packit 16808d
    CASE(LOGIN_REDIRECT, mwMsgLoginRedirect);
Packit 16808d
    CASE(LOGIN_CONTINUE, mwMsgLoginContinue);
Packit 16808d
    CASE(LOGIN_ACK, mwMsgLoginAck);
Packit 16808d
    CASE(CHANNEL_CREATE, mwMsgChannelCreate);
Packit 16808d
    CASE(CHANNEL_DESTROY, mwMsgChannelDestroy);
Packit 16808d
    CASE(CHANNEL_SEND, mwMsgChannelSend);
Packit 16808d
    CASE(CHANNEL_ACCEPT, mwMsgChannelAccept);
Packit 16808d
    CASE(SET_USER_STATUS, mwMsgSetUserStatus);
Packit 16808d
    CASE(SET_PRIVACY_LIST, mwMsgSetPrivacyList);
Packit 16808d
    CASE(SENSE_SERVICE, mwMsgSenseService);
Packit 16808d
    CASE(ADMIN, mwMsgAdmin);
Packit 16808d
    CASE(ANNOUNCE, mwMsgAnnounce);
Packit 16808d
    
Packit 16808d
  default:
Packit 16808d
    g_warning("unknown message type 0x%02x\n", type);
Packit 16808d
  }
Packit 16808d
  
Packit 16808d
  return msg;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
#undef CASE
Packit 16808d
Packit 16808d
Packit 16808d
/* each type needs to be passed to a specially named _get functions,
Packit 16808d
   and cast to a specific subclass of mwMessage. */
Packit 16808d
#define CASE(v, t) \
Packit 16808d
case mwMessage_ ## v: \
Packit 16808d
  msg = (struct mwMessage *) g_new0(struct t, 1); \
Packit 16808d
  mwMessageHead_clone(msg, &head;; \
Packit 16808d
  v ## _get(b, (struct t *) msg); \
Packit 16808d
  break;
Packit 16808d
Packit 16808d
Packit 16808d
struct mwMessage *mwMessage_get(struct mwGetBuffer *b) {
Packit 16808d
  struct mwMessage *msg = NULL;
Packit 16808d
  struct mwMessage head;
Packit 16808d
  
Packit 16808d
  g_return_val_if_fail(b != NULL, NULL);
Packit 16808d
Packit 16808d
  head.attribs.len = 0;
Packit 16808d
  head.attribs.data = NULL;
Packit 16808d
Packit 16808d
  /* attempt to read the header first */
Packit 16808d
  mwMessageHead_get(b, &head;;
Packit 16808d
Packit 16808d
  if(mwGetBuffer_error(b)) {
Packit 16808d
    mwMessageHead_clear(&head;;
Packit 16808d
    g_warning("problem parsing message head from buffer");
Packit 16808d
    return NULL;
Packit 16808d
  }
Packit 16808d
Packit 16808d
  /* load the rest of the message depending on the header type */
Packit 16808d
  switch(head.type) {
Packit 16808d
    CASE(HANDSHAKE, mwMsgHandshake);
Packit 16808d
    CASE(HANDSHAKE_ACK, mwMsgHandshakeAck);
Packit 16808d
    CASE(LOGIN, mwMsgLogin);
Packit 16808d
    CASE(LOGIN_REDIRECT, mwMsgLoginRedirect);
Packit 16808d
    CASE(LOGIN_CONTINUE, mwMsgLoginContinue);
Packit 16808d
    CASE(LOGIN_ACK, mwMsgLoginAck);
Packit 16808d
    CASE(CHANNEL_CREATE, mwMsgChannelCreate);
Packit 16808d
    CASE(CHANNEL_DESTROY, mwMsgChannelDestroy);
Packit 16808d
    CASE(CHANNEL_SEND, mwMsgChannelSend);
Packit 16808d
    CASE(CHANNEL_ACCEPT, mwMsgChannelAccept);
Packit 16808d
    CASE(SET_USER_STATUS, mwMsgSetUserStatus);
Packit 16808d
    CASE(SET_PRIVACY_LIST, mwMsgSetPrivacyList);
Packit 16808d
    CASE(SENSE_SERVICE, mwMsgSenseService);
Packit 16808d
    CASE(ADMIN, mwMsgAdmin);
Packit 16808d
    CASE(ANNOUNCE, mwMsgAnnounce);
Packit 16808d
Packit 16808d
  default:
Packit 16808d
    g_warning("unknown message type 0x%02x, no parse handler", head.type);
Packit 16808d
  }
Packit 16808d
Packit 16808d
  if(mwGetBuffer_error(b)) {
Packit 16808d
    g_warning("problem parsing message type 0x%02x, not enough data",
Packit 16808d
	      head.type);
Packit 16808d
  }
Packit 16808d
Packit 16808d
  mwMessageHead_clear(&head;;
Packit 16808d
  
Packit 16808d
  return msg;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
#undef CASE
Packit 16808d
Packit 16808d
Packit 16808d
#define CASE(v, t) \
Packit 16808d
case mwMessage_ ## v: \
Packit 16808d
  v ## _put(b, (struct t *) msg); \
Packit 16808d
  break;
Packit 16808d
Packit 16808d
Packit 16808d
void mwMessage_put(struct mwPutBuffer *b, struct mwMessage *msg) {
Packit 16808d
Packit 16808d
  g_return_if_fail(b != NULL);
Packit 16808d
  g_return_if_fail(msg != NULL);
Packit 16808d
Packit 16808d
  mwMessageHead_put(b, msg);
Packit 16808d
Packit 16808d
  switch(msg->type) {
Packit 16808d
    CASE(HANDSHAKE, mwMsgHandshake);
Packit 16808d
    CASE(HANDSHAKE_ACK, mwMsgHandshakeAck);
Packit 16808d
    CASE(LOGIN, mwMsgLogin);
Packit 16808d
    CASE(LOGIN_REDIRECT, mwMsgLoginRedirect);
Packit 16808d
    CASE(LOGIN_CONTINUE, mwMsgLoginContinue);
Packit 16808d
    CASE(CHANNEL_CREATE, mwMsgChannelCreate);
Packit 16808d
    CASE(CHANNEL_DESTROY, mwMsgChannelDestroy);
Packit 16808d
    CASE(CHANNEL_SEND, mwMsgChannelSend);
Packit 16808d
    CASE(CHANNEL_ACCEPT, mwMsgChannelAccept);
Packit 16808d
    CASE(SET_USER_STATUS, mwMsgSetUserStatus);
Packit 16808d
    CASE(SET_PRIVACY_LIST, mwMsgSetPrivacyList);
Packit 16808d
    CASE(SENSE_SERVICE, mwMsgSenseService);
Packit 16808d
    CASE(ANNOUNCE, mwMsgAnnounce);
Packit 16808d
    
Packit 16808d
  default:
Packit 16808d
    ; /* hrm. */
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
#undef CASE
Packit 16808d
Packit 16808d
Packit 16808d
#define CASE(v, t) \
Packit 16808d
case mwMessage_ ## v: \
Packit 16808d
  v ## _clear((struct t *) msg); \
Packit 16808d
  break;
Packit 16808d
Packit 16808d
Packit 16808d
void mwMessage_free(struct mwMessage *msg) {
Packit 16808d
  if(! msg) return;
Packit 16808d
Packit 16808d
  mwMessageHead_clear(msg);
Packit 16808d
Packit 16808d
  switch(msg->type) {
Packit 16808d
    CASE(HANDSHAKE, mwMsgHandshake);
Packit 16808d
    CASE(HANDSHAKE_ACK, mwMsgHandshakeAck);
Packit 16808d
    CASE(LOGIN, mwMsgLogin);
Packit 16808d
    CASE(LOGIN_REDIRECT, mwMsgLoginRedirect);
Packit 16808d
    CASE(LOGIN_CONTINUE, mwMsgLoginContinue);
Packit 16808d
    CASE(LOGIN_ACK, mwMsgLoginAck);
Packit 16808d
    CASE(CHANNEL_CREATE, mwMsgChannelCreate);
Packit 16808d
    CASE(CHANNEL_DESTROY, mwMsgChannelDestroy);
Packit 16808d
    CASE(CHANNEL_SEND, mwMsgChannelSend);
Packit 16808d
    CASE(CHANNEL_ACCEPT, mwMsgChannelAccept);
Packit 16808d
    CASE(SET_USER_STATUS, mwMsgSetUserStatus);
Packit 16808d
    CASE(SET_PRIVACY_LIST, mwMsgSetPrivacyList);
Packit 16808d
    CASE(SENSE_SERVICE, mwMsgSenseService);
Packit 16808d
    CASE(ADMIN, mwMsgAdmin);
Packit 16808d
    CASE(ANNOUNCE, mwMsgAnnounce);
Packit 16808d
    
Packit 16808d
  default:
Packit 16808d
    ; /* hrm. */
Packit 16808d
  }
Packit 16808d
Packit 16808d
  g_free(msg);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
#undef CASE
Packit 16808d
Packit 16808d