Пример #1
0
void buffer_append_strftime(buffer *b, const char *format, const struct tm *tm) {
	size_t r;
	char* buf;
	force_assert(NULL != b);
	force_assert(NULL != tm);

	if (NULL == format || '\0' == format[0]) {
		/* empty format */
		buffer_string_prepare_append(b, 0);
		return;
	}

	buf = buffer_string_prepare_append(b, 255);
	r = strftime(buf, buffer_string_space(b), format, tm);

	/* 0 (in some apis buffer_string_space(b)) signals the string may have
	 * been too small; but the format could also just have lead to an empty
	 * string
	 */
	if (0 == r || r >= buffer_string_space(b)) {
		/* give it a second try with a larger string */
		buf = buffer_string_prepare_append(b, 4095);
		r = strftime(buf, buffer_string_space(b), format, tm);
	}

	if (r >= buffer_string_space(b)) r = 0;

	buffer_commit(b, r);
}
Пример #2
0
void chunkqueue_get_memory(chunkqueue *cq, char **mem, size_t *len, size_t min_size, size_t alloc_size) {
    static const size_t REALLOC_MAX_SIZE = 256;
    chunk *c;
    buffer *b;
    char *dummy_mem;
    size_t dummy_len;

    force_assert(NULL != cq);
    if (NULL == mem) mem = &dummy_mem;
    if (NULL == len) len = &dummy_len;

    /* default values: */
    if (0 == min_size) min_size = 1024;
    if (0 == alloc_size) alloc_size = 4096;
    if (alloc_size < min_size) alloc_size = min_size;

    if (NULL != cq->last && MEM_CHUNK == cq->last->type) {
        size_t have;

        b = cq->last->mem;
        have = buffer_string_space(b);

        /* unused buffer: allocate space */
        if (buffer_string_is_empty(b)) {
            buffer_string_prepare_copy(b, alloc_size);
            have = buffer_string_space(b);
        }
        /* if buffer is really small just make it bigger */
        else if (have < min_size && b->size <= REALLOC_MAX_SIZE) {
            size_t cur_len = buffer_string_length(b);
            size_t new_size = cur_len + min_size, append;
            if (new_size < alloc_size) new_size = alloc_size;

            append = new_size - cur_len;
            if (append >= min_size) {
                buffer_string_prepare_append(b, append);
                have = buffer_string_space(b);
            }
        }

        /* return pointer into existing buffer if large enough */
        if (have >= min_size) {
            *mem = b->ptr + buffer_string_length(b);
            *len = have;
            return;
        }
    }

    /* allocate new chunk */
    c = chunkqueue_get_unused_chunk(cq);
    c->type = MEM_CHUNK;
    chunkqueue_append_chunk(cq, c);

    b = c->mem;
    buffer_string_prepare_append(b, alloc_size);

    *mem = b->ptr + buffer_string_length(b);
    *len = buffer_string_space(b);
}
Пример #3
0
static void test_buffer_string_space(void) {
	buffer *b = buffer_init();
	size_t space;

	space = buffer_string_space(b);
	assert(0 == space);
	buffer_copy_string_len(b, CONST_STR_LEN(""));
	space = buffer_string_space(b);
	assert(space > 0);
	assert(space + buffer_string_length(b) == b->size - 1);
	buffer_commit(b, b->size - 1);
	assert(b->used == b->size);
	space = buffer_string_space(b);
	assert(0 == space);

	buffer_free(b);
}
Пример #4
0
static int proxy_demux_response(server *srv, handler_ctx *hctx) {
	int fin = 0;
	int b;
	ssize_t r;

	plugin_data *p    = hctx->plugin_data;
	connection *con   = hctx->remote_conn;
	int proxy_fd       = hctx->fd;

	/* check how much we have to read */
	if (ioctl(hctx->fd, FIONREAD, &b)) {
		log_error_write(srv, __FILE__, __LINE__, "sd",
				"ioctl failed: ",
				proxy_fd);
		return -1;
	}


	if (p->conf.debug) {
		log_error_write(srv, __FILE__, __LINE__, "sd",
				"proxy - have to read:", b);
	}

	if (b > 0) {
		buffer_string_prepare_append(hctx->response, b);

		if (-1 == (r = read(hctx->fd, hctx->response->ptr + buffer_string_length(hctx->response), buffer_string_space(hctx->response)))) {
			if (errno == EAGAIN) return 0;
			log_error_write(srv, __FILE__, __LINE__, "sds",
					"unexpected end-of-file (perhaps the proxy process died):",
					proxy_fd, strerror(errno));
			return -1;
		}

		/* this should be catched by the b > 0 above */
		force_assert(r);

		buffer_commit(hctx->response, r);

#if 0
		log_error_write(srv, __FILE__, __LINE__, "sdsbs",
				"demux: Response buffer len", hctx->response->used, ":", hctx->response, ":");
#endif

		if (0 == con->got_response) {
			con->got_response = 1;
			buffer_string_prepare_copy(hctx->response_header, 1023);
		}

		if (0 == con->file_started) {
			char *c;

			/* search for the \r\n\r\n in the string */
			if (NULL != (c = buffer_search_string_len(hctx->response, CONST_STR_LEN("\r\n\r\n")))) {
				size_t hlen = c - hctx->response->ptr + 4;
				size_t blen = buffer_string_length(hctx->response) - hlen;
				/* found */

				buffer_append_string_len(hctx->response_header, hctx->response->ptr, hlen);
#if 0
				log_error_write(srv, __FILE__, __LINE__, "sb", "Header:", hctx->response_header);
#endif
				/* parse the response header */
				proxy_response_parse(srv, con, p, hctx->response_header);

				/* enable chunked-transfer-encoding */
				if (con->request.http_version == HTTP_VERSION_1_1 &&
				    !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
					con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
				}

				con->file_started = 1;
				if (blen > 0) http_chunk_append_mem(srv, con, c + 4, blen);
				buffer_reset(hctx->response);
				joblist_append(srv, con);
			}
		} else {
			http_chunk_append_buffer(srv, con, hctx->response);
			joblist_append(srv, con);
			buffer_reset(hctx->response);
		}

	} else {
		/* reading from upstream done */
		con->file_finished = 1;

		http_chunk_close(srv, con);
		joblist_append(srv, con);

		fin = 1;
	}

	return fin;
}