Exemple #1
0
/*
 * This function allow the core to invoke the closing connection process
 * when some connection was not proceesed due to a premature close or similar
 * exception, it also take care of invoke the STAGE_40 and STAGE_50 plugins events
 */
static void mk_request_premature_close(int http_status, struct mk_http_session *cs)
{
    struct mk_http_request *sr;
    struct mk_list *sr_list = &cs->request_list;
    struct mk_list *host_list = &mk_config->hosts;

    /*
     * If the connection is too premature, we need to allocate a temporal session_request
     * to do not break the plugins stages
     */
    if (mk_list_is_empty(sr_list) == 0) {
        sr = &cs->sr_fixed;
        memset(sr, 0, sizeof(struct mk_http_request));
        mk_http_request_init(cs, sr);
        mk_list_add(&sr->_head, &cs->request_list);
    }
    else {
        sr = mk_list_entry_first(sr_list, struct mk_http_request, _head);
    }

    /* Raise error */
    if (http_status > 0) {
        if (!sr->host_conf) {
            sr->host_conf = mk_list_entry_first(host_list, struct host, _head);
        }
        mk_http_error(http_status, cs, sr);

        /* STAGE_40, request has ended */
        mk_plugin_stage_run_40(cs, sr);
    }
Exemple #2
0
struct cache_req_t *cache_req_new() {
  struct mk_list *pool = pthread_getspecific(cache_req_pool);
  struct cache_req_t *req;

    if (mk_list_is_empty(pool) == -1) {
        // printf("reusing an exhisting request!\n");
        req = mk_list_entry_first(pool, struct cache_req_t, _head);

        mk_list_del(&req->_head);

        if (req->buf->filled) {
            pipe_buf_flush(req->buf);
        }

    }
Exemple #3
0
void mk_cheetah_cmd_plugins_print_stage(struct mk_list *list, const char *stage,
                                        int stage_bw)
{
    struct plugin *p;
    struct mk_list *head;

    if (mk_list_is_empty(list) == 0) {
        return;
    }

    CHEETAH_WRITE("%s[%s]%s", ANSI_BOLD ANSI_YELLOW, stage, ANSI_RESET);

    mk_list_foreach(head, list) {
        p = mk_list_entry(head, struct plugin, _head);
        if (p->hooks & stage_bw) {
            CHEETAH_WRITE("\n  [%s] %s v%s on \"%s\"",
                          p->shortname, p->name, p->version, p->path);
        }
    }
Exemple #4
0
/*
 * Copy inherit bytes from old chunk to new chunk and set as current
 * chunk.
 */
int fcgi_fd_set_chunk(struct fcgi_fd *fd, struct chunk *a, size_t inherit)
{
	struct chunk *b = fd->chunk;
	size_t b_pos, a_pos;
	struct chunk_ptr tmp;

	chunk_retain(a);

	if (b && inherit > 0) {
		check(b->write >= inherit,
			"Not enough used on old chunk to inherit.");
		check(a->size - a->write > inherit,
			"Not enough free space on new chunk to inherit.");

		a_pos = a->write;
		b_pos = b->write - inherit;

		memcpy(a->data + a_pos, b->data + b_pos, inherit);

		a_pos     += inherit;
		tmp.parent = a;
		tmp.len    = a->size - a_pos;
		tmp.data   = a->data + a_pos;

		check(!chunk_set_write_ptr(a, tmp),
			"Failed to set new write pointer.");
		chunk_release(b);
	} else if (b) {
		chunk_release(b);
	} else {
		check(inherit == 0, "There are no chunks to inherit from.");
	}

	fd->chunk = a;
	return 0;
error:
	if (mk_list_is_empty(&a->_head)) {
		mk_list_del(&a->_head);
	}
	return -1;
}
Exemple #5
0
/*
 * Check if a connection can stay open using
 * the keepalive headers vars and Monkey configuration as criteria
 */
int mk_http_keepalive_check(struct client_session *cs)
{
    struct session_request *sr_node;
    struct mk_list *sr_head;

    if (mk_list_is_empty(&cs->request_list) == 0) {
        return -1;
    }

    sr_head = &cs->request_list;
    sr_node = mk_list_entry_last(sr_head, struct session_request, _head);
    if (config->keep_alive == MK_FALSE || sr_node->keep_alive == MK_FALSE) {
        return -1;
    }

    /* Old client without Connection header */
    if (sr_node->protocol < MK_HTTP_PROTOCOL_11 &&
            sr_node->connection.len <= 0) {
        return -1;
    }

    /* Old client and content length to send is unknown */
    if (sr_node->protocol < MK_HTTP_PROTOCOL_11 &&
            sr_node->headers.content_length < 0) {
        return -1;
    }

    /* Connection was forced to close */
    if (sr_node->close_now == MK_TRUE) {
        return -1;
    }

    /* Client has reached keep-alive connections limit */
    if (cs->counter_connections >= config->max_keep_alive_request) {
        return -1;
    }

    return 0;
}
Exemple #6
0
int mk_conn_read(int socket)
{
    int ret;
    int status;
    struct mk_http_session *cs;
    struct mk_http_request *sr;
    struct sched_list_node *sched;

    MK_TRACE("[FD %i] Connection Handler / read", socket);

    /* Plugin hook */
    ret = mk_plugin_event_read(socket);

    switch (ret) {
    case MK_PLUGIN_RET_EVENT_OWNED:
        return MK_PLUGIN_RET_CONTINUE;
    case MK_PLUGIN_RET_EVENT_CLOSE:
        return -1;
    case MK_PLUGIN_RET_EVENT_CONTINUE:
        break; /* just return controller to invoker */
    }

    sched = mk_sched_get_thread_conf();
    cs = mk_http_session_get(socket);
    if (!cs) {
        /* Check if is this a new connection for the Scheduler */
        if (!mk_sched_get_connection(sched, socket)) {
            MK_TRACE("[FD %i] Registering new connection");
            if (mk_sched_register_client(socket, sched) == -1) {
                MK_TRACE("[FD %i] Close requested", socket);
                return -1;
            }
            /*
             * New connections are not registered yet into the
             * events loop, we need to do it manually:
             */
            mk_event_add(sched->loop, socket, MK_EVENT_READ, NULL);
            return 0;
        }

        /* Create session for the client */
        MK_TRACE("[FD %i] Create session", socket);
        cs = mk_http_session_create(socket, sched);
        if (!cs) {
            return -1;
        }
    }

    /* Invoke the read handler, on this case we only support HTTP (for now :) */
    ret = mk_http_handler_read(socket, cs);
    if (ret > 0) {
        if (mk_list_is_empty(&cs->request_list) == 0) {
            /* Add the first entry */
            sr = &cs->sr_fixed;
            mk_list_add(&sr->_head, &cs->request_list);
            mk_http_request_init(cs, sr);
        }
        else {
            sr = mk_list_entry_first(&cs->request_list, struct mk_http_request, _head);
        }

        status = mk_http_parser(sr, &cs->parser,
                                cs->body, cs->body_length);
        if (status == MK_HTTP_PARSER_OK) {
            MK_TRACE("[FD %i] HTTP_PARSER_OK", socket);
            mk_http_status_completed(cs);
            mk_event_add(sched->loop, socket, MK_EVENT_WRITE, NULL);
        }
        else if (status == MK_HTTP_PARSER_ERROR) {
            mk_http_session_remove(socket);
            MK_TRACE("[FD %i] HTTP_PARSER_ERROR", socket);
            return -1;
        }
        else {
            MK_TRACE("[FD %i] HTTP_PARSER_PENDING", socket);
        }
    }

    if (ret == -EAGAIN) {
        return 1;
    }

    return ret;
}
Exemple #7
0
int mk_channel_write(struct mk_channel *channel)
{
    ssize_t bytes = -1;
    struct mk_iov *iov;
    mk_ptr_t *ptr;
    struct mk_stream *stream;

    if (mk_list_is_empty(&channel->streams) == 0) {
        MK_TRACE("[CH %i] CHANNEL_EMPTY", channel->fd);
        return MK_CHANNEL_EMPTY;
    }

    /* Get the input source */
    stream = mk_list_entry_first(&channel->streams, struct mk_stream, _head);

    /*
     * Based on the Stream type we consume on that way, not all inputs
     * requires to read from buffer, e.g: Static File, Pipes.
     */
    if (channel->type == MK_CHANNEL_SOCKET) {
        if (stream->type == MK_STREAM_FILE) {
            bytes = channel_write_stream_file(channel, stream);
        }
        else if (stream->type == MK_STREAM_IOV) {
            MK_TRACE("[CH %i] STREAM_IOV, wrote %lu bytes",
                     channel->fd, stream->bytes_total);

            iov   = stream->buffer;
            bytes = mk_sched_conn_writev(channel, iov);
            if (bytes > 0) {
                /* Perform the adjustment on mk_iov */
                mk_iov_consume(iov, bytes);
            }
        }
        else if (stream->type == MK_STREAM_PTR) {
            MK_TRACE("[CH %i] STREAM_PTR, bytes=%lu",
                     channel->fd, stream->bytes_total);

            ptr = stream->buffer;
            bytes = mk_sched_conn_write(channel, ptr->data, ptr->len);
            if (bytes > 0) {
                /* FIXME OFFSET */
            }
        }

        if (bytes > 0) {
            mk_stream_bytes_consumed(stream, bytes);

            /* notification callback, optional */
            if (stream->cb_bytes_consumed) {
                stream->cb_bytes_consumed(stream, bytes);
            }

            if (stream->bytes_total == 0) {
                MK_TRACE("Stream done, unlinking");

                if (stream->cb_finished) {
                    stream->cb_finished(stream);
                }

                if (stream->preserve == MK_FALSE) {
                    mk_stream_unlink(stream);
                }
            }

            if (mk_list_is_empty(&channel->streams) == 0) {
                MK_TRACE("[CH %i] CHANNEL_DONE", channel->fd);
                return MK_CHANNEL_DONE;
            }

            MK_TRACE("[CH %i] CHANNEL_FLUSH", channel->fd);
            return MK_CHANNEL_FLUSH;
        }
        else if (bytes <= 0) {
            if (stream->cb_exception) {
                stream->cb_exception(stream, errno);
            }
            return MK_CHANNEL_ERROR;
        }
    }

    return MK_CHANNEL_UNKNOWN;
}