Esempio n. 1
0
/**
 * Decode a BFCP message from a buffer
 *
 * @param msgp Pointer to allocated and decoded BFCP message
 * @param mb   Mbuf to decode from
 * @param src  Source network address (optional)
 *
 * @return 0 if success, otherwise errorcode
 */
int bfcp_msg_decode(struct bfcp_msg **msgp, struct mbuf *mb,
		    const struct sa *src)
{
	struct bfcp_msg *msg;
	size_t start, extra;
	int err;

	if (!msgp || !mb)
		return EINVAL;

	start = mb->pos;

	msg = mem_zalloc(sizeof(*msg), destructor);
	if (!msg)
		return ENOMEM;

	err = bfcp_hdr_decode(mb, &msg->hdr);
	if (err) {
		mb->pos = start;
		goto out;
	}

	extra = mbuf_get_left(mb) - 4*msg->hdr.len;

	while (mbuf_get_left(mb) - extra >= ATTR_HDR_SIZE) {

		struct bfcp_attr *attr;

		err = bfcp_attr_decode(&attr, mb);
		if (err)
			break;

		list_append(&msg->attrl, &attr->le, attr);
	}

	if (src)
		msg->src = *src;

 out:
	if (err)
		mem_deref(msg);
	else
		*msgp = msg;

	return err;
}
Esempio n. 2
0
int build_msg_fragments( std::vector<mbuf_t*> &fragBufs, mbuf_t *msgBuf, size_t maxMsgSize )
{
  assert(kHeaderWithFragSize < maxMsgSize);

  int err = 0;
  size_t bufSize = msgBuf->end;
  if (bufSize < maxMsgSize)
  {
    fragBufs.push_back(msgBuf);
    mem_ref(msgBuf);
  }
  else
  {
    size_t start = msgBuf->pos;

    size_t payloadSize = bufSize - kHeaderSize;
    size_t maxFragPayloadSize = (maxMsgSize - kHeaderWithFragSize) & ~0x3;
    size_t fragmentCount = 
      (payloadSize + maxFragPayloadSize - 1) / maxFragPayloadSize;

    std::vector<mbuf_t*> bufs;
    bufs.reserve(fragmentCount);
    
    bfcp_hdr_t header;
    err = bfcp_hdr_decode(&header, msgBuf);
    assert(!err);
    assert(!header.f);

    size_t remainPayloadSize = payloadSize;
    for (size_t i = 0; i < fragmentCount; ++i)
    {
      mbuf_t *buf = mbuf_alloc(maxMsgSize);
      if (!buf)
      {
        err = ENOMEM;
        break;
      }
      bufs.push_back(buf);

      header.f = 1;
      header.fragoffset = i * maxFragPayloadSize / 4;
      size_t actualPayloadSize = (std::min)(maxFragPayloadSize, remainPayloadSize);
      header.fraglen = actualPayloadSize / 4;
      remainPayloadSize -= actualPayloadSize;
      err = bfcp_hdr_encode(buf, &header);
      if (err) break;

      mbuf_write_mem(buf, msgBuf->buf + msgBuf->pos, actualPayloadSize);
      msgBuf->pos += actualPayloadSize;
    }
    if (err)
    {
      for (auto buf : bufs)
      {
        mem_deref(buf);
      }
    }
    else
    {
      assert(msgBuf->pos == msgBuf->end);
      msgBuf->pos = start;
      fragBufs.insert(fragBufs.end(), bufs.begin(), bufs.end());
    }
  }
  return err;
}