static ret_t downloader_step (cherokee_downloader_t *downloader) { ret_t ret; size_t read_ = 0; cherokee_socket_t *sock = &downloader->socket; ret = cherokee_socket_bufread (sock, &downloader->body, DEFAULT_RECV_SIZE, &read_); switch (ret) { case ret_eagain: return ret_eagain; case ret_ok: /* Count */ downloader->info.body_recv += read_; /* Has it finished? */ if (downloader->info.body_recv >= downloader->content_length) { return ret_eof_have_data; } return ret_ok; default: return ret; } return ret_ok; }
static ret_t read_from_fcgi (cherokee_handler_cgi_base_t *cgi, cherokee_buffer_t *buffer) { ret_t ret; size_t read = 0; cherokee_handler_fcgi_t *fcgi = HDL_FCGI(cgi); ret = cherokee_socket_bufread (&fcgi->socket, &fcgi->write_buffer, DEFAULT_READ_SIZE, &read); switch (ret) { case ret_eagain: ret = cherokee_thread_deactive_to_polling (HANDLER_THREAD(cgi), HANDLER_CONN(cgi), fcgi->socket.socket, FDPOLL_MODE_READ, false); if (unlikely (ret != ret_ok)) { cgi->got_eof = true; return ret_error; } return ret_eagain; case ret_ok: ret = process_buffer (fcgi, &fcgi->write_buffer, buffer); TRACE (ENTRIES, "%d bytes read, buffer.len %d\n", read, buffer->len); if ((ret == ret_ok) && cgi->got_eof && (buffer->len > 0)) { return ret_eof_have_data; } return ret; case ret_eof: case ret_error: cgi->got_eof = true; return ret; default: RET_UNKNOWN(ret); } SHOULDNT_HAPPEN; return ret_error; }
static ret_t do_read_plain (cherokee_post_t *post, cherokee_socket_t *sock_in, cherokee_buffer_t *buffer, off_t to_read) { ret_t ret; size_t len; /* Surplus from header read */ if (! cherokee_buffer_is_empty (&post->header_surplus)) { TRACE (ENTRIES, "Post appending %d surplus bytes\n", post->header_surplus.len); post->send.read += post->header_surplus.len; cherokee_buffer_add_buffer (buffer, &post->header_surplus); cherokee_buffer_clean (&post->header_surplus); return ret_ok; } /* Read */ if (to_read <= 0) { return ret_ok; } TRACE (ENTRIES, "Post reading from client (to_read=%d)\n", to_read); ret = cherokee_socket_bufread (sock_in, buffer, to_read, &len); TRACE (ENTRIES, "Post read from client: ret=%d len=%d\n", ret, len); if (ret != ret_ok) { return ret; } post->send.read += len; return ret_ok; }
ret_t cherokee_handler_proxy_conn_recv_headers (cherokee_handler_proxy_conn_t *pconn, cherokee_buffer_t *body, cherokee_boolean_t flexible) { ret_t ret; char *end; cuint_t sep_len; size_t size = 0; /* Read */ ret = cherokee_socket_bufread (&pconn->socket, &pconn->header_in_raw, DEFAULT_RECV_SIZE, &size); switch (ret) { case ret_ok: break; case ret_eof: case ret_error: return ret; case ret_eagain: if (cherokee_buffer_is_empty (&pconn->header_in_raw)) { return ret_eagain; } break; default: RET_UNKNOWN(ret); } /* Look for the end of header */ ret = cherokee_find_header_end (&pconn->header_in_raw, &end, &sep_len); switch (ret) { case ret_ok: break; case ret_not_found: return ret_eagain; default: /* Did not success */ if (! flexible) { goto error; } /* Plan B! */ TRACE (ENTRIES, "Header end not found. Being more flexible about malformed headers\n"); ret = find_header_end_flexible (&pconn->header_in_raw, &end, &sep_len); switch (ret) { case ret_ok: break; case ret_not_found: return ret_eagain; default: goto error; } } /* Copy the body if there is any */ size = (pconn->header_in_raw.buf + pconn->header_in_raw.len) - (end + sep_len); cherokee_buffer_add (body, end+sep_len, size); cherokee_buffer_drop_ending (&pconn->header_in_raw, size); return ret_ok; error: LOG_ERROR (CHEROKEE_ERROR_PROXY_HEADER_PARSE, pconn->header_in_raw.len, pconn->header_in_raw.buf); return ret_error; }
static ret_t downloader_header_read (cherokee_downloader_t *downloader, cherokee_buffer_t *tmp1, cherokee_buffer_t *tmp2) { ret_t ret; cuint_t len; size_t read_ = 0; cherokee_socket_t *sock = &downloader->socket; cherokee_http_t error_code = http_bad_request; UNUSED(tmp2); ret = cherokee_socket_bufread (sock, &downloader->reply_header, DEFAULT_RECV_SIZE, &read_); switch (ret) { case ret_eof: return ret_eof; case ret_eagain: return ret_eagain; case ret_ok: /* Count */ downloader->info.headers_recv += read_; /* Check the header. Is it complete? */ ret = cherokee_header_has_header (downloader->header, &downloader->reply_header, 0); switch (ret) { case ret_ok: break; case ret_not_found: /* It needs to read more headers ... */ return ret_eagain; default: /* Too many initial CRLF */ return ret_error; } /* Parse the header */ ret = cherokee_header_parse (downloader->header, &downloader->reply_header, &error_code); if (unlikely (ret != ret_ok)) return ret_error; /* Look for the length, it will need to drop out the header from the buffer */ cherokee_header_get_length (downloader->header, &len); /* Maybe it has some body */ if (downloader->reply_header.len > len) { uint32_t body_chunk; /* Skip the CRLF separator and copy the body */ len += 2; body_chunk = downloader->reply_header.len - len; downloader->info.body_recv += body_chunk; cherokee_buffer_add (&downloader->body, downloader->reply_header.buf + len, body_chunk); cherokee_buffer_drop_ending (&downloader->reply_header, body_chunk); } /* Try to read the "Content-Length" response header */ ret = cherokee_header_has_known (downloader->header, header_content_length); if (ret == ret_ok) { cherokee_buffer_clean (tmp1); ret = cherokee_header_copy_known (downloader->header, header_content_length, tmp1); if (ret == ret_ok) { ret = cherokee_atou (tmp1->buf, &downloader->content_length); #ifdef TRACE_ENABLED if (ret == ret_ok) { TRACE (ENTRIES, "Known length: %d bytes\n", downloader->content_length); } else { TRACE (ENTRIES, "Could not parse Content-Length\n"); } #endif } } return ret_ok; case ret_error: /* Opsss.. something has failed */ return ret_error; default: RET_UNKNOWN (ret); return ret; } return ret_error; }