Esempio n. 1
0
int mk_http_send_file(struct client_session *cs, struct session_request *sr)
{
    long int nbytes = 0;

    nbytes = mk_socket_send_file(cs->socket, sr->fd_file,
                                 &sr->bytes_offset, sr->bytes_to_send);

    if (nbytes > 0) {
        sr->bytes_to_send -= nbytes;
        if (sr->bytes_to_send == 0) {
            mk_server_cork_flag(cs->socket, TCP_CORK_OFF);
        }
    }

    sr->loop++;

    /*
     * In some circumstances when writing data, the connection can get broken.
     * So, we must be aware of that.
     *
     * Also, if for some reason the file that is being served changes it's size
     * we can get a zero bytes send as return value. We need to validate the
     * return values <= zero
     */
    if (mk_unlikely(nbytes <= 0)) {
        MK_TRACE("sendfile() = -1;");
        return EXIT_ABORT;
    }

    return sr->bytes_to_send;
}
Esempio n. 2
0
int mk_socket_ip_str(int socket_fd, char **buf, int size, unsigned long *len)
{
    int ret;
    struct sockaddr_storage addr;
    socklen_t s_len = sizeof(addr);

    ret = getpeername(socket_fd, (struct sockaddr *) &addr, &s_len);

    if (mk_unlikely(ret == -1)) {
        MK_TRACE("[FD %i] Can't get addr for this socket", socket_fd);
        return -1;
    }

    errno = 0;

    if(addr.ss_family == AF_INET) {
        if((inet_ntop(AF_INET, &((struct sockaddr_in *)&addr)->sin_addr,
                      *buf, size)) == NULL) {
            mk_warn("mk_socket_ip_str: Can't get the IP text form (%i)", errno);
            return -1;
        }
    }
    else if(addr.ss_family == AF_INET6) {
        if((inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr)->sin6_addr,
                      *buf, size)) == NULL) {
            mk_warn("mk_socket_ip_str: Can't get the IP text form (%i)", errno);
            return -1;
        }
    }

    *len = strlen(*buf);
    return 0;
}
Esempio n. 3
0
ssize_t mk_iov_send(int fd, struct mk_iov *mk_io)
{
    ssize_t n = writev(fd, mk_io->io, mk_io->iov_idx);
    if (mk_unlikely(n < 0)) {
        MK_TRACE( "[FD %i] writev() '%s'", fd, strerror(errno));
        return -1;
    }

    return n;
}
Esempio n. 4
0
static inline
struct mk_sched_conn *mk_server_listen_handler(struct mk_sched_worker *sched,
                                               void *data)
{
    int ret;
    int client_fd = -1;
    struct mk_sched_conn *conn;
    struct mk_server_listen *listener = data;

    client_fd = mk_socket_accept(listener->server_fd);
    if (mk_unlikely(client_fd == -1)) {
        MK_TRACE("[server] Accept connection failed: %s", strerror(errno));
        goto error;
    }

    conn = mk_sched_add_connection(client_fd, listener, sched);
    if (mk_unlikely(!conn)) {
        goto error;
    }

    ret = mk_event_add(sched->loop, client_fd,
                       MK_EVENT_CONNECTION, MK_EVENT_READ, conn);
    if (mk_unlikely(ret != 0)) {
        mk_err("[server] Error registering file descriptor: %s",
               strerror(errno));
        goto error;
    }

    sched->accepted_connections++;
    MK_TRACE("[server] New connection arrived: FD %i", client_fd);
    return conn;

error:
    if (client_fd != -1) {
        listener->network->network->close(client_fd);
    }

    return NULL;
}
Esempio n. 5
0
int _mkp_network_io_send_file(int socket_fd, int file_fd, off_t *file_offset,
                              size_t file_count)
{
    ssize_t bytes_written = -1;

    bytes_written = sendfile(socket_fd, file_fd, file_offset, file_count);

    if (mk_unlikely(bytes_written == -1)) {
        PLUGIN_TRACE("[FD %i] error from sendfile() = -1", socket_fd);
        return -1;
    }

    return bytes_written;
}
Esempio n. 6
0
ssize_t mk_iov_send(int fd, struct mk_iov *mk_io)
{
#ifdef __rtems__
    ssize_t n = rtems_writev(fd, mk_io->io, mk_io->iov_idx);
#else
    ssize_t n = writev(fd, mk_io->io, mk_io->iov_idx);
#endif
    if (mk_unlikely(n < 0)) {
        MK_TRACE( "[FD %i] writev() '%s'", fd, strerror(errno));
        return -1;
    }

    return n;
}
Esempio n. 7
0
static int mk_utils_gmt_cache_get(char **data, time_t date)
{
    unsigned int i;
    struct mk_gmt_cache *gcache = mk_cache_get(mk_cache_utils_gmt_text);

    if (mk_unlikely(!gcache)) {
        return MK_FALSE;
    }

    for (i = 0; i < MK_GMT_CACHES; i++) {
        if (date == gcache[i].time) {
            memcpy(*data, gcache[i].text, 32);
            gcache[i].hits++;
            return MK_TRUE;
        }
    }

    return MK_FALSE;
}
Esempio n. 8
0
int mk_http_method_get(char *body)
{
    int int_method, pos = 0;
    int max_len_method = 8;
    mk_ptr_t method;

    /* Max method length is 7 (GET/POST/HEAD/PUT/DELETE/OPTIONS) */
    pos = mk_string_char_search(body, ' ', max_len_method);
    if (mk_unlikely(pos <= 2 || pos >= max_len_method)) {
        return MK_HTTP_METHOD_UNKNOWN;
    }

    method.data = body;
    method.len = (unsigned long) pos;

    int_method = mk_http_method_check(method);

    return int_method;
}
Esempio n. 9
0
int mk_buffer_cat(mk_ptr_t *p, char *buf1, int len1, char *buf2, int len2)
{
    /* Validate lengths */
    if (mk_unlikely(len1 < 0 || len2 < 0)) {
         return -1;
    }

    /* alloc space */
    p->data = (char *) mk_mem_malloc(len1 + len2 + 1);

    /* copy data */
    memcpy(p->data, buf1, len1);
    memcpy(p->data + len1, buf2, len2);
    p->data[len1 + len2] = '\0';

    /* assign len */
    p->len = len1 + len2;

    return 0;
}
Esempio n. 10
0
void mk_server_loop(int server_fd)
{
    int ret;
    int remote_fd;

    /* Activate TCP_DEFER_ACCEPT */
    if (mk_socket_set_tcp_defer_accept(server_fd) != 0) {
            mk_warn("TCP_DEFER_ACCEPT failed");
    }

    /* Rename worker */
    mk_utils_worker_rename("monkey: server");
    mk_info("HTTP Server started");

    while (1) {
        remote_fd = mk_socket_accept(server_fd);

        if (mk_unlikely(remote_fd == -1)) {
            continue;
        }

#ifdef TRACE
        MK_TRACE("New connection arrived: FD %i", remote_fd);

        int i;
        struct sched_list_node *node;

        node = sched_list;
        for (i=0; i < config->workers; i++) {
            MK_TRACE("Worker Status");
            MK_TRACE(" WID %i / conx = %llu", node[i].idx, node[i].accepted_connections - node[i].closed_connections);
        }
#endif

        /* Assign socket to worker thread */
        ret = mk_sched_add_client(remote_fd);
        if (ret == -1) {
            close(remote_fd);
        }
    }
}
Esempio n. 11
0
int mk_http_request_end(int socket)
{
    int ka;
    struct client_session *cs;
    struct sched_list_node *sched;

    sched = mk_sched_get_thread_conf();
    cs = mk_session_get(socket);

    if (!cs) {
        MK_TRACE("[FD %i] Not found", socket);
        return -1;
    }

    if (mk_unlikely(!sched)) {
        MK_TRACE("Could not find sched list node :/");
        return -1;
    }

    /*
     * We need to ask to http_keepalive if this
     * connection can continue working or we must
     * close it.
     */
    ka = mk_http_keepalive_check(cs);
    mk_request_free_list(cs);

    if (ka < 0) {
        MK_TRACE("[FD %i] No KeepAlive mode, remove", socket);
        mk_session_remove(socket);
    }
    else {
        mk_request_ka_next(cs);
        mk_epoll_change_mode(sched->epoll_fd,
                             socket, MK_EPOLL_READ, MK_EPOLL_LEVEL_TRIGGERED);
        return 0;
    }

    return -1;
}
Esempio n. 12
0
int create_event(int efd, int fd, int init_mode, unsigned int behavior)
{
    int ret;
    struct epoll_event event = {0, {0}};

    event.data.fd = fd;
    event.events = EPOLLERR | EPOLLHUP | EPOLLRDHUP;

    if (behavior == MK_EPOLL_EDGE_TRIGGERED) {
        event.events |= EPOLLET;
    }

    switch (init_mode) {
    case MK_EPOLL_READ:
        event.events |= EPOLLIN;
        break;
    case MK_EPOLL_WRITE:
        event.events |= EPOLLOUT;
        break;
    case MK_EPOLL_RW:
        event.events |= EPOLLIN | EPOLLOUT;
        break;
    case MK_EPOLL_SLEEP:
        event.events = 0;
        break;
    }

    /* Add to epoll queue */
    ret = epoll_ctl(efd, EPOLL_CTL_ADD, fd, &event);
    if (mk_unlikely(ret < 0 && errno != EEXIST)) {
        perror("epoll_ctl");
        return ret;
    }

    return ret;
}
Esempio n. 13
0
int mk_http_init(struct client_session *cs, struct session_request *sr)
{
    int ret;
    int bytes = 0;
    struct mimetype *mime;

    MK_TRACE("HTTP Protocol Init");

    /* Request to root path of the virtualhost in question */
    if (sr->uri_processed.len == 1 && sr->uri_processed.data[0] == '/') {
        sr->real_path.data = sr->host_conf->documentroot.data;
        sr->real_path.len = sr->host_conf->documentroot.len;
    }

    /* Compose real path */
    if (sr->user_home == MK_FALSE) {
        int len;

        len = sr->host_conf->documentroot.len + sr->uri_processed.len;
        if (len < MK_PATH_BASE) {
            memcpy(sr->real_path_static,
                   sr->host_conf->documentroot.data,
                   sr->host_conf->documentroot.len);
            memcpy(sr->real_path_static + sr->host_conf->documentroot.len,
                   sr->uri_processed.data,
                   sr->uri_processed.len);
            sr->real_path_static[len] = '\0';
            sr->real_path.data = sr->real_path_static;
            sr->real_path.len = len;
        }
        else {
            ret = mk_buffer_cat(&sr->real_path,
                                sr->host_conf->documentroot.data,
                                sr->host_conf->documentroot.len,
                                sr->uri_processed.data,
                                sr->uri_processed.len);

            if (ret < 0) {
                MK_TRACE("Error composing real path");
                return EXIT_ERROR;
            }
        }
    }

    /* Check backward directory request */
    if (memmem(sr->uri_processed.data, sr->uri_processed.len,
               MK_HTTP_DIRECTORY_BACKWARD,
               sizeof(MK_HTTP_DIRECTORY_BACKWARD) - 1)) {
        return mk_request_error(MK_CLIENT_FORBIDDEN, cs, sr);
    }


    if (mk_file_get_info(sr->real_path.data, &sr->file_info) != 0) {
        /* if the requested resource doesn't exist,
         * check if some plugin would like to handle it
         */
        MK_TRACE("No file, look for handler plugin");
        ret = mk_plugin_stage_run(MK_PLUGIN_STAGE_30, cs->socket, NULL, cs, sr);
        if (ret == MK_PLUGIN_RET_CLOSE_CONX) {
            if (sr->headers.status > 0) {
                return mk_request_error(sr->headers.status, cs, sr);
            }
            else {
                return mk_request_error(MK_CLIENT_FORBIDDEN, cs, sr);
            }
        }
        else if (ret == MK_PLUGIN_RET_CONTINUE) {
            return MK_PLUGIN_RET_CONTINUE;
        }
        else if (ret == MK_PLUGIN_RET_END) {
            return EXIT_NORMAL;
        }

        if (sr->file_info.exists == MK_FALSE) {
            return mk_request_error(MK_CLIENT_NOT_FOUND, cs, sr);
        }
        else if (sr->stage30_blocked == MK_FALSE) {
            return mk_request_error(MK_CLIENT_FORBIDDEN, cs, sr);
        }
    }

    /* is it a valid directory ? */
    if (sr->file_info.is_directory == MK_TRUE) {
        /* Send redirect header if end slash is not found */
        if (mk_http_directory_redirect_check(cs, sr) == -1) {
            MK_TRACE("Directory Redirect");

            /* Redirect has been sent */
            return -1;
        }

        /* looking for an index file */
        mk_ptr_t index_file;
        char tmppath[MK_MAX_PATH];
        index_file = mk_request_index(sr->real_path.data, tmppath, MK_MAX_PATH);

        if (index_file.data) {
            if (sr->real_path.data != sr->real_path_static) {
                mk_ptr_t_free(&sr->real_path);
                sr->real_path = index_file;
                sr->real_path.data = mk_string_dup(index_file.data);
            }
            /* If it's static and it still fits */
            else if (index_file.len < MK_PATH_BASE) {
                memcpy(sr->real_path_static, index_file.data, index_file.len);
                sr->real_path_static[index_file.len] = '\0';
                sr->real_path.len = index_file.len;
            }
            /* It was static, but didn't fit */
            else {
                sr->real_path = index_file;
                sr->real_path.data = mk_string_dup(index_file.data);
            }

            mk_file_get_info(sr->real_path.data, &sr->file_info);
        }
    }

    /* Check symbolic link file */
    if (sr->file_info.is_link == MK_TRUE) {
        if (config->symlink == MK_FALSE) {
            return mk_request_error(MK_CLIENT_FORBIDDEN, cs, sr);
        }
        else {
            int n;
            char linked_file[MK_MAX_PATH];
            n = readlink(sr->real_path.data, linked_file, MK_MAX_PATH);
            if (n < 0) {
                return mk_request_error(MK_CLIENT_FORBIDDEN, cs, sr);
            }
        }
    }

    /* Plugin Stage 30: look for handlers for this request */
    if (sr->stage30_blocked == MK_FALSE) {
        ret  = mk_plugin_stage_run(MK_PLUGIN_STAGE_30, cs->socket, NULL, cs, sr);
        MK_TRACE("[FD %i] STAGE_30 returned %i", cs->socket, ret);
        switch (ret) {
        case MK_PLUGIN_RET_CONTINUE:
            return MK_PLUGIN_RET_CONTINUE;
        case MK_PLUGIN_RET_CLOSE_CONX:
            if (sr->headers.status > 0) {
                return mk_request_error(sr->headers.status, cs, sr);
            }
            else {
                return mk_request_error(MK_CLIENT_FORBIDDEN, cs, sr);
            }
        case MK_PLUGIN_RET_END:
            return EXIT_NORMAL;
        }
    }

    /*
     * Monkey listens for PUT and DELETE methods in addition to GET, POST and
     * HEAD, but it does not care about them, so if any plugin did not worked
     * on it, Monkey will return error 501 (501 Not Implemented).
     */
    if (sr->method == MK_HTTP_METHOD_PUT || sr->method == MK_HTTP_METHOD_DELETE ||
            sr->method == MK_HTTP_METHOD_UNKNOWN) {
        return mk_request_error(MK_SERVER_NOT_IMPLEMENTED, cs, sr);
    }

    /* counter connections */
    sr->headers.pconnections_left = (int)
                                    (config->max_keep_alive_request - cs->counter_connections);

    /* Set default value */
    mk_header_set_http_status(sr, MK_HTTP_OK);
    sr->headers.location = NULL;
    sr->headers.content_length = 0;

    /*
     * For OPTIONS method, we let the plugin handle it and
     * return without any content.
     */
    if (sr->method == MK_HTTP_METHOD_OPTIONS) {
        sr->headers.allow_methods.data = MK_HTTP_METHOD_AVAILABLE;
        sr->headers.allow_methods.len = strlen(MK_HTTP_METHOD_AVAILABLE);

        mk_ptr_t_reset(&sr->headers.content_type);
        mk_header_send(cs->socket, cs, sr);
        return EXIT_NORMAL;
    }
    else {
        mk_ptr_t_reset(&sr->headers.allow_methods);
    }

    /* read permissions and check file */
    if (sr->file_info.read_access == MK_FALSE) {
        return mk_request_error(MK_CLIENT_FORBIDDEN, cs, sr);
    }

    /* Matching MimeType  */
    mime = mk_mimetype_find(&sr->real_path);
    if (!mime) {
        mime = mimetype_default;
    }

    if (sr->file_info.is_directory == MK_TRUE) {
        return mk_request_error(MK_CLIENT_FORBIDDEN, cs, sr);
    }

    /* get file size */
    if (sr->file_info.size < 0) {
        return mk_request_error(MK_CLIENT_NOT_FOUND, cs, sr);
    }

    sr->headers.last_modified = sr->file_info.last_modification;

    if (sr->if_modified_since.data && sr->method == MK_HTTP_METHOD_GET) {
        time_t date_client;       /* Date sent by client */
        time_t date_file_server;  /* Date server file */

        date_client = mk_utils_gmt2utime(sr->if_modified_since.data);
        date_file_server = sr->file_info.last_modification;

        if (date_file_server <= date_client && date_client > 0 &&
                date_client <= log_current_utime) {

            mk_header_set_http_status(sr, MK_NOT_MODIFIED);
            mk_header_send(cs->socket, cs, sr);
            return EXIT_NORMAL;
        }
    }

    /* Object size for log and response headers */
    sr->headers.content_length = sr->file_info.size;
    sr->headers.real_length = sr->file_info.size;

    /* Open file */
    if (mk_likely(sr->file_info.size > 0)) {
        sr->fd_file = mk_vhost_open(sr);
        if (sr->fd_file == -1) {
            MK_TRACE("open() failed");
            return mk_request_error(MK_CLIENT_FORBIDDEN, cs, sr);
        }
        sr->bytes_to_send = sr->file_info.size;
    }

    /* Process methods */
    if (sr->method == MK_HTTP_METHOD_GET || sr->method == MK_HTTP_METHOD_HEAD) {
        sr->headers.content_type = mime->type;

        /* HTTP Ranges */
        if (sr->range.data != NULL && config->resume == MK_TRUE) {
            if (mk_http_range_parse(sr) < 0) {
                sr->headers.ranges[0] = -1;
                sr->headers.ranges[1] = -1;
                return mk_request_error(MK_CLIENT_BAD_REQUEST, cs, sr);
            }
            if (sr->headers.ranges[0] >= 0 || sr->headers.ranges[1] >= 0) {
                mk_header_set_http_status(sr, MK_HTTP_PARTIAL);
            }

            /* Calc bytes to send & offset */
            if (mk_http_range_set(sr, sr->file_info.size) != 0) {
                sr->headers.content_length = -1;
                sr->headers.ranges[0] = -1;
                sr->headers.ranges[1] = -1;
                return mk_request_error(MK_CLIENT_REQUESTED_RANGE_NOT_SATISF, cs, sr);
            }
        }
    }
    else {
        /* without content-type */
        mk_ptr_t_reset(&sr->headers.content_type);
    }

    /* Send headers */
    mk_header_send(cs->socket, cs, sr);

    if (mk_unlikely(sr->headers.content_length == 0)) {
        return 0;
    }

    /* Send file content */
    if (sr->method == MK_HTTP_METHOD_GET || sr->method == MK_HTTP_METHOD_POST) {
        bytes = mk_http_send_file(cs, sr);
    }

    return bytes;
}
Esempio n. 14
0
/* Return a struct with method, URI , protocol version
and all static headers defined here sent in request */
static int mk_request_header_process(struct session_request *sr)
{
    int uri_init = 0, uri_end = 0;
    int query_init = 0;
    int prot_init = 0, prot_end = 0, pos_sep = 0;
    int fh_limit;
    char *headers;
    char *temp = 0;
    mk_ptr_t host;

    /* Method */
    sr->method_p = mk_http_method_check_str(sr->method);

    /* Request URI */
    temp = index(sr->body.data, ' ');
    if (mk_unlikely(!temp)) {
        MK_TRACE("Error, invalid first header");
        return -1;
    }
    uri_init = (temp - sr->body.data) + 1;

    temp = index(sr->body.data, '\n');
    if (mk_unlikely(!temp)) {
        MK_TRACE("Error, invalid header CRLF");
        return -1;
    }
    fh_limit = (temp - sr->body.data);

    uri_end = mk_string_char_search_r(sr->body.data, ' ', fh_limit) - 1;
    if (mk_unlikely(uri_end <= 0)) {
        MK_TRACE("Error, first header bad formed");
        return -1;
    }

    prot_init = uri_end + 2;

    if (mk_unlikely(uri_end < uri_init)) {
        return -1;
    }

    /* Query String */
    query_init = mk_string_char_search(sr->body.data + uri_init, '?', prot_init);
    if (query_init > 0) {
        int init, end;

        init = query_init + uri_init;
        if (init <= uri_end) {
            end = uri_end;
            uri_end = init - 1;

            sr->query_string = mk_ptr_create(sr->body.data,
                                                 init + 1, end + 1);
        }
    }

    /* Request URI Part 2 */
    sr->uri = mk_ptr_create(sr->body.data, uri_init, uri_end + 1);
    if (mk_unlikely(sr->uri.len < 1)) {
        return -1;
    }

    /* HTTP Version */
    prot_end = fh_limit - 1;
    if (mk_unlikely(prot_init == prot_end)) {
        return  -1;
    }

    if (prot_end != prot_init && prot_end > 0) {
        sr->protocol = mk_http_protocol_check(sr->body.data + prot_init,
                                              prot_end - prot_init);
        sr->protocol_p = mk_http_protocol_check_str(sr->protocol);
    }

    headers = sr->body.data + prot_end + mk_crlf.len;

    /*
     * Process URI, if it contains ASCII encoded strings like '%20',
     * it will return a new memory buffer with the decoded string, otherwise
     * it returns NULL
     */
    temp = mk_utils_url_decode(sr->uri);
    if (temp) {
        sr->uri_processed.data = temp;
        sr->uri_processed.len  = strlen(temp);
    }
    else {
        sr->uri_processed.data = sr->uri.data;
        sr->uri_processed.len  = sr->uri.len;
    }

    /* Creating Table of Content (index) for HTTP headers */
    sr->headers_len = sr->body.len - (prot_end + mk_crlf.len);
    if (mk_request_header_toc_parse(&sr->headers_toc, headers, sr->headers_len) < 0) {
        MK_TRACE("Invalid headers");
        return -1;
    }

    /* Host */
    host = mk_request_header_get(&sr->headers_toc,
                                 mk_rh_host.data,
                                 mk_rh_host.len);
    if (host.data) {
        if ((pos_sep = mk_string_char_search_r(host.data, ':', host.len)) >= 0) {
            /* TCP port should not be higher than 65535 */
            char *p;
            short int port_len, port_size = 6;
            char port[port_size];

            /* just the host */
            sr->host.data = host.data;
            sr->host.len = pos_sep;

            /* including the port */
            sr->host_port = host;

            /* Port string length */
            port_len = (host.len - pos_sep - 1);
            if (port_len >= port_size) {
                return -1;
            }

            /* Copy to buffer */
            memcpy(port, host.data + pos_sep + 1, port_len);
            port[port_len] = '\0';

            /* Validate that the input port is numeric */
            p = port;
            while (*p) {
                if (!isdigit(*p)) return -1;
                p++;
            }

            /* Convert to base 10 */
            errno = 0;
            sr->port = strtol(port, (char **) NULL, 10);
            if ((errno == ERANGE && (sr->port == LONG_MAX || sr->port == LONG_MIN))
                || sr->port == 0) {
                return -1;
            }
        }
        else {
            sr->host = host;    /* maybe null */
            sr->port = config->standard_port;
        }
    }
    else {
        sr->host.data = NULL;
    }

    /* Looking for headers that ONLY Monkey uses */
    sr->connection = mk_request_header_get(&sr->headers_toc,
                                           mk_rh_connection.data,
                                           mk_rh_connection.len);

    sr->range = mk_request_header_get(&sr->headers_toc,
                                      mk_rh_range.data,
                                      mk_rh_range.len);

    sr->if_modified_since = mk_request_header_get(&sr->headers_toc,
                                                  mk_rh_if_modified_since.data,
                                                  mk_rh_if_modified_since.len);

    /* Default Keepalive is off */
    if (sr->protocol == MK_HTTP_PROTOCOL_10) {
        sr->keep_alive = MK_FALSE;
        sr->close_now = MK_TRUE;
    }
    else if(sr->protocol == MK_HTTP_PROTOCOL_11) {
        sr->keep_alive = MK_TRUE;
        sr->close_now = MK_FALSE;
    }

    if (sr->connection.data) {
        if (mk_string_search_n(sr->connection.data, "Keep-Alive",
                               MK_STR_INSENSITIVE, sr->connection.len) >= 0) {
            sr->keep_alive = MK_TRUE;
            sr->close_now = MK_FALSE;
        }
        else if (mk_string_search_n(sr->connection.data, "Close",
                                    MK_STR_INSENSITIVE, sr->connection.len) >= 0) {
            sr->keep_alive = MK_FALSE;
            sr->close_now = MK_TRUE;
        }
        else {
            /* Set as a non-valid connection header value */
            sr->connection.len = 0;
        }
    }

    return 0;
}
Esempio n. 15
0
int duda_body_buffer_flush(int sock, struct duda_body_buffer *bb)
{
    int i;
    int count = 0;
    unsigned int bytes_sent, bytes_to;
    int reset_to = -1;
    struct mk_iov *buf = bb->buf;

    /* FIXME: Temporal Check */
    if (mk_unlikely(buf->iov_idx > IOV_MAX)) {
        mk_err("Boddy buffer flush: enqueued data is larger than IOV_MAX (%i)\n",
                IOV_MAX);
        exit(EXIT_FAILURE);
    }

    bytes_sent = mk_api->socket_sendv(sock, buf);
    PLUGIN_TRACE("body_flush: %i/%i", bytes_sent, buf->total_len);
    /*
     * If the call sent less data than total, we must modify the mk_iov struct
     * to mark the buffers already processed and set them with with length = zero,
     * so on the next calls to this function Monkey will skip buffers with bytes
     * length = 0.
     */
    if (bytes_sent < buf->total_len) {
        /* Go around each buffer entry and check where the offset took place */
        for (i = 0; i < buf->iov_idx; i++) {
            if (count + buf->io[i].iov_len == bytes_sent) {
                reset_to = i;
                break;
            }
            else if (bytes_sent < (count + buf->io[i].iov_len)) {
                reset_to = i - 1;
                bytes_to = (bytes_sent - count);
                buf->io[i].iov_base += bytes_to;
                buf->io[i].iov_len   = buf->io[i].iov_len - bytes_to;
                break;
            }
            count += buf->io[i].iov_len;
        }

        /* Reset entries */
        for (i = 0; i <= reset_to; i++) {
            buf->io[i].iov_len = 0;
        }

        buf->total_len -= bytes_sent;

#ifdef TRACE
        PLUGIN_TRACE("new total len: %i (iov_idx=%i)",
                     buf->total_len,
                     buf->iov_idx);
        int j;

        for (j = 0; j < buf->iov_idx; j++) {
            PLUGIN_TRACE("io[%i] = %i", j, buf->io[j].iov_len);
        }
#endif
    }

    /* Successfully end ? */
    if (bytes_sent == buf->total_len) {
        buf->total_len = 0;
        return 0;
    }

    return bytes_sent;
}