Boot Linux faster!

Check our new training course

Boot Linux faster!

Check our new training course
and Creative Commons CC-BY-SA
lecture and lab materials

Bootlin logo

Elixir Cross Referencer

/*
 * Copyright (c) 2017 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include "http_client.h"
#include "http_client_rcv.h"
#include "http_client_cb.h"
#include "config.h"

#include <misc/printk.h>
#include <net/nbuf.h>

int http_init(struct http_client_ctx *http_ctx)
{
	memset(http_ctx, 0, sizeof(struct http_client_ctx));

	http_ctx->settings.on_body = on_body;
	http_ctx->settings.on_chunk_complete = on_chunk_complete;
	http_ctx->settings.on_chunk_header = on_chunk_header;
	http_ctx->settings.on_headers_complete = on_headers_complete;
	http_ctx->settings.on_header_field = on_header_field;
	http_ctx->settings.on_header_value = on_header_value;
	http_ctx->settings.on_message_begin = on_message_begin;
	http_ctx->settings.on_message_complete = on_message_complete;
	http_ctx->settings.on_status = on_status;
	http_ctx->settings.on_url = on_url;

	return 0;
}

int http_reset_ctx(struct http_client_ctx *http_ctx)
{
	http_parser_init(&http_ctx->parser, HTTP_RESPONSE);

	memset(http_ctx->http_status, 0, sizeof(http_ctx->http_status));

	http_ctx->cl_present = 0;
	http_ctx->content_length = 0;
	http_ctx->processed = 0;
	http_ctx->body_found = 0;

	return 0;
}

static
int http_send_request(struct http_client_ctx *http_ctx, const char *method,
		      const char *url, const char *protocol,
		      const char *content_type_value, const char *payload)
{
	const char *content_type = "Content-Type: ";
	const char *sep = "\r\n\r\n";
	struct net_buf *tx;
	int rc;

	tx = net_nbuf_get_tx(http_ctx->tcp_ctx.net_ctx, K_FOREVER);
	if (tx == NULL) {
		return -ENOMEM;
	}

	if (!net_nbuf_append(tx, strlen(method), (uint8_t *)method,
			     K_FOREVER)) {
		goto lb_exit;
	}

	if (!net_nbuf_append(tx, strlen(url), (uint8_t *)url, K_FOREVER)) {
		goto lb_exit;
	}

	if (!net_nbuf_append(tx, strlen(protocol), (uint8_t *)protocol,
			     K_FOREVER)) {
		goto lb_exit;
	}

	if (!net_nbuf_append(tx, strlen(HEADER_FIELDS),
			     (uint8_t *)HEADER_FIELDS, K_FOREVER)) {
		goto lb_exit;
	}

	if (content_type_value && payload) {
		char content_len_str[CON_LEN_SIZE];

		if (!net_nbuf_append(tx, strlen(content_type),
				     (uint8_t *)content_type, K_FOREVER)) {
			rc = -ENOMEM;
			goto lb_exit;
		}

		if (!net_nbuf_append(tx, strlen(content_type_value),
				     (uint8_t *)content_type_value,
				     K_FOREVER)) {
			rc = -ENOMEM;
			goto lb_exit;
		}

		rc = snprintk(content_len_str, sizeof(content_len_str),
			      "\r\nContent-Length: %u\r\n\r\n",
			      (unsigned int)strlen(payload));
		if (rc <= 0 || rc >= sizeof(content_len_str)) {
			rc = -ENOMEM;
			goto lb_exit;
		}

		if (!net_nbuf_append(tx, strlen(content_len_str),
				     (uint8_t *)content_len_str, K_FOREVER)) {
			rc = -ENOMEM;
			goto lb_exit;
		}

		if (!net_nbuf_append(tx, strlen(payload), (uint8_t *)payload,
				     K_FOREVER)) {
			rc = -ENOMEM;
			goto lb_exit;
		}

	} else {
		if (!net_nbuf_append(tx, strlen(sep), (uint8_t *)sep,
				     K_FOREVER)) {
			rc = -ENOMEM;
			goto lb_exit;
		}
	}

	return net_context_send(tx, NULL, http_ctx->tcp_ctx.timeout,
				NULL, NULL);

lb_exit:
	net_buf_unref(tx);

	return rc;
}

int http_send_get(struct http_client_ctx *http_ctx, const char *url)
{
	return http_send_request(http_ctx, "GET ", url, " HTTP/1.1\r\n",
				 NULL, NULL);
}

int http_send_head(struct http_client_ctx *http_ctx, const char *url)
{
	return http_send_request(http_ctx, "HEAD ", url, " HTTP/1.1\r\n",
				 NULL, NULL);
}

int http_send_options(struct http_client_ctx *http_ctx, const char *url,
		      const char *content_type_value, const char *payload)
{
	return http_send_request(http_ctx, "OPTIONS ", url, " HTTP/1.1\r\n",
				 content_type_value, payload);
}

int http_send_post(struct http_client_ctx *http_ctx, const char *url,
		   const char *content_type_value, const char *payload)
{
	return http_send_request(http_ctx, "POST ", url, " HTTP/1.1\r\n",
				 content_type_value, payload);
}