Exemple #1
0
static int mk_patas_write_pending_to_remote(int socket, struct mk_patas_conx *conx)
{
    int bytes;

    if (!conx) {
        return MK_PLUGIN_RET_EVENT_NEXT;
    }
    
    if (conx->buf_pending_node > 0) {
        PLUGIN_TRACE("PENDING: %i", conx->buf_pending_node);
        bytes = write(conx->socket_remote, 
                      conx->buf_node + (conx->buf_len_node - conx->buf_pending_node),
                      conx->buf_pending_node);

        PLUGIN_TRACE("  written: %i", bytes);

        if (bytes >= 0) {
            conx->buf_pending_node -= bytes;
        }
        else {
            switch(errno) {
            case EAGAIN:
                PLUGIN_TRACE("EAGAIN");
                return MK_PLUGIN_RET_EVENT_OWNED;
            default:
                return MK_PLUGIN_RET_EVENT_CLOSE;
            }
        }
    }

    return MK_PLUGIN_RET_EVENT_OWNED;
}
Exemple #2
0
/*
int _mkp_event_write(int socket)
{
    struct mk_patas_conx *conx = NULL;

#ifdef TRACE
    PLUGIN_TRACE("[FD %i] Writting to REMOTE", socket);
#endif

    conx = mk_patas_connection_get(socket);
    if (!conx) {
        return MK_PLUGIN_RET_EVENT_NEXT;
    }
    
    return mk_patas_write_pending_to_remote(socket, conx);
}
*/
int _mkp_event_read(int socket)
{
    int av_bytes=-1, ret;
    struct mk_patas_conx *conx = NULL;

    return MK_PLUGIN_RET_EVENT_NEXT;

    /* Get connection node */
    conx = mk_patas_connection_get(socket);

    /* Check amount of data available */
    ret = ioctl(socket, FIONREAD, &av_bytes);
    if (ret == -1) {
        PLUGIN_TRACE("[FD %i] ERROR ioctl(FIONREAD)", socket);
        return MK_PLUGIN_RET_EVENT_OWNED;
    }

    PLUGIN_TRACE("[FD %i] available bytes: %i", socket, av_bytes);

    /* Map right handler */
    if (!conx || conx->socket_remote == socket) {
        //return mk_patas_read_from_remote(socket, av_bytes, conx);
    }
    else if (conx->socket_node == socket) {
        return mk_patas_read_from_node(socket, av_bytes, conx);
    }

    return MK_PLUGIN_RET_EVENT_OWNED;
}
Exemple #3
0
int cb_cgi_read(void *data)
{
    int n;
    struct cgi_request *r = data;

    if (r->active == MK_FALSE) {
        return -1;
    }

    if ((BUFLEN - r->in_len) < 1) {
        PLUGIN_TRACE("CLOSE BY SIZE");
        cgi_finish(r);
        return -1;
    }

    n = read(r->fd, r->in_buf + r->in_len, BUFLEN - r->in_len);
    PLUGIN_TRACE("FD=%i CGI READ=%d", r->fd, n);
    if (n <= 0) {
        /* It most of cases this means the child process finished */
        cgi_finish(r);
        return MK_PLUGIN_RET_EVENT_CLOSE;
    }
    r->in_len += n;
    process_cgi_data(r);
    return 0;
}
Exemple #4
0
struct table_t *table_create () {

    PLUGIN_TRACE ("Created hashtable");
    struct table_t *table = malloc(sizeof(struct table_t));

    if (!table)
        return NULL;

    table->table_size = TABLE_SIZE;
    PLUGIN_TRACE ("Created min heap");
    table->table_list = malloc(TABLE_SIZE * (sizeof(struct table_t)));
    
    return table;
}
void cache_stats_update_finreqs (struct cache_thread_stats *stats) {

    time_t now;
    time(&now);
    
    int time_diff = difftime(now,stats->started_at);
    PLUGIN_TRACE("time_diff = %d", time_diff);

    if (time_diff > 60) {

        PLUGIN_TRACE("stats->finished_reqs = %d, stats->reqs_psec = %d", stats->finished_reqs, stats->reqs_psec);
        stats->started_at = now;
        stats->reqs_psec = stats->finished_reqs; // / (time_diff /10.0);
//        stats->finished_reqs = 0;
    }
}
Exemple #6
0
int _mkp_stage_30(struct plugin *plugin, struct client_session *cs, 
                  struct session_request *sr)
{

    PLUGIN_TRACE("[FD %i] STAGE 30", cs->socket);
    return MK_PLUGIN_RET_CONTINUE;
}
Exemple #7
0
int mk_liana_send_file(int socket_fd, int file_fd, off_t *file_offset,
                       size_t file_count)
{
    ssize_t ret = -1;

#if defined (__linux__)
    ret = sendfile(socket_fd, file_fd, file_offset, file_count);
    if (ret == -1 && errno != EAGAIN) {
        PLUGIN_TRACE("[FD %i] error from sendfile(): %s",
                     socket_fd, strerror(errno));
    }
    return ret;
#elif defined (__APPLE__)
    off_t offset = *file_offset;
    off_t len = (off_t) file_count;

    ret = sendfile(file_fd, socket_fd, offset, &len, NULL, 0);
    if (ret == -1 && errno != EAGAIN) {
        PLUGIN_TRACE("[FD %i] error from sendfile(): %s",
                     socket_fd, strerror(errno));
    }
    else if (len > 0) {
        *file_offset += len;
        return len;
    }
    return ret;
#elif defined (__FreeBSD__)
    off_t offset = *file_offset;
    off_t len = (off_t) file_count;

    ret = sendfile(file_fd, socket_fd, offset, len, NULL, 0, 0);
    if (ret == -1 && errno != EAGAIN) {
        PLUGIN_TRACE("[FD %i] error from sendfile(): %s",
                     socket_fd, strerror(errno));
    }
    else if (len > 0) {
        *file_offset += len;
        return len;
    }
    return ret;
#else
#error Sendfile not supported on platform
#endif
}
Exemple #8
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;
}
Exemple #9
0
void *table_lookup (struct table_t *table, const char *key) {

    PLUGIN_TRACE ("Lookup inside the hash table.\n");

    int index = hash_func_asciisum_modulo(key, table->table_size);
    struct node_t *temp = table->table_list[index];

    if (temp == NULL) {
        return NULL;
    }

    PLUGIN_TRACE ("Finding out hash of the file name requested = %d\n", index);

    for (; temp != NULL; temp = temp->next) {
        PLUGIN_TRACE ("index = %s", temp->key);
        if (temp->key == key || (strcmp(temp->key, key) ==0)) {
            PLUGIN_TRACE ("Found file\n");
            return temp->data;
        }
    }

    PLUGIN_TRACE ("Not found\n");
    return NULL;
}
Exemple #10
0
void serve_cache_headers(struct cache_req_t *req) {
    int ret = tee(req->file->cache_headers->pipe[0],
        req->buf->pipe[1], req->file->cache_headers->filled, SPLICE_F_NONBLOCK);

    if (ret < 0) {
        perror("cannot tee into the request buffer!!\n");
        mk_bug(1);
    }

    if (ret < req->file->header_len) {

        PLUGIN_TRACE("teed %d data instead of headers len %ld\n", ret, req->file->header_len);
        mk_bug(ret < req->file->header_len);
    }

    req->buf->filled += ret;

    // HACK: make headers seem like file contents
    req->bytes_offset -= req->file->header_len;
    req->bytes_to_send += req->file->header_len;
}
Exemple #11
0
/* 
 * Return the next target node to balance a new incoming
 * connection
 */
struct mk_patas_node *mk_patas_node_next_target()
{
    struct mk_patas_node *node;

    /* Mutex lock */
    pthread_mutex_lock(&mutex_patas_target);

    if (!mk_patas_nodes_head) {
        mk_patas_nodes_head = mk_patas_nodes_list;
    }
    
    node = mk_list_entry_next(mk_patas_nodes_head, struct mk_patas_node, _head,
                              mk_patas_nodes_list);

    /* Mutex unlock */
    pthread_mutex_unlock(&mutex_patas_target);


    PLUGIN_TRACE("next target node: %s:%i", node->host, node->port);
    return node;
}
Exemple #12
0
int _mkp_event_error(int socket)
{
    PLUGIN_TRACE("[FD %i] error", socket);
    return hangup(socket);
}
Exemple #13
0
/*
 * Returns an 'iov' palm request array with the CGI data
 */
struct mk_iov *mk_palm_protocol_request_new(struct client_session *cs,
                                            struct session_request *sr)
{
    int i, ret;
    int row_len;
    char *ip_str;
    unsigned long ip_len;
    char *row_buf;

    mk_pointer iov_temp;
    struct mk_iov *iov;
    struct header_toc_row *row;

    /* Use cached iov_request */
    iov = prot_template();
    iov->iov_idx = 0;

    /* DOCUMENT_ROOT */
    prot_add_header(iov, mk_cgi_document_root, sr->host_conf->documentroot);

    /* CONTENT_XYZ */
    //mk_api->pointer_reset(&iov_temp);
    if (sr->method == HTTP_METHOD_POST && sr->content_length >= 0) {
        iov_temp.data = mk_api->mem_alloc(32);
        mk_api->str_itop(sr->content_length, &iov_temp);

        iov_temp.len -= 2;
        prot_add_header(iov, mk_cgi_content_length, iov_temp);
    }
    if (sr->headers.content_type.len > 0) {
        prot_add_header(iov, mk_cgi_content_type, sr->headers.content_type);
    }

    /* SERVER_ADDR */
    //prot_add_header(iov, mk_cgi_server_addr, mk_server_address);

    /* SERVER_PORT */
    prot_add_header(iov, mk_cgi_server_port, mk_server_port);

    /*
     * SERVER_NAME
     * -----------
     *
     * Server name belongs to the value specified in the conf/sites/XYZ vhost file
     * under key 'ServerName'.
     */
    iov_temp.data = sr->host_alias->name;
    iov_temp.len = sr->host_alias->len;
    prot_add_header(iov, mk_cgi_server_name, iov_temp);

    /* SERVER_PROTOCOL */
    prot_add_header(iov, mk_cgi_server_protocol, mk_server_protocol);

    /*
     * SERVER_SIGNATURE
     * ----------------
     * we use an offset of 8 bytes as each host signature is composed in
     * the following way:
     *
     *   server: Monkey/x.y.x
     *
     * so the 8 bytes do the offset for 'server: ' which is not useful for
     * the CGI environment variable.
     */
    iov_temp.data = sr->host_conf->header_host_signature.data + 8;
    iov_temp.len = sr->host_conf->header_host_signature.len - 8;
    prot_add_header(iov, mk_cgi_server_signature, iov_temp);

    /*
     * HTTP_*
     * --------
     *
     * CGI spec specify that incomming HTTP headers by the client must be
     * converted to uppercase, replace '-' by '_' and prefix the 'HTTP_'
     * string. e.g:
     *
     *   Accept-Encoding: -> HTTP_ACCEPT_ENCODING
     */
    short int len;
    short int offset;
    short int prefix_len = 5;

    for (i=0; i < sr->headers_toc.length; i++) {
        row = &sr->headers_toc.rows[i];
        /* let's match common CGI HTTP_ headers */
        len = row->end - row->init;
        row_buf = mk_api->mem_alloc(len + 1);
        row_len = prot_header2cgi(row->init, len, &row_buf);

        /* Row key */
        mk_api->iov_add_entry(iov, row_buf, row_len,
                              mk_iov_equal, MK_IOV_FREE_BUF);

        /* Just prefixed HEADERS requires the offset */
        if (strncmp(row_buf, "HTTP_", 5) == 0) {
            offset = prefix_len;
        }
        else {
            offset = 0;
        }

        /* Row value */
        mk_api->iov_add_entry(iov, row->init + (row_len - offset) + 2,
                              len - (row_len - offset) - 2,
                              mk_iov_crlf, MK_IOV_NOT_FREE_BUF);
    }

    /* REMOTE_ADDR */
    ip_str = pthread_getspecific(cache_ip_str);
    ret = mk_api->socket_ip_str(cs->socket, (char **) &ip_str, INET6_ADDRSTRLEN + 1, &ip_len);
    if (ret < 0) {
        PLUGIN_TRACE("[FD %i] Error formatting IP address", cs->socket);
        return NULL;
    }

    iov_temp.len = ip_len;
    iov_temp.data = ip_str;

    prot_add_header(iov, mk_cgi_remote_addr, iov_temp);

    /* REMOTE_PORT */
    iov_temp.data = mk_api->mem_alloc(8);
    mk_api->str_itop(get_port_by_socket(cs->socket), &iov_temp);
    iov_temp.len -=2;
    mk_api->iov_add_entry(iov, mk_cgi_remote_port.data, mk_cgi_remote_port.len,
                          mk_iov_equal, MK_IOV_NOT_FREE_BUF);
    mk_api->iov_add_entry(iov, iov_temp.data, iov_temp.len,
                          mk_iov_crlf, MK_IOV_FREE_BUF);

    /* Miscellaneus CGI headers */
    prot_add_header(iov, mk_cgi_gateway_interface, mk_cgi_version);

    /*
     * REQUEST_URI
     *
     * if the request URI contains a query string, we must re-compose the full
     * string as Monkey splits URI from query string
     */
    iov_temp.data = sr->uri.data;
    if (sr->query_string.len > 0) {
        iov_temp.len = sr->uri.len + sr->query_string.len + 1;
    }
    else {
        iov_temp.len = sr->uri.len;
    }
    prot_add_header(iov, mk_cgi_request_uri, iov_temp);

    /* REQUEST_METHOD */
    prot_add_header(iov, mk_cgi_request_method, sr->method_p);
    prot_add_header(iov, mk_cgi_script_name, sr->uri);
    prot_add_header(iov, mk_cgi_script_filename, sr->real_path);

    /* QUERY_STRING */
    if (sr->query_string.len > 0) {
        prot_add_header(iov, mk_cgi_query_string, sr->query_string);
    }

    /*
     * POST_VARIABLES
     * --------------
     * non-standard field of CGI, it just used by Palm protocol
     */
    if (sr->content_length > 0 && sr->data.len > 0) {
        prot_add_header(iov, mk_cgi_post_vars, sr->data);
    }

    /* Ending CRLFCRLF (\r\n\r\n) */
    mk_api->iov_add_entry(iov,
                          mk_iov_crlfcrlf.data, mk_iov_crlfcrlf.len,
                          mk_iov_none, MK_IOV_NOT_FREE_BUF);
#ifdef TRACE
    PLUGIN_TRACE("Palm protocol request");
    mk_api->iov_send(0, iov);
#endif

    return iov;
}
Exemple #14
0
int mk_liana_send_file(int socket_fd, int file_fd, off_t *file_offset,
                       size_t file_count)
{
    ssize_t ret = -1;

#if defined (__linux__)
    ret = sendfile(socket_fd, file_fd, file_offset, file_count);
    if (ret == -1 && errno != EAGAIN) {
        PLUGIN_TRACE("[FD %i] error from sendfile(): %s",
                     socket_fd, strerror(errno));
    }
    return ret;
#elif defined (__APPLE__)
    off_t offset = *file_offset;
    off_t len = (off_t) file_count;

    ret = sendfile(file_fd, socket_fd, offset, &len, NULL, 0);
    if (ret == -1 && errno != EAGAIN) {
        PLUGIN_TRACE("[FD %i] error from sendfile(): %s",
                     socket_fd, strerror(errno));
    }
    else if (len > 0) {
        *file_offset += len;
        return len;
    }
    return ret;
#elif defined (__FreeBSD__)
    off_t offset = *file_offset;
    off_t len = (off_t) file_count;

    ret = sendfile(file_fd, socket_fd, offset, len, NULL, 0, 0);
    if (ret == -1 && errno != EAGAIN) {
        PLUGIN_TRACE("[FD %i] error from sendfile(): %s",
                     socket_fd, strerror(errno));
    }
    else if (len > 0) {
        *file_offset += len;
        return len;
    }
    return ret;
#elif defined(__rtems__)
    ret=0;
    uint8_t success=0;
    size_t bufsize=1000000;
    uint8_t *buffer= (uint8_t*)malloc(bufsize*sizeof(uint8_t));

    if( !buffer )
        return -1;

    while (1) {
        int bytes_read = read(file_fd, buffer, bufsize*sizeof(uint8_t));

        if (bytes_read == 0){
            success=1;
            break;
        }

        if (bytes_read < 0){
	    success=0;
	    break;
        }

        void *p = buffer;

        while (bytes_read > 0) {
            int bytes_written = write(socket_fd, p, bytes_read);

            if (bytes_written <= 0) {
                success = 0;
		return -1;
            }

            ret+=bytes_written;
            bytes_read -= bytes_written;

            p += bytes_written;
        }
    }
    if ( buffer )
        free(buffer);

    if (success == 0) {
        PLUGIN_TRACE("[FD %i] error from sendfile(): unspecified",
                     socket_fd );
        return -1;
    }
        PLUGIN_TRACE("IMPLEMENTATION OF SENDFILE");

#else
#error Sendfile not supported on platform
#endif
}
Exemple #15
0
int _mkp_event_timeout(int socket)
{
    PLUGIN_TRACE("[FD %i] timeout", socket);
    return hangup(socket);
}
Exemple #16
0
int _mkp_event_close(int socket)
{

    PLUGIN_TRACE("[FD %i] close", socket);
    return hangup(socket);
}
Exemple #17
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;
}
Exemple #18
0
static int mk_patas_read_from_node(int socket, int av_bytes, struct mk_patas_conx *conx)
{
    int bytes = -1;
    int read_limit = 0;

    PLUGIN_TRACE("[FD %i] Reading from NODE", socket);

    /* Process pending data */
    if (conx->buf_pending_node > 0) {
        PLUGIN_TRACE("     Pending %i bytes", conx->buf_pending_node);
        return mk_patas_write_pending_to_remote(socket, conx);
    }

    /* check Node EOF, at this point no pending data should exists */
    if (av_bytes == 0) {
        return MK_PLUGIN_RET_EVENT_CLOSE;
    }

    if (av_bytes < conx->buf_size_node) {
        read_limit = av_bytes;
    }
    else {
        read_limit = conx->buf_size_node;
    }

    bytes = read(conx->socket_node, conx->buf_node, read_limit);
    if (bytes <= 0) {
        PLUGIN_TRACE("[FD %i] Node END", conx->socket_node);
        close(conx->socket_node);
        conx->socket_node = -1;
        return MK_PLUGIN_RET_EVENT_OWNED;
    }
    else {
        conx->buf_len_node = bytes;
    }

    PLUGIN_TRACE("[FD %i] read %i bytes", socket, bytes);

    /* Write node data to remote client */
    bytes = write(conx->socket_remote, conx->buf_node, conx->buf_len_node);

    PLUGIN_TRACE("[FD %i] written %i/%i bytes ", 
                 conx->socket_remote, bytes, conx->buf_len_node);

    if (bytes == 0) {
        return MK_PLUGIN_RET_EVENT_CLOSE;
    }
    else if (bytes < 0) {
#ifdef TRACE
        mk_api->errno_print(errno);
#endif
        switch(errno) {
        case EAGAIN:
            /* 
             * Could not write because can block on socket, 
             * let's set as pending 
             */
            PLUGIN_TRACE("EAGAIN");
            conx->buf_pending_node += conx->buf_len_node;
            return MK_PLUGIN_RET_EVENT_OWNED;
        case EPIPE:
            return MK_PLUGIN_RET_EVENT_CLOSE;

        }
    }

    if (bytes == conx->buf_len_node) { 
        conx->buf_len_node = 0;
    }
    else {
        conx->buf_pending_node = conx->buf_len_node - bytes;
    }

    return MK_PLUGIN_RET_EVENT_OWNED;
}
Exemple #19
0
/* Read configuration parameters */
int mk_patas_conf(char *confdir)
{
    int res;
    int val_port;
    char *val_host;
    char *val_uri;
    unsigned long len;
    char *conf_path=NULL;

    struct mk_config_section *section;
    struct mk_config_entry *entry;
    struct mk_patas_node *node;

    /* Init nodes list */
    mk_patas_nodes_list = mk_api->mem_alloc(sizeof(struct mk_list));
    mk_list_init(mk_patas_nodes_list);

    /* Read configuration */
    mk_api->str_build(&conf_path, &len, "%s/patas.conf", confdir);
    conf = mk_api->config_create(conf_path);
    section = mk_api->config_section_get(conf, "NODE");

    while (section) { 
        entry = section->entry;
        val_host = NULL;
        val_port = -1;
        val_uri = NULL;

        /* Get section values */
        val_host = mk_api->config_section_getval(section, "IP", MK_CONFIG_VAL_STR);
        val_port = (int)  mk_api->config_section_getval(section, "Port", MK_CONFIG_VAL_NUM);
        val_uri  = mk_api->config_section_getval(section, "Uri", MK_CONFIG_VAL_LIST);

        if (val_host && val_uri && val_port > 0) {
            /* validate that node:ip is not pointing this server */
            if (mk_patas_validate_node(val_host, val_port) < 0) {
                break;
            }

            /* alloc node */
            node = mk_api->mem_alloc(sizeof(struct mk_patas_node));
            node->host = val_host;
            node->port = val_port;
                
            /* pre-socket stuff */
            node->sockaddr = mk_api->mem_alloc_z(sizeof(struct sockaddr_in));
            node->sockaddr->sin_family = AF_INET;

            res = inet_pton(AF_INET, node->host, 
                            (void *) (&(node->sockaddr->sin_addr.s_addr)));
            if (res < 0) {
                mk_warn("Can't set remote->sin_addr.s_addr");
                mk_api->mem_free(node->sockaddr);
                return -1;
            }
            else if (res == 0) {
                mk_err("Invalid IP address");
                mk_api->mem_free(node->sockaddr);
                return -1;
            }

            node->sockaddr->sin_port = htons(node->port);
                
            /* add node to list */
            PLUGIN_TRACE("Balance Node: %s:%i", val_host, val_port);

            mk_list_add(&node->_head, mk_patas_nodes_list);
            mk_patas_n_nodes++;
        }
        section = section->next;
    }

    mk_api->mem_free(conf_path);
    return 0;
}