Exemple #1
0
static int send_client_response_buffered(conn_info *conn, char **response_buffers, int *buf_sizes, int num_bufs) {
    // Copy the buffers to the output buffer
    int res = 0;
    for (int i=0; i< num_bufs; i++) {
        res = circbuf_write(&conn->output, response_buffers[i], buf_sizes[i]);
        if (res) break;
    }
    return res;
}
Exemple #2
0
static int send_client_response_direct(conn_info *conn, char **response_buffers, int *buf_sizes, int num_bufs) {
    // Stack allocate the iovectors
    struct iovec *vectors = alloca(num_bufs * sizeof(struct iovec));

    // Setup all the pointers
    ssize_t total_bytes = 0;
    for (int i=0; i < num_bufs; i++) {
        vectors[i].iov_base = response_buffers[i];
        vectors[i].iov_len = buf_sizes[i];
        total_bytes += buf_sizes[i];
    }

    // Perform the write
    ssize_t sent = writev(conn->client.fd, vectors, num_bufs);
    if (sent == total_bytes) return 0;

    // Check for a fatal error
    if (sent == -1) {
        if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) {
            syslog(LOG_ERR, "Failed to send() to connection [%d]! %s.",
                    conn->client.fd, strerror(errno));
            close_client_connection(conn);
            return 1;
        }
    }

    // Figure out which buffer we left off on
    int skip_bytes = 0;
    int index = 0;
    for (index; index < num_bufs; index++) {
        skip_bytes += buf_sizes[index];
        if (skip_bytes > sent) {
            skip_bytes -= buf_sizes[index];
            break;
        }
    }

    // Copy the buffers
    int res, offset;
    for (int i=index; i < num_bufs; i++) {
        offset = 0;
        if (i == index && skip_bytes < sent) {
            offset = sent - skip_bytes;
        }
        res = circbuf_write(&conn->output, response_buffers[i] + offset, buf_sizes[i] - offset);
        if (res) return 1;
    }

    // Setup the async write
    conn->use_write_buf = 1;
    ev_io_start(conn->thread_ev->loop, &conn->write_client);

    // Done
    return 0;
}
static int send_proxy_msg_buffered(conn_info *conn, char *msg_buffer, int buf_size) {
    // Might not be using buffered writes anymore
    if (!conn->use_write_buf) {
        return send_proxy_msg_direct(conn, msg_buffer, buf_size);
    }

    // Copy the buffers to the output buffer
    int res = 0;
    return circbuf_write(&conn->output, msg_buffer, buf_size);

}
Exemple #4
0
/**
 * Invoked when a UDP connection has a message ready to be read.
 * We need to take care to add the data to our buffers, and then
 * invoke the connection handlers who have the business logic
 * of what to do.
 */
static void handle_udp_message(ev_io *watch, int ready_events) {
    while (1) {
        // Get the associated connection struct
        conn_info *conn = watch->data;

        // Clear the input buffer
        circbuf_clear(&conn->input);

        // Build the IO vectors to perform the read
        struct iovec vectors[2];
        int num_vectors;
        circbuf_setup_readv_iovec(&conn->input, (struct iovec*)&vectors, &num_vectors);

        /*
         * Issue the read, always use the first vector.
         * since we just cleared the buffer, and it should
         * be a contiguous buffer.
         */
        assert(num_vectors == 1);
        ssize_t read_bytes = recv(watch->fd, vectors[0].iov_base,
                                    vectors[0].iov_len, 0);

        // Make sure we actually read something
        if (read_bytes == 0) {
            syslog(LOG_DEBUG, "Got empty UDP packet. [%d]\n", watch->fd);
            return;

        } else if (read_bytes == -1) {
            if (errno != EAGAIN && errno != EINTR) {
                syslog(LOG_ERR, "Failed to recv() from connection [%d]! %s.",
                        watch->fd, strerror(errno));
            }
            return;
        }

        // Update the write cursor
        circbuf_advance_write(&conn->input, read_bytes);

        // UDP clients don't need to append newlines to the messages like
        // TCP clients do, but our parser requires them.  Append one if
        // it's not present.
        if (conn->input.buffer[conn->input.write_cursor - 1] != '\n')
            circbuf_write(&conn->input, "\n", 1);

        // Get the user data
        worker_ev_userdata *data = ev_userdata();

        // Invoke the connection handler
        statsite_conn_handler handle = {data->netconf->config, watch->data};
        handle_client_connect(&handle);
    }
}
static int send_proxy_msg_direct(conn_info *conn, char *msg_buffer, int buf_size) {
    // Stack allocate the iovectors
    struct iovec vector;

    // Setup all the pointers
    vector.iov_base = msg_buffer;
	vector.iov_len = buf_size;

    // Perform the write
    ssize_t sent = writev(conn->client.fd, &vector, 1);
    if (sent == buf_size) return 0;

    // Check for a fatal error
    if (sent == -1) {
        if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) {
            syslog(LOG_ERR, "Failed to send() to connection [%d]! %s.",
                    conn->client.fd, strerror(errno));

            // Probably want to try and reopen connection here???
            close_client_connection(conn);
            return 1;
        }
    }

    // Copy unsent data to circ buffer
    int res;
    if (sent < buf_size) {
		res = circbuf_write(&conn->output, msg_buffer + sent, buf_size - sent);
		if (res) {
			return 1;
		}
    }

    // Setup the async write
    conn->use_write_buf = 1;
    incref_client_connection(conn);
    schedule_async(conn->netconf, SCHEDULE_WATCHER, &conn->write_client);

    // Done
    return 0;
}