/* writes <len> bytes from message <msg> to the channel's buffer. Returns -1 in * case of success, -2 if the message is larger than the buffer size, or the * number of bytes available otherwise. The send limit is automatically * adjusted to the amount of data written. FIXME-20060521: handle unaligned * data. Note: this function appends data to the buffer's output and possibly * overwrites any pending input data which are assumed not to exist. */ int bo_inject(struct channel *chn, const char *msg, int len) { int max; if (len == 0) return -1; if (len > chn->buf->size) { /* we can't write this chunk and will never be able to, because * it is larger than the buffer. This must be reported as an * error. Then we return -2 so that writers that don't care can * ignore it and go on, and others can check for this value. */ return -2; } max = buffer_realign(chn->buf); if (len > max) return max; memcpy(chn->buf->p, msg, len); chn->buf->o += len; chn->buf->p = b_ptr(chn->buf, len); chn->total += len; return -1; }
int tcpclient_sendall(tcpclient_t *client, const char *buf, size_t len) { buffer_t *sendq = &client->send_queue; if (client->addr == NULL) { stats_error_log("tcpclient[%s]: Cannot send before connect!", client->name); return 1; } else { // Does nothing if we're already connected, triggers a // reconnect if backoff has expired. tcpclient_connect(client); } if (buffer_datacount(&client->send_queue) >= client->config->max_send_queue) { if (client->failing == 0) { stats_error_log("tcpclient[%s]: send queue for %s client is full (at %zd bytes, max is %" PRIu64 " bytes), dropping data", client->name, tcpclient_state_name[client->state], buffer_datacount(&client->send_queue), client->config->max_send_queue); client->failing = 1; } return 2; } if (buffer_spacecount(sendq) < len) { if (buffer_realign(sendq) != 0) { stats_error_log("tcpclient[%s]: Unable to realign send queue", client->name); return 3; } } while (buffer_spacecount(sendq) < len) { if (buffer_expand(sendq) != 0) { stats_error_log("tcpclient[%s]: Unable to allocate additional memory for send queue, dropping data", client->name); return 4; } } memcpy(buffer_tail(sendq), buf, len); buffer_produced(sendq, len); if (client->state == STATE_CONNECTED) { client->write_watcher.started = true; ev_io_start(client->loop, &client->write_watcher.watcher); } return 0; }