size_t dbuf_get(struct DBuf* dyn, char* buf, size_t length) { size_t moved = 0; size_t chunk; const char* b; while (length > 0 && (b = dbuf_map(dyn, &chunk)) != 0) { if (chunk > length) chunk = length; memcpy(buf, b, chunk); dbuf_delete(dyn, chunk); buf += chunk; length -= chunk; moved += chunk; } return moved; }
/** Copy data from a buffer and remove what was copied. * @param[in,out] dyn Buffer to copy from. * @param[out] buf Buffer to write to. * @param[in] length Maximum number of bytes to copy. * @return Number of bytes actually copied. */ unsigned int dbuf_get(struct DBuf *dyn, char *buf, unsigned int length) { unsigned int moved = 0; unsigned int chunk; const char *b; assert(0 != dyn); assert(0 != buf); while (length > 0 && (b = dbuf_map(dyn, &chunk)) != 0) { if (chunk > length) chunk = length; memcpy(buf, b, chunk); dbuf_delete(dyn, chunk); buf += chunk; length -= chunk; moved += chunk; } return moved; }
/* ** send_queued ** This function is called from the main select-loop (or whatever) ** when there is a chance the some output would be possible. This ** attempts to empty the send queue as far as possible... */ int send_queued(aClient *to) { char *msg; int len, rlen, more = 0; aClient *bysptr = NULL; /* ** Once socket is marked dead, we cannot start writing to it, ** even if the error is removed... */ if (IsDead(to)) { /* ** Actually, we should *NEVER* get here--something is ** not working correct if send_queued is called for a ** dead socket... --msa */ return -1; } #ifdef ZIP_LINKS /* ** Here, we must make sure than nothing will be left in to->zip->outbuf ** This buffer needs to be compressed and sent if all the sendQ is sent */ if ((to->flags & FLAGS_ZIP) && to->zip->outcount) { if (DBufLength(&to->sendQ) > 0) more = 1; else { msg = zip_buffer(to, NULL, &len, 1); if (len == -1) return dead_link(to, "fatal error in zip_buffer()"); if (dbuf_put(&to->sendQ, msg, len) < 0) { to->exitc = EXITC_MBUF; return dead_link(to, "Buffer allocation error for %s", get_client_name(to, FALSE)); } } } #endif while (DBufLength(&to->sendQ) > 0 || more) { msg = dbuf_map(&to->sendQ, &len); /* Returns always len > 0 */ if ((rlen = deliver_it(to, msg, len)) < 0) { if ( (IsConnecting(to) || IsHandshake(to)) && to->serv && to->serv->byuid[0]) { bysptr = find_uid(to->serv->byuid, NULL); if (bysptr && !MyConnect(bysptr)) { sendto_one(bysptr, ":%s NOTICE %s :" "Write error (%s) to %s, closing link", ME, bysptr->name, strerror(-rlen), to->name); } } return dead_link(to, "Write error (%s) to %s, closing link", strerror(-rlen), get_client_name(to, FALSE)); } (void)dbuf_delete(&to->sendQ, rlen); to->lastsq = DBufLength(&to->sendQ)/1024; if (rlen < len) /* ..or should I continue until rlen==0? */ break; #ifdef ZIP_LINKS if (DBufLength(&to->sendQ) == 0 && more) { /* ** The sendQ is now empty, compress what's left ** uncompressed and try to send it too */ more = 0; msg = zip_buffer(to, NULL, &len, 1); if (len == -1) return dead_link(to, "fatal error in zip_buffer()"); if (dbuf_put(&to->sendQ, msg, len) < 0) { to->exitc = EXITC_MBUF; return dead_link(to, "Buffer allocation error for %s", get_client_name(to, FALSE)); } } #endif } return (IsDead(to)) ? -1 : 0; }