mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-04 05:50:17 +00:00 
			
		
		
		
	Add an EFI HTTP driver. This commit implements the EFI_HTTP_PROTOCOL and the EFI_HTTP_SERVICE_BINDING_PROTOCOL. The latter is attached to the handle of th efi network device. This is the same handle where snp, pxe, and ipconfig are attached to. Signed-off-by: Adriano Cordova <adrianox@gmail.com>
		
			
				
	
	
		
			549 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			549 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
						|
/*
 | 
						|
 * An HTTP driver
 | 
						|
 *
 | 
						|
 * HTTP_PROTOCOL
 | 
						|
 * HTTP_SERVICE_BINDING_PROTOCOL
 | 
						|
 * IP4_CONFIG2_PROTOCOL
 | 
						|
 */
 | 
						|
 | 
						|
#include <charset.h>
 | 
						|
#include <efi_loader.h>
 | 
						|
#include <image.h>
 | 
						|
#include <malloc.h>
 | 
						|
#include <mapmem.h>
 | 
						|
#include <net.h>
 | 
						|
 | 
						|
static const efi_guid_t efi_http_service_binding_guid = EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID;
 | 
						|
static const efi_guid_t efi_http_guid = EFI_HTTP_PROTOCOL_GUID;
 | 
						|
 | 
						|
/**
 | 
						|
 * struct efi_http_instance - EFI object representing an HTTP protocol instance
 | 
						|
 *
 | 
						|
 * @http:			EFI_HTTP_PROTOCOL interface
 | 
						|
 * @handle:			handle to efi object
 | 
						|
 * @configured:			configuration status
 | 
						|
 * @http_load_addr:		data buffer
 | 
						|
 * @file_size:			size of data
 | 
						|
 * @current_offset:		offset in data buffer
 | 
						|
 * @status_code:		HTTP status code
 | 
						|
 * @num_headers:		number of received headers
 | 
						|
 * @headers:			array of headers
 | 
						|
 * @headers_buffer:		raw buffer with headers
 | 
						|
 */
 | 
						|
struct efi_http_instance {
 | 
						|
	struct efi_http_protocol http;
 | 
						|
	efi_handle_t handle;
 | 
						|
	bool configured;
 | 
						|
	void *http_load_addr;
 | 
						|
	ulong file_size;
 | 
						|
	ulong current_offset;
 | 
						|
	u32 status_code;
 | 
						|
	ulong num_headers;
 | 
						|
	struct http_header headers[MAX_HTTP_HEADERS];
 | 
						|
	char headers_buffer[MAX_HTTP_HEADERS_SIZE];
 | 
						|
};
 | 
						|
 | 
						|
static int num_instances;
 | 
						|
 | 
						|
/*
 | 
						|
 * efi_u32_to_httpstatus() - convert u32 to status
 | 
						|
 *
 | 
						|
 */
 | 
						|
enum efi_http_status_code efi_u32_to_httpstatus(u32 status);
 | 
						|
 | 
						|
/*
 | 
						|
 * efi_http_send_data() - sends data to client
 | 
						|
 *
 | 
						|
 *
 | 
						|
 * @client_buffer:		client buffer to send data to
 | 
						|
 * @client_buffer_size:		size of the client buffer
 | 
						|
 * @inst:			HTTP instance for which to send data
 | 
						|
 *
 | 
						|
 * Return:	status code
 | 
						|
 */
 | 
						|
static efi_status_t efi_http_send_data(void *client_buffer,
 | 
						|
				       efi_uintn_t *client_buffer_size,
 | 
						|
				       struct efi_http_instance *inst)
 | 
						|
{
 | 
						|
	efi_status_t ret = EFI_SUCCESS;
 | 
						|
	ulong total_size, transfer_size;
 | 
						|
	uchar *ptr;
 | 
						|
 | 
						|
	// Amount of data left;
 | 
						|
	total_size = inst->file_size;
 | 
						|
	transfer_size = total_size - inst->current_offset;
 | 
						|
	debug("efi_http: sending data to client, total size %lu\n", total_size);
 | 
						|
	// Amount of data the client is willing to receive
 | 
						|
	if (transfer_size > *client_buffer_size)
 | 
						|
		transfer_size = *client_buffer_size;
 | 
						|
	else
 | 
						|
		*client_buffer_size = transfer_size;
 | 
						|
	debug("efi_http: transfer size %lu\n", transfer_size);
 | 
						|
	if (!transfer_size) // Ok, only headers
 | 
						|
		goto out;
 | 
						|
 | 
						|
	if (!client_buffer) {
 | 
						|
		ret = EFI_INVALID_PARAMETER;
 | 
						|
		goto out;
 | 
						|
	}
 | 
						|
 | 
						|
	// Send data
 | 
						|
	ptr = (uchar *)inst->http_load_addr + inst->current_offset;
 | 
						|
	memcpy(client_buffer, ptr, transfer_size);
 | 
						|
 | 
						|
	inst->current_offset += transfer_size;
 | 
						|
 | 
						|
	// Whole file served, clean the buffer:
 | 
						|
	if (inst->current_offset == inst->file_size) {
 | 
						|
		efi_free_pool(inst->http_load_addr);
 | 
						|
		inst->http_load_addr = NULL;
 | 
						|
		inst->current_offset = 0;
 | 
						|
		inst->file_size = 0;
 | 
						|
	}
 | 
						|
 | 
						|
out:
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
 | 
						|
/* EFI_HTTP_PROTOCOL */
 | 
						|
 | 
						|
/*
 | 
						|
 * efi_http_get_mode_data() - Gets the current operational status.
 | 
						|
 *
 | 
						|
 * This function implements EFI_HTTP_PROTOCOL.GetModeData().
 | 
						|
 * See the Unified Extensible Firmware Interface
 | 
						|
 * (UEFI) specification for details.
 | 
						|
 *
 | 
						|
 * @this:	pointer to the protocol instance
 | 
						|
 * @data:	pointer to the buffer for operational parameters
 | 
						|
 *		of this HTTP instance
 | 
						|
 * Return:	status code
 | 
						|
 */
 | 
						|
static efi_status_t EFIAPI efi_http_get_mode_data(struct efi_http_protocol *this,
 | 
						|
						  struct efi_http_config_data *data)
 | 
						|
{
 | 
						|
	EFI_ENTRY("%p, %p", this, data);
 | 
						|
 | 
						|
	efi_status_t ret = EFI_UNSUPPORTED;
 | 
						|
 | 
						|
	return EFI_EXIT(ret);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * efi_http_configure() - Initializes operational status for this
 | 
						|
 * EFI HTTP instance.
 | 
						|
 *
 | 
						|
 * This function implements EFI_HTTP_PROTOCOL.Configure().
 | 
						|
 * See the Unified Extensible Firmware Interface
 | 
						|
 * (UEFI) specification for details.
 | 
						|
 *
 | 
						|
 * @this:	pointer to the protocol instance
 | 
						|
 * @data:	pointer to the buffer for operational parameters of
 | 
						|
 *		this HTTP instance
 | 
						|
 * Return:	status code
 | 
						|
 */
 | 
						|
static efi_status_t EFIAPI efi_http_configure(struct efi_http_protocol *this,
 | 
						|
					      struct efi_http_config_data *data)
 | 
						|
{
 | 
						|
	EFI_ENTRY("%p, %p", this, data);
 | 
						|
 | 
						|
	efi_status_t ret = EFI_SUCCESS;
 | 
						|
	enum efi_http_version http_version;
 | 
						|
	struct efi_httpv4_access_point *ipv4_node;
 | 
						|
	struct efi_http_instance *http_instance;
 | 
						|
 | 
						|
	if (!this) {
 | 
						|
		ret = EFI_INVALID_PARAMETER;
 | 
						|
		goto out;
 | 
						|
	}
 | 
						|
 | 
						|
	http_instance = (struct efi_http_instance *)this;
 | 
						|
 | 
						|
	if (!data) {
 | 
						|
		efi_free_pool(http_instance->http_load_addr);
 | 
						|
		http_instance->http_load_addr = NULL;
 | 
						|
		http_instance->current_offset = 0;
 | 
						|
		http_instance->configured = false;
 | 
						|
 | 
						|
		goto out;
 | 
						|
	}
 | 
						|
 | 
						|
	if (http_instance->configured) {
 | 
						|
		ret = EFI_ALREADY_STARTED;
 | 
						|
		goto out;
 | 
						|
	}
 | 
						|
 | 
						|
	http_version = data->http_version;
 | 
						|
	ipv4_node = data->access_point.ipv4_node;
 | 
						|
 | 
						|
	if ((http_version != HTTPVERSION10 &&
 | 
						|
	    http_version != HTTPVERSION11) ||
 | 
						|
	    data->is_ipv6 || !ipv4_node) { /* Only support ipv4 */
 | 
						|
		ret = EFI_UNSUPPORTED;
 | 
						|
		goto out;
 | 
						|
	}
 | 
						|
 | 
						|
	if (!ipv4_node->use_default_address) {
 | 
						|
		efi_net_set_addr((struct efi_ipv4_address *)&ipv4_node->local_address,
 | 
						|
				 (struct efi_ipv4_address *)&ipv4_node->local_subnet, NULL);
 | 
						|
	}
 | 
						|
 | 
						|
	http_instance->current_offset = 0;
 | 
						|
	http_instance->configured = true;
 | 
						|
 | 
						|
out:
 | 
						|
	return EFI_EXIT(ret);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * efi_http_request() - Queues an HTTP request to this HTTP instance
 | 
						|
 *
 | 
						|
 * This function implements EFI_HTTP_PROTOCOL.Request().
 | 
						|
 * See the Unified Extensible Firmware Interface
 | 
						|
 * (UEFI) specification for details.
 | 
						|
 *
 | 
						|
 * @this:	pointer to the protocol instance
 | 
						|
 * @token:	pointer to storage containing HTTP request token
 | 
						|
 * Return:	status code
 | 
						|
 */
 | 
						|
static efi_status_t EFIAPI efi_http_request(struct efi_http_protocol *this,
 | 
						|
					    struct efi_http_token *token)
 | 
						|
{
 | 
						|
	EFI_ENTRY("%p, %p", this, token);
 | 
						|
 | 
						|
	efi_status_t ret = EFI_SUCCESS;
 | 
						|
	u8 *tmp;
 | 
						|
	u8 url_8[1024];
 | 
						|
	u16 *url_16;
 | 
						|
	enum efi_http_method current_method;
 | 
						|
	struct efi_http_instance *http_instance;
 | 
						|
 | 
						|
	if (!token || !this || !token->message ||
 | 
						|
	    !token->message->data.request) {
 | 
						|
		ret = EFI_INVALID_PARAMETER;
 | 
						|
		goto out;
 | 
						|
	}
 | 
						|
 | 
						|
	http_instance = (struct efi_http_instance *)this;
 | 
						|
 | 
						|
	if (!http_instance->configured) {
 | 
						|
		ret = EFI_NOT_STARTED;
 | 
						|
		goto out;
 | 
						|
	}
 | 
						|
 | 
						|
	current_method = token->message->data.request->method;
 | 
						|
	url_16 = token->message->data.request->url;
 | 
						|
 | 
						|
	/* Parse URL. It comes in UCS-2 encoding and follows RFC3986 */
 | 
						|
	tmp = url_8;
 | 
						|
	utf16_utf8_strncpy((char **)&tmp, url_16, 1024);
 | 
						|
 | 
						|
	ret = efi_net_do_request(url_8, current_method, &http_instance->http_load_addr,
 | 
						|
				 &http_instance->status_code, &http_instance->file_size,
 | 
						|
				 http_instance->headers_buffer);
 | 
						|
	if (ret != EFI_SUCCESS)
 | 
						|
		goto out;
 | 
						|
 | 
						|
	// We have a successful request
 | 
						|
	efi_net_parse_headers(&http_instance->num_headers, http_instance->headers);
 | 
						|
	http_instance->current_offset = 0;
 | 
						|
	token->status = EFI_SUCCESS;
 | 
						|
	goto out_signal;
 | 
						|
 | 
						|
out_signal:
 | 
						|
	efi_signal_event(token->event);
 | 
						|
out:
 | 
						|
	return EFI_EXIT(ret);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * efi_http_cancel() - Abort an asynchronous HTTP request or response token
 | 
						|
 *
 | 
						|
 * This function implements EFI_HTTP_PROTOCOL.Cancel().
 | 
						|
 * See the Unified Extensible Firmware Interface
 | 
						|
 * (UEFI) specification for details.
 | 
						|
 *
 | 
						|
 * @this:	pointer to the protocol instance
 | 
						|
 * @token:	pointer to storage containing HTTP request token
 | 
						|
 * Return:	status code
 | 
						|
 */
 | 
						|
static efi_status_t EFIAPI efi_http_cancel(struct efi_http_protocol *this,
 | 
						|
					   struct efi_http_token *token)
 | 
						|
{
 | 
						|
	EFI_ENTRY("%p, %p", this, token);
 | 
						|
 | 
						|
	efi_status_t ret = EFI_UNSUPPORTED;
 | 
						|
 | 
						|
	return EFI_EXIT(ret);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * efi_http_response() -  Queues an HTTP response to this HTTP instance
 | 
						|
 *
 | 
						|
 * This function implements EFI_HTTP_PROTOCOL.Response().
 | 
						|
 * See the Unified Extensible Firmware Interface
 | 
						|
 * (UEFI) specification for details.
 | 
						|
 *
 | 
						|
 * @this:	pointer to the protocol instance
 | 
						|
 * @token:	pointer to storage containing HTTP request token
 | 
						|
 * Return:	status code
 | 
						|
 */
 | 
						|
static efi_status_t EFIAPI efi_http_response(struct efi_http_protocol *this,
 | 
						|
					     struct efi_http_token *token)
 | 
						|
{
 | 
						|
	EFI_ENTRY("%p, %p", this, token);
 | 
						|
 | 
						|
	efi_status_t ret = EFI_SUCCESS;
 | 
						|
	struct efi_http_instance *http_instance;
 | 
						|
	struct efi_http_header **client_headers;
 | 
						|
	struct efi_http_response_data *response;
 | 
						|
 | 
						|
	if (!token || !this || !token->message) {
 | 
						|
		ret = EFI_INVALID_PARAMETER;
 | 
						|
		goto out;
 | 
						|
	}
 | 
						|
 | 
						|
	http_instance = (struct efi_http_instance *)this;
 | 
						|
 | 
						|
	// Set HTTP status code
 | 
						|
	if (token->message->data.response) { // TODO extra check, see spec.
 | 
						|
		response = token->message->data.response;
 | 
						|
		response->status_code = efi_u32_to_httpstatus(http_instance->status_code);
 | 
						|
	}
 | 
						|
 | 
						|
	client_headers = &token->message->headers;
 | 
						|
 | 
						|
	ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA,
 | 
						|
				(http_instance->num_headers) * sizeof(struct efi_http_header),
 | 
						|
				(void **)client_headers); // This is deallocated by the client.
 | 
						|
	if (ret != EFI_SUCCESS)
 | 
						|
		goto out_bad_signal;
 | 
						|
 | 
						|
	// Send headers
 | 
						|
	token->message->header_count = http_instance->num_headers;
 | 
						|
	for (int i = 0; i < http_instance->num_headers; i++) {
 | 
						|
		(*client_headers)[i].field_name = http_instance->headers[i].name;
 | 
						|
		(*client_headers)[i].field_value = http_instance->headers[i].value;
 | 
						|
	}
 | 
						|
 | 
						|
	ret = efi_http_send_data(token->message->body, &token->message->body_length, http_instance);
 | 
						|
	if (ret != EFI_SUCCESS)
 | 
						|
		goto out_bad_signal;
 | 
						|
 | 
						|
	token->status = EFI_SUCCESS;
 | 
						|
	goto out_signal;
 | 
						|
 | 
						|
out_bad_signal:
 | 
						|
	token->status = EFI_ABORTED;
 | 
						|
out_signal:
 | 
						|
	efi_signal_event(token->event);
 | 
						|
out:
 | 
						|
	return EFI_EXIT(ret);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * efi_http_poll() -  Polls for incoming data packets and processes outgoing data packets
 | 
						|
 *
 | 
						|
 * This function implements EFI_HTTP_PROTOCOL.Poll().
 | 
						|
 * See the Unified Extensible Firmware Interface
 | 
						|
 * (UEFI) specification for details.
 | 
						|
 *
 | 
						|
 * @this:	pointer to the protocol instance
 | 
						|
 * @token:	pointer to storage containing HTTP request token
 | 
						|
 * Return:	status code
 | 
						|
 */
 | 
						|
static efi_status_t EFIAPI efi_http_poll(struct efi_http_protocol *this)
 | 
						|
{
 | 
						|
	EFI_ENTRY("%p", this);
 | 
						|
 | 
						|
	efi_status_t ret = EFI_UNSUPPORTED;
 | 
						|
 | 
						|
	return EFI_EXIT(ret);
 | 
						|
}
 | 
						|
 | 
						|
/* EFI_HTTP_SERVICE_BINDING_PROTOCOL */
 | 
						|
 | 
						|
/*
 | 
						|
 * efi_http_service_binding_create_child() -  Creates a child handle
 | 
						|
 * and installs a protocol
 | 
						|
 *
 | 
						|
 * This function implements EFI_HTTP_SERVICE_BINDING.CreateChild().
 | 
						|
 * See the Unified Extensible Firmware Interface
 | 
						|
 * (UEFI) specification for details.
 | 
						|
 *
 | 
						|
 * @this:		pointer to the protocol instance
 | 
						|
 * @child_handle:	pointer to child handle
 | 
						|
 * Return:		status code
 | 
						|
 */
 | 
						|
static efi_status_t EFIAPI efi_http_service_binding_create_child(
 | 
						|
			struct efi_service_binding_protocol *this,
 | 
						|
			efi_handle_t *child_handle)
 | 
						|
{
 | 
						|
	EFI_ENTRY("%p, %p", this, child_handle);
 | 
						|
 | 
						|
	efi_status_t ret = EFI_SUCCESS;
 | 
						|
	struct efi_http_instance *new_instance;
 | 
						|
 | 
						|
	if (!child_handle)
 | 
						|
		return EFI_EXIT(EFI_INVALID_PARAMETER);
 | 
						|
 | 
						|
	new_instance = calloc(1, sizeof(struct efi_http_instance));
 | 
						|
	if (!new_instance) {
 | 
						|
		ret = EFI_OUT_OF_RESOURCES;
 | 
						|
		goto failure_to_add_protocol;
 | 
						|
	}
 | 
						|
 | 
						|
	if (*child_handle) {
 | 
						|
		new_instance->handle = *child_handle;
 | 
						|
		goto install;
 | 
						|
	}
 | 
						|
 | 
						|
	new_instance->handle = calloc(1, sizeof(struct efi_object));
 | 
						|
	if (!new_instance->handle) {
 | 
						|
		efi_free_pool((void *)new_instance);
 | 
						|
		ret = EFI_OUT_OF_RESOURCES;
 | 
						|
		goto failure_to_add_protocol;
 | 
						|
	}
 | 
						|
 | 
						|
	efi_add_handle(new_instance->handle);
 | 
						|
	*child_handle = new_instance->handle;
 | 
						|
 | 
						|
install:
 | 
						|
	ret = efi_add_protocol(new_instance->handle, &efi_http_guid,
 | 
						|
			       &new_instance->http);
 | 
						|
	if (ret != EFI_SUCCESS)
 | 
						|
		goto failure_to_add_protocol;
 | 
						|
 | 
						|
	new_instance->http.get_mode_data = efi_http_get_mode_data;
 | 
						|
	new_instance->http.configure = efi_http_configure;
 | 
						|
	new_instance->http.request = efi_http_request;
 | 
						|
	new_instance->http.cancel = efi_http_cancel;
 | 
						|
	new_instance->http.response = efi_http_response;
 | 
						|
	new_instance->http.poll = efi_http_poll;
 | 
						|
	++num_instances;
 | 
						|
 | 
						|
	return EFI_EXIT(EFI_SUCCESS);
 | 
						|
 | 
						|
failure_to_add_protocol:
 | 
						|
	return EFI_EXIT(ret);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * efi_http_service_binding_destroy_child() -  Destroys a child handle with
 | 
						|
 * a protocol installed on it
 | 
						|
 *
 | 
						|
 * This function implements EFI_HTTP_SERVICE_BINDING.DestroyChild().
 | 
						|
 * See the Unified Extensible Firmware Interface
 | 
						|
 * (UEFI) specification for details.
 | 
						|
 *
 | 
						|
 * @this:		pointer to the protocol instance
 | 
						|
 * @child_handle:	child handle
 | 
						|
 * Return:		status code
 | 
						|
 */
 | 
						|
static efi_status_t EFIAPI efi_http_service_binding_destroy_child(
 | 
						|
			struct efi_service_binding_protocol *this,
 | 
						|
			efi_handle_t child_handle)
 | 
						|
{
 | 
						|
	EFI_ENTRY("%p, %p", this, child_handle);
 | 
						|
	efi_status_t ret = EFI_SUCCESS;
 | 
						|
	struct efi_http_instance *http_instance;
 | 
						|
	struct efi_handler *phandler;
 | 
						|
	void *protocol_interface;
 | 
						|
 | 
						|
	if (num_instances == 0)
 | 
						|
		return EFI_EXIT(EFI_NOT_FOUND);
 | 
						|
 | 
						|
	if (!child_handle)
 | 
						|
		return EFI_EXIT(EFI_INVALID_PARAMETER);
 | 
						|
 | 
						|
	efi_search_protocol(child_handle, &efi_http_guid, &phandler);
 | 
						|
 | 
						|
	if (phandler)
 | 
						|
		protocol_interface = phandler->protocol_interface;
 | 
						|
 | 
						|
	ret = efi_delete_handle(child_handle);
 | 
						|
	if (ret != EFI_SUCCESS)
 | 
						|
		return EFI_EXIT(ret);
 | 
						|
 | 
						|
	http_instance = (struct efi_http_instance *)protocol_interface;
 | 
						|
	efi_free_pool(http_instance->http_load_addr);
 | 
						|
	http_instance->http_load_addr = NULL;
 | 
						|
 | 
						|
	free(protocol_interface);
 | 
						|
 | 
						|
	num_instances--;
 | 
						|
 | 
						|
	return EFI_EXIT(EFI_SUCCESS);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * efi_http_register() - register the http protocol
 | 
						|
 *
 | 
						|
 */
 | 
						|
efi_status_t efi_http_register(const efi_handle_t handle,
 | 
						|
			       struct efi_service_binding_protocol *http_service_binding)
 | 
						|
{
 | 
						|
	efi_status_t r = EFI_SUCCESS;
 | 
						|
 | 
						|
	r = efi_add_protocol(handle, &efi_http_service_binding_guid,
 | 
						|
			     http_service_binding);
 | 
						|
	if (r != EFI_SUCCESS)
 | 
						|
		goto failure_to_add_protocol;
 | 
						|
 | 
						|
	http_service_binding->create_child = efi_http_service_binding_create_child;
 | 
						|
	http_service_binding->destroy_child = efi_http_service_binding_destroy_child;
 | 
						|
 | 
						|
	return EFI_SUCCESS;
 | 
						|
failure_to_add_protocol:
 | 
						|
	return r;
 | 
						|
}
 | 
						|
 | 
						|
enum efi_http_status_code efi_u32_to_httpstatus(u32 status)
 | 
						|
{
 | 
						|
	switch (status) {
 | 
						|
	case 100: return HTTP_STATUS_100_CONTINUE;
 | 
						|
	case 101: return HTTP_STATUS_101_SWITCHING_PROTOCOLS;
 | 
						|
	case 200: return HTTP_STATUS_200_OK;
 | 
						|
	case 201: return HTTP_STATUS_201_CREATED;
 | 
						|
	case 202: return HTTP_STATUS_202_ACCEPTED;
 | 
						|
	case 203: return HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION;
 | 
						|
	case 204: return HTTP_STATUS_204_NO_CONTENT;
 | 
						|
	case 205: return HTTP_STATUS_205_RESET_CONTENT;
 | 
						|
	case 206: return HTTP_STATUS_206_PARTIAL_CONTENT;
 | 
						|
	case 300: return HTTP_STATUS_300_MULTIPLE_CHOICES;
 | 
						|
	case 301: return HTTP_STATUS_301_MOVED_PERMANENTLY;
 | 
						|
	case 302: return HTTP_STATUS_302_FOUND;
 | 
						|
	case 303: return HTTP_STATUS_303_SEE_OTHER;
 | 
						|
	case 304: return HTTP_STATUS_304_NOT_MODIFIED;
 | 
						|
	case 305: return HTTP_STATUS_305_USE_PROXY;
 | 
						|
	case 307: return HTTP_STATUS_307_TEMPORARY_REDIRECT;
 | 
						|
	case 400: return HTTP_STATUS_400_BAD_REQUEST;
 | 
						|
	case 401: return HTTP_STATUS_401_UNAUTHORIZED;
 | 
						|
	case 402: return HTTP_STATUS_402_PAYMENT_REQUIRED;
 | 
						|
	case 403: return HTTP_STATUS_403_FORBIDDEN;
 | 
						|
	case 404: return HTTP_STATUS_404_NOT_FOUND;
 | 
						|
	case 405: return HTTP_STATUS_405_METHOD_NOT_ALLOWED;
 | 
						|
	case 406: return HTTP_STATUS_406_NOT_ACCEPTABLE;
 | 
						|
	case 407: return HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED;
 | 
						|
	case 408: return HTTP_STATUS_408_REQUEST_TIME_OUT;
 | 
						|
	case 409: return HTTP_STATUS_409_CONFLICT;
 | 
						|
	case 410: return HTTP_STATUS_410_GONE;
 | 
						|
	case 411: return HTTP_STATUS_411_LENGTH_REQUIRED;
 | 
						|
	case 412: return HTTP_STATUS_412_PRECONDITION_FAILED;
 | 
						|
	case 413: return HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE;
 | 
						|
	case 414: return HTTP_STATUS_414_REQUEST_URI_TOO_LARGE;
 | 
						|
	case 415: return HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE;
 | 
						|
	case 416: return HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED;
 | 
						|
	case 417: return HTTP_STATUS_417_EXPECTATION_FAILED;
 | 
						|
	case 500: return HTTP_STATUS_500_INTERNAL_SERVER_ERROR;
 | 
						|
	case 501: return HTTP_STATUS_501_NOT_IMPLEMENTED;
 | 
						|
	case 502: return HTTP_STATUS_502_BAD_GATEWAY;
 | 
						|
	case 503: return HTTP_STATUS_503_SERVICE_UNAVAILABLE;
 | 
						|
	case 504: return HTTP_STATUS_504_GATEWAY_TIME_OUT;
 | 
						|
	case 505: return HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED;
 | 
						|
	case 308: return HTTP_STATUS_308_PERMANENT_REDIRECT;
 | 
						|
	default: return HTTP_STATUS_UNSUPPORTED_STATUS;
 | 
						|
	}
 | 
						|
}
 |