ws_parse_state_t _ws_read_http_headers(ws_t ws, struct evbuffer *in)
{
	char *line = NULL;
	char *header_name = NULL;
	char *header_val = NULL;
	ws_parse_state_t state = WS_PARSE_STATE_NEED_MORE;
	size_t len;
	assert(ws);
	assert(in);

	// TODO: Set a max header size to allow.

	while ((line = evbuffer_readln(in, &len, EVBUFFER_EOL_CRLF)) != NULL)
	{
		// Check for end of HTTP response (empty line).
		if (*line == '\0')
		{
			LIBWS_LOG(LIBWS_DEBUG2, "End of HTTP request");
			state = WS_PARSE_STATE_SUCCESS;
			break;	
		}

		if (_ws_parse_http_header(line, &header_name, &header_val))
		{
			LIBWS_LOG(LIBWS_ERR, "Failed to parse HTTP upgrade "
								 "repsonse line: %s", line);
			
			state = WS_PARSE_STATE_ERROR;
			break;
		}

		LIBWS_LOG(LIBWS_DEBUG2, "%s: %s", header_name, header_val);
		
		// Let the user get the header.
		if (ws->header_cb)
		{
			LIBWS_LOG(LIBWS_DEBUG2, "	Call header callback");

			if (ws->header_cb(ws, header_name, header_val, ws->header_arg))
			{
				LIBWS_LOG(LIBWS_DEBUG, "User header callback cancelled "
										"handshake");
				state = WS_PARSE_STATE_USER_ABORT;
				break;
			}
		}

		if (_ws_validate_http_headers(ws, header_name, header_val))
		{
			LIBWS_LOG(LIBWS_ERR, "	invalid");
			state = WS_PARSE_STATE_ERROR;
			break;
		}

		LIBWS_LOG(LIBWS_DEBUG2, "	valid");

		_ws_free(line);
		line = NULL;

		if (header_name) 
		{
			_ws_free(header_name);
			header_name = NULL;
		}

		if (header_val)
		{
			_ws_free(header_val);
			header_val = NULL;
		}
	}

	if (line) _ws_free(line);
	if (header_name) _ws_free(header_name);
	if (header_val) _ws_free(header_val);

	return state;
}
int TEST_ws_parse_http_header(int argc, char **argv)
{
    int ret = 0;
    char *line = "Origin:    arne weise    ";
    char *invalid_line = "Blarg";
    char *header_name;
    char *header_val;
    int i;

    libws_test_HEADLINE("TEST_ws_parse_http_header");

    if (libws_test_init(argc, argv)) return -1;

    libws_test_STATUS("Parse header \"%s\"", line);

    if (_ws_parse_http_header(line, &header_name, &header_val))
    {
        libws_test_FAILURE("Failed to parse header \"%s\"", line);
        ret = -1;
    }
    else
    {
        if (!header_name || !header_val)
        {
            if (!header_name)
            {
                libws_test_FAILURE("Header name NULL after parse");
                ret = -1;
            }

            if (!header_name)
            {
                libws_test_FAILURE("Header val NULL after parse");
                ret = -1;
            }
        }
        else
        {
            libws_test_SUCCESS("Parsed header \"%s\". "
                               "Name = \"%s\", Value = \"%s\"",
                               line, header_name, header_val);
        }
    }

    free(header_name);
    free(header_val);

    libws_test_STATUS("Parse invalid line:");

    if (_ws_parse_http_header(invalid_line, &header_name, &header_val))
    {
        if (header_name || header_val)
        {
            if (header_name)
            {
                libws_test_FAILURE("Header name not NULL after parse failure");
                ret = -1;
            }

            if (header_name)
            {
                libws_test_FAILURE("Header value not NULL after parse failure");
                ret = -1;
            }
        }
        else
        {
            libws_test_SUCCESS("Header name and value NULL after failed parse");
        }
    }

    libws_test_STATUS("Parse NULL line:");

    if (_ws_parse_http_header(NULL, &header_name, &header_val))
    {
        libws_test_SUCCESS("Failed on NULL input");
    }
    else
    {
        libws_test_FAILURE("Did not fail o NULL input");
        ret |= -1;
    }

    {
        int http_major_version;
        int http_minor_verson;
        int http_status;

        if (_ws_parse_http_status(NULL, &http_major_version,
                                  &http_minor_verson, &http_status))
        {
            libws_test_SUCCESS("Failed to parse HTTP status with NULL input");
        }
        else
        {
            libws_test_FAILURE("Success parsing HTTP status with NULL input");
            ret |= -1;
        }

        if (_ws_parse_http_status("HTTP/1.1 abc", &http_major_version,
                                  &http_minor_verson, &http_status))
        {
            libws_test_SUCCESS("Failed to parse HTTP status with NULL input");
        }
        else
        {
            libws_test_FAILURE("Success parsing HTTP status with NULL input");
            ret |= -1;
        }
    }

    ws_set_memory_functions(libws_test_malloc,
                            free,
                            libws_test_realloc);

    for (i = 1; i <= 2; i++)
    {
        libws_test_STATUS("Test failing malloc on allocation: %d", i);
        libws_test_set_malloc_fail_count(i);

        if (_ws_parse_http_header(line, &header_name, &header_val))
        {
            libws_test_SUCCESS("Failed as expected on NULL memory allocation "
                               "after %d allocations", i);
        }
        else
        {
            libws_test_FAILURE("Did not fail on NULL memory allocation "
                               "after %d allocations", i);
            ret |= -1;
        }
    }

    ws_set_memory_functions(NULL, NULL, NULL);

    return ret;
}