/** * Encode a BFCP message with variable arguments * * @param mb Mbuf to encode into * @param prim BFCP Primitive * @param confid Conference ID * @param tid Transaction ID * @param userid User ID * @param attrc Number of attributes * @param ap Variable argument of attributes * * @return 0 if success, otherwise errorcode */ int bfcp_msg_vencode(struct mbuf *mb, enum bfcp_prim prim, uint32_t confid, uint16_t tid, uint16_t userid, uint32_t attrc, va_list ap) { size_t start; uint32_t i; uint16_t len; int err = 0; if (!mb) return EINVAL; start = mb->pos; mb->pos += BFCP_HDR_SIZE; for (i=0; i<attrc; i++) { uint16_t type = va_arg(ap, int); const void *v = va_arg(ap, const void *); bool mand = false; if (!v) continue; err = bfcp_attr_encode(mb, mand, type, v); if (err) return err; } /* header */ len = (mb->pos - start - BFCP_HDR_SIZE) / 4; mb->pos = start; err = bfcp_hdr_encode(mb, prim, len, confid, tid, userid); mb->pos = mb->end; return err; }
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; }