+/*********************************************************************
+ *
+ * Function : read_http_request_body
+ *
+ * Description : Reads remaining request body from the client.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : 0 on success, anything else is an error.
+ *
+ *********************************************************************/
+static int read_http_request_body(struct client_state *csp)
+{
+ size_t to_read = csp->expected_client_content_length;
+ int len;
+
+ assert(to_read != 0);
+
+ /* check if all data has been already read */
+ if (to_read <= (csp->client_iob->eod - csp->client_iob->cur))
+ {
+ return 0;
+ }
+
+ for (to_read -= (size_t)(csp->client_iob->eod - csp->client_iob->cur);
+ to_read > 0 && data_is_available(csp->cfd, csp->config->socket_timeout);
+ to_read -= (unsigned)len)
+ {
+ char buf[BUFFER_SIZE];
+ size_t max_bytes_to_read = to_read < sizeof(buf) ? to_read : sizeof(buf);
+
+ log_error(LOG_LEVEL_CONNECT,
+ "Waiting for up to %lu bytes of request body from the client.",
+ max_bytes_to_read);
+ len = read_socket(csp->cfd, buf, (int)max_bytes_to_read);
+ if (len <= -1)
+ {
+ log_error(LOG_LEVEL_CONNECT, "Failed receiving request body from %s: %E", csp->ip_addr_str);
+ return 1;
+ }
+ if (add_to_iob(csp->client_iob, csp->config->buffer_limit, (char *)buf, len))
+ {
+ return 1;
+ }
+ assert(to_read >= len);
+ }
+
+ if (to_read != 0)
+ {
+ log_error(LOG_LEVEL_CONNECT,
+ "Not enough request body has been read: expected %lu more bytes.",
+ to_read);
+ return 1;
+ }
+ log_error(LOG_LEVEL_CONNECT,
+ "The last %d bytes of the request body have been read.", len);
+ return 0;
+}
+
+
+/*********************************************************************
+ *
+ * Function : update_client_headers
+ *
+ * Description : Updates the HTTP headers from the client request.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : new_content_length = new content length value to set
+ *
+ * Returns : 0 on success, anything else is an error.
+ *
+ *********************************************************************/
+static int update_client_headers(struct client_state *csp, size_t new_content_length)
+{
+ static const char content_length[] = "Content-Length:";
+ int updated = 0;
+ struct list_entry *p;
+
+#ifndef FEATURE_HTTPS_INSPECTION
+ for (p = csp->headers->first;
+#else
+ for (p = csp->http->client_ssl ? csp->https_headers->first : csp->headers->first;
+#endif
+ !updated && (p != NULL); p = p->next)
+ {
+ /* Header crunch()ed in previous run? -> ignore */
+ if (p->str == NULL)
+ {
+ continue;
+ }
+
+ /* Does the current parser handle this header? */
+ if (0 == strncmpic(p->str, content_length, sizeof(content_length) - 1))
+ {
+ updated = (JB_ERR_OK == header_adjust_content_length((char **)&(p->str), new_content_length));
+ if (!updated)
+ {
+ return 1;
+ }
+ }
+ }
+
+ return !updated;
+}
+
+
+/*********************************************************************
+ *
+ * Function : can_buffer_request_body
+ *
+ * Description : Checks if the current request body can be stored in
+ * the client_iob without hitting buffer limit.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : TRUE if the current request size do not exceed buffer limit
+ * FALSE otherwise.
+ *
+ *********************************************************************/
+static int can_buffer_request_body(const struct client_state *csp)
+{
+ if (!can_add_to_iob(csp->client_iob, csp->config->buffer_limit,
+ csp->expected_client_content_length))
+ {
+ log_error(LOG_LEVEL_INFO,
+ "Not filtering request body from %s: buffer limit %lu will be exceeded "
+ "(content length %llu)", csp->ip_addr_str, csp->config->buffer_limit,
+ csp->expected_client_content_length);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+