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