Пример #1
0
static int recv_SECTION_PEER_PART(struct mwPlace *place,
				  struct mwGetBuffer *b) {
  struct mwServicePlace *srvc;
  int ret = 0;
  guint32 section, id;
  struct place_member *pm;

  srvc = place->service;

  guint32_get(b, &section);
  g_return_val_if_fail(section == place->section, 0);

  guint32_get(b, &id);
  pm = GET_MEMBER(place, id);

  /* SECTION_PART may have been called already */
  if(! pm) return 0;

  if(srvc->handler && srvc->handler->peerParted)
    srvc->handler->peerParted(place, &pm->idb);

  REMOVE_MEMBER(place, pm);

  return ret;
}
Пример #2
0
static void recv_list(struct mwServiceDirectory *srvc,
		      struct mwOpaque *data) {

  struct mwGetBuffer *b;
  guint32 request, code, count;
  gboolean foo_1;
  guint16 foo_2;
  
  b = mwGetBuffer_wrap(data);
  
  guint32_get(b, &request);
  guint32_get(b, &code);
  guint32_get(b, &count);

  gboolean_get(b, &foo_1);
  guint16_get(b, &foo_2);

  if(foo_1 || foo_2) {
    mw_mailme_opaque(data, "received strange address book list");
    mwGetBuffer_free(b);
    return;
  }

  while(!mwGetBuffer_error(b) && count--) {
    guint32 id;
    char *name = NULL;

    guint32_get(b, &id);
    mwString_get(b, &name);

    book_new(srvc, name, id);
    g_free(name);
  }
}
Пример #3
0
static void data_recv(struct mwServiceConference *srvc,
		      struct mwConference *conf,
		      struct mwLoginInfo *m,
		      struct mwGetBuffer *b) {

  /* this function acts a lot like receiving an IM Data message. The
     data message has a type, a subtype, and an opaque. We only
     support typing notification though. */

  /** @todo it's possible that some clients send text in a data
      message, as we've seen rarely in the IM service. Have to add
      support for that here */

  guint32 type, subtype;
  struct mwConferenceHandler *h;

  guint32_get(b, &type);
  guint32_get(b, &subtype);

  if(mwGetBuffer_error(b)) return;

  /* don't know how to deal with any others yet */
  if(type != 0x01) {
    g_message("unknown data message type (0x%08x, 0x%08x)", type, subtype);
    return;
  }

  h = srvc->handler;
  if(h->on_typing) {
    h->on_typing(conf, m, !subtype);
  }
}
Пример #4
0
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;
}
Пример #5
0
static void WELCOME_recv(struct mwServiceConference *srvc,
			 struct mwConference *conf,
			 struct mwGetBuffer *b) {

  struct mwConferenceHandler *h;
  guint16 tmp16;
  guint32 tmp32;
  guint32 count;
  GList *l = NULL;

  /* re-read name and title */
  g_free(conf->name);
  g_free(conf->title);
  conf->name = NULL;
  conf->title = NULL;
  mwString_get(b, &conf->name);
  mwString_get(b, &conf->title);

  /* some numbers we don't care about, then a count of members */
  guint16_get(b, &tmp16);
  guint32_get(b, &tmp32);
  guint32_get(b, &count);

  if(mwGetBuffer_error(b)) {
    g_warning("error parsing welcome message for conference");
    mwConference_destroy(conf, ERR_FAILURE, NULL);
    return;
  }
  
  while(count--) {
    guint16 member_id;
    struct mwLoginInfo *member = g_new0(struct mwLoginInfo, 1);

    guint16_get(b, &member_id);
    mwLoginInfo_get(b, member);

    if(mwGetBuffer_error(b)) {
      login_free(member);
      break;
    }

    MEMBER_ADD(conf, member_id, member);
    l = g_list_append(l, member);
  }

  conf_state(conf, mwConference_OPEN);

  h = srvc->handler;
  if(h->conf_opened)
    h->conf_opened(conf, l);

  /* get rid of the GList, but not its contents */
  g_list_free(l);
}
Пример #6
0
static int recv_JOIN_RESPONSE(struct mwPlace *place,
			      struct mwGetBuffer *b) {
  
  int ret = 0;
  guint32 our_id, section;

  guint32_get(b, &our_id);
  guint32_get(b, &section);

  place->our_id = our_id;
  place->section = section;

  return ret;
}
Пример #7
0
static void recv_channelCreate(struct mwServiceFileTransfer *srvc,
			       struct mwChannel *chan,
			       struct mwMsgChannelCreate *msg) {

  struct mwFileTransferHandler *handler;
  struct mwGetBuffer *b;

  char *fnm, *txt;
  guint32 size, junk;
  gboolean b_err;

  g_return_if_fail(srvc->handler != NULL);
  handler = srvc->handler;
  
  b = mwGetBuffer_wrap(&msg->addtl);

  guint32_get(b, &junk); /* unknown */
  mwString_get(b, &fnm); /* offered filename */
  mwString_get(b, &txt); /* offering message */
  guint32_get(b, &size); /* size of offered file */
  /// Miranda NG adaptation - start - http://www.lilotux.net/~mikael/pub/meanwhile/ft_fix.diff
  /* guint32_get(b, &junk); */ /* unknown */
  /// Miranda NG adaptation - end
  /* and we just skip an unknown guint16 at the end */

  b_err = mwGetBuffer_error(b);
  mwGetBuffer_free(b);

  if(b_err) {
    g_warning("bad/malformed addtl in File Transfer service");
    mwChannel_destroy(chan, ERR_FAILURE, NULL);

  } else {
    struct mwIdBlock idb;
    struct mwFileTransfer *ft;

    login_into_id(&idb, mwChannel_getUser(chan));
    ft = mwFileTransfer_new(srvc, &idb, txt, fnm, size);
    ft->channel = chan;
    ft_state(ft, mwFileTransfer_PENDING);

    mwChannel_setServiceData(chan, ft, NULL);

    if(handler->ft_offered)
      handler->ft_offered(ft);
  }

  g_free(fnm);
  g_free(txt);
}
Пример #8
0
static void HANDSHAKE_get(struct mwGetBuffer *b, struct mwMsgHandshake *msg) {
  if(mwGetBuffer_error(b)) return;

  guint16_get(b, &msg->major);
  guint16_get(b, &msg->minor);
  guint32_get(b, &msg->head.channel);
  guint32_get(b, &msg->srvrcalc_addr);
  guint16_get(b, &msg->login_type);
  guint32_get(b, &msg->loclcalc_addr);

  if(msg->major >= 0x001e && msg->minor >= 0x001d) {
    guint16_get(b, &msg->unknown_a);
    guint32_get(b, &msg->unknown_b);
    mwString_get(b, &msg->local_host);
  }
}
Пример #9
0
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;
}
Пример #10
0
static void recv_channelCreate(struct mwService *srvc,
			       struct mwChannel *chan,
			       struct mwMsgChannelCreate *msg) {

  /* - this is how we really receive invitations
     - create a conference and associate it with the channel
     - obtain the invite data from the msg addtl info
     - mark the conference as INVITED
     - trigger the got_invite event
  */

  struct mwServiceConference *srvc_conf = (struct mwServiceConference *) srvc;
  struct mwConference *conf;

  struct mwGetBuffer *b;

  char *invite = NULL;
  guint tmp;

  conf = conf_new(srvc_conf);
  conf->channel = chan;

  b = mwGetBuffer_wrap(&msg->addtl);

  guint32_get(b, &tmp);
  mwString_get(b, &conf->name);
  mwString_get(b, &conf->title);
  guint32_get(b, &tmp);
  mwLoginInfo_get(b, &conf->owner);
  guint32_get(b, &tmp);
  mwString_get(b, &invite);

  if(mwGetBuffer_error(b)) {
    g_warning("failure parsing addtl for conference invite");
    mwConference_destroy(conf, ERR_FAILURE, NULL);

  } else {
    struct mwConferenceHandler *h = srvc_conf->handler;
    conf_state(conf, mwConference_INVITED);
    if(h->on_invited)
      h->on_invited(conf, &conf->owner, invite);
  }

  mwGetBuffer_free(b);
  g_free(invite);
}
Пример #11
0
static void HANDSHAKE_ACK_get(struct mwGetBuffer *b,
			      struct mwMsgHandshakeAck *msg) {

  if(mwGetBuffer_error(b)) return;

  guint16_get(b, &msg->major);
  guint16_get(b, &msg->minor);
  guint32_get(b, &msg->srvrcalc_addr);

  /** @todo: get a better handle on what versions support what parts
      of this message. eg: minor version 0x0018 doesn't send the
      following */
  if(msg->major >= 0x1e && msg->minor > 0x18) {
    guint32_get(b, &msg->magic);
    mwOpaque_get(b, &msg->data);
  }
}
Пример #12
0
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;
}
Пример #13
0
static void request_get(struct mwGetBuffer *b, struct mwStorageReq *req) {
  guint32 id, count, junk;

  if(mwGetBuffer_error(b)) return;

  guint32_get(b, &id);
  guint32_get(b, &req->result_code);

  if(req->action == action_loaded) {
    guint32_get(b, &count);

    if(count > 0) {
      guint32_get(b, &junk);
      guint32_get(b, &req->item->key);

      mwOpaque_clear(&req->item->data);
      mwOpaque_get(b, &req->item->data);
    }
  }
}
Пример #14
0
static void mwMessageHead_get(struct mwGetBuffer *b, struct mwMessage *msg) {

  if(mwGetBuffer_error(b)) return;

  guint16_get(b, &msg->type);
  guint16_get(b, &msg->options);
  guint32_get(b, &msg->channel);

  if(msg->options & mwMessageOption_HAS_ATTRIBS)
    mwOpaque_get(b, &msg->attribs);
}
Пример #15
0
static void MESSAGE_recv(struct mwServiceConference *srvc,
			 struct mwConference *conf,
			 struct mwGetBuffer *b) {

  /* - look up who send the message by their id
     - trigger the event
  */

  guint16 id;
  guint32 type;
  struct mwLoginInfo *m;

  /* an empty buffer isn't an error, just ignored */
  if(! mwGetBuffer_remaining(b)) return;

  guint16_get(b, &id);
  guint32_get(b, &type); /* reuse type variable */
  guint32_get(b, &type);

  if(mwGetBuffer_error(b)) return;

  m = MEMBER_FIND(conf, id);
  if(! m) {
    g_warning("received message type 0x%04x from"
	      " unknown conference member %u", type, id);
    return;
  }
  
  switch(type) {
  case 0x01:  /* type is text */
    text_recv(srvc, conf, m, b);
    break;

  case 0x02:  /* type is data */
    data_recv(srvc, conf, m, b);
    break;

  default:
    g_warning("unknown message type 0x%4x received in conference", type);
  }
}
Пример #16
0
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;
}
Пример #17
0
static int recv_INFO(struct mwPlace *place,
		     struct mwGetBuffer *b) {

  int ret = 0;
  guint32 skip = 0;
  guint32 section = 0;

  guint32_get(b, &skip);
  guint32_get(b, &section);
  mwGetBuffer_advance(b, skip);

  if(! section) {
    /* this is a place info rather than member info */
    if(place->title) g_free(place->title);
    mwGetBuffer_advance(b, 2);
    mwString_get(b, &place->title);

    place_state(place, mwPlace_JOINED);
    ret = send_SECTION_LIST(place, place->section);
  }

  return ret;
}
Пример #18
0
static void enc_offer_get(struct mwGetBuffer *b,
			  struct mwEncryptOffer *enc) {
  guint32 skip;

  if(mwGetBuffer_error(b)) return;

  guint16_get(b, &enc->mode);
  guint32_get(b, &skip);

  if(skip >= 7) {
    guint32 count;

    guint32_get(b, &count);

    while(count-- && (! mwGetBuffer_error(b))) {
      struct mwEncryptItem *ei = g_new0(struct mwEncryptItem, 1);
      mwEncryptItem_get(b, ei);
      enc->items = g_list_append(enc->items, ei);
    }

    guint16_get(b, &enc->extra);
    gboolean_get(b, &enc->flag);
  }
Пример #19
0
guint32 mwStorageUnit_asInteger(struct mwStorageUnit *item,
				guint32 val) {
  struct mwGetBuffer *b;
  guint32 v;

  g_return_val_if_fail(item != NULL, val);

  b = mwGetBuffer_wrap(&item->data);

  guint32_get(b, &v);
  if(! mwGetBuffer_error(b)) val = v;
  mwGetBuffer_free(b);

  return val;
}
Пример #20
0
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;
}
Пример #21
0
static int recv_SECTION_PEER_JOIN(struct mwPlace *place,
				  struct mwGetBuffer *b) {
  struct mwServicePlace *srvc;
  struct place_member *pm;
  guint32 section;
  int ret = 0;

  srvc = place->service;

  guint32_get(b, &section);
  if(! section) {
    g_info("SECTION_PEER_JOIN with section 0x00");
    return 0;
  }

  mwGetBuffer_advance(b, 4);

  pm = g_new0(struct place_member, 1);
  guint32_get(b, &pm->place_id);
  guint16_get(b, &pm->member_type);
  mwIdBlock_get(b, &pm->idb);
  mwString_get(b, &pm->login_id);
  mwString_get(b, &pm->name);
  guint16_get(b, &pm->login_type);
  guint32_get(b, &pm->unknown_a);
  guint32_get(b, &pm->unknown_b);

  PUT_MEMBER(place, pm);
  if(srvc->handler && srvc->handler->peerJoined)
    srvc->handler->peerJoined(place, &pm->idb);

  if(pm->place_id == place->our_id)
    place_opened(place);

  return ret;
}