* @param name Header name ID (see @ref http_header_name_t).
* @param value Header value pointer.
* @param value_len Header value length.
+ *
+ * @return @c 0 if in case of success, @c -1 otherwise.
*/
-always_inline void
+always_inline int
http_add_header (http_headers_ctx_t *ctx, http_header_name_t name,
const char *value, uword value_len)
{
http_app_header_t *header;
- ASSERT ((ctx->tail_offset + sizeof (http_app_header_t) + value_len) <
- ctx->len);
+ if ((ctx->tail_offset + sizeof (http_app_header_t) + value_len) > ctx->len)
+ return -1;
header = (http_app_header_t *) (ctx->buf + ctx->tail_offset);
header->name = (u32) name;
header->value.len = (u32) value_len;
clib_memcpy (header->value.token, (u8 *) value, value_len);
ctx->tail_offset += sizeof (http_app_header_t) + value_len;
+ return 0;
}
/**
* @param name_len Header name length.
* @param value Header value pointer.
* @param value_len Header value length.
+ *
+ * @return @c 0 if in case of success, @c -1 otherwise.
*/
-always_inline void
+always_inline int
http_add_custom_header (http_headers_ctx_t *ctx, const char *name,
uword name_len, const char *value, uword value_len)
{
http_custom_token_t *token;
- ASSERT ((ctx->tail_offset + 2 * sizeof (http_custom_token_t) + name_len +
- value_len) < ctx->len);
+ if ((ctx->tail_offset + 2 * sizeof (http_custom_token_t) + name_len +
+ value_len) > ctx->len)
+ return -1;
/* name */
token = (http_custom_token_t *) (ctx->buf + ctx->tail_offset);
token->len = (u32) value_len;
clib_memcpy (token->token, (u8 *) value, token->len);
ctx->tail_offset += sizeof (http_custom_token_t) + value_len;
+ return 0;
+}
+
+/**
+ * Truncate the header list
+ *
+ * @param ctx Headers list context.
+ */
+always_inline void
+http_truncate_headers_list (http_headers_ctx_t *ctx)
+{
+ ctx->tail_offset = 0;
}
typedef enum http_uri_host_type_
/*? %%clicmd:group_label Static HTTP Server %% ?*/
#define HSS_FIFO_THRESH (16 << 10)
-
+#define HSS_HEADER_BUF_MAX_SIZE 16192
hss_main_t hss_main;
+static int
+hss_add_header (hss_session_t *hs, http_header_name_t name, const char *value,
+ uword value_len)
+{
+ u32 needed_size = 0;
+ while (http_add_header (&hs->resp_headers, name, value, value_len) == -1)
+ {
+ if (needed_size)
+ {
+ http_truncate_headers_list (&hs->resp_headers);
+ hs->data_len = 0;
+ return -1;
+ }
+ else
+ needed_size = hs->resp_headers.tail_offset +
+ sizeof (http_app_header_t) + value_len;
+ if (needed_size < HSS_HEADER_BUF_MAX_SIZE)
+ {
+ vec_resize (hs->headers_buf, sizeof (http_app_header_t) + value_len);
+ hs->resp_headers.len = needed_size;
+ hs->resp_headers.buf = hs->headers_buf;
+ }
+ else
+ {
+ http_truncate_headers_list (&hs->resp_headers);
+ hs->data_len = 0;
+ return -1;
+ }
+ }
+ return 0;
+}
+
static hss_session_t *
hss_session_alloc (u32 thread_index)
{
/* Set content type only if we have some response data */
if (hs->data_len)
- http_add_header (&hs->resp_headers, HTTP_HEADER_CONTENT_TYPE,
- http_content_type_token (args->ct));
+ if (hss_add_header (hs, HTTP_HEADER_CONTENT_TYPE,
+ http_content_type_token (args->ct)))
+ args->sc = HTTP_STATUS_INTERNAL_ERROR;
start_send_data (hs, args->sc);
}
/* Set content type only if we have some response data */
if (hs->data_len)
- http_add_header (&hs->resp_headers, HTTP_HEADER_CONTENT_TYPE,
- http_content_type_token (args.ct));
+ if (hss_add_header (hs, HTTP_HEADER_CONTENT_TYPE,
+ http_content_type_token (args.ct)))
+ sc = HTTP_STATUS_INTERNAL_ERROR;
start_send_data (hs, sc);
vec_free (port_str);
- http_add_header (&hs->resp_headers, HTTP_HEADER_LOCATION,
- (const char *) redirect, vec_len (redirect));
+ if (hss_add_header (hs, HTTP_HEADER_LOCATION, (const char *) redirect,
+ vec_len (redirect)))
+ return HTTP_STATUS_INTERNAL_ERROR;
+
vec_free (redirect);
hs->data_len = 0;
hs->free_data = 1;
* Last-Modified
*/
type = content_type_from_request (target);
- http_add_header (&hs->resp_headers, HTTP_HEADER_CONTENT_TYPE,
- http_content_type_token (type));
- http_add_header (&hs->resp_headers, HTTP_HEADER_CACHE_CONTROL,
- (const char *) hsm->max_age_formatted,
- vec_len (hsm->max_age_formatted));
- http_add_header (&hs->resp_headers, HTTP_HEADER_LAST_MODIFIED,
- (const char *) last_modified, vec_len (last_modified));
+ if (hss_add_header (hs, HTTP_HEADER_CONTENT_TYPE,
+ http_content_type_token (type)) ||
+ hss_add_header (hs, HTTP_HEADER_CACHE_CONTROL,
+ (const char *) hsm->max_age_formatted,
+ vec_len (hsm->max_age_formatted)) ||
+ hss_add_header (hs, HTTP_HEADER_LAST_MODIFIED,
+ (const char *) last_modified, vec_len (last_modified)))
+ {
+ sc = HTTP_STATUS_INTERNAL_ERROR;
+ }
done:
vec_free (sanitized_path);
if (msg.type != HTTP_MSG_REQUEST ||
(msg.method_type != HTTP_REQ_GET && msg.method_type != HTTP_REQ_POST))
{
- http_add_header (&hs->resp_headers, HTTP_HEADER_ALLOW,
- http_token_lit ("GET, POST"));
- start_send_data (hs, HTTP_STATUS_METHOD_NOT_ALLOWED);
+ if (hss_add_header (hs, HTTP_HEADER_ALLOW, http_token_lit ("GET, POST")))
+ start_send_data (hs, HTTP_STATUS_INTERNAL_ERROR);
+ else
+ start_send_data (hs, HTTP_STATUS_METHOD_NOT_ALLOWED);
goto err_done;
}