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; }
/* 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; }
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; }
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; } }
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; }
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 }
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; }
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; }
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; }
/* * 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; }
int _mkp_event_error(int socket) { PLUGIN_TRACE("[FD %i] error", socket); return hangup(socket); }
/* * 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; }
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 }
int _mkp_event_timeout(int socket) { PLUGIN_TRACE("[FD %i] timeout", socket); return hangup(socket); }
int _mkp_event_close(int socket) { PLUGIN_TRACE("[FD %i] close", socket); return hangup(socket); }
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; }
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; }
/* 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; }