Index: uspace/app/download/Makefile
===================================================================
--- uspace/app/download/Makefile	(revision 3ce68b7bc50391278f778663dd78d5162fbda5d0)
+++ uspace/app/download/Makefile	(revision b623b68e159f4973ecd11ab5fb53eca272b74c6d)
@@ -29,5 +29,5 @@
 USPACE_PREFIX = ../..
 LIBS = $(LIBHTTP_PREFIX)/libhttp.a $(LIBURI_PREFIX)/liburi.a
-EXTRA_CFLAGS = -I$(LIBHTTP_PREFIX) -I$(LIBURI_PREFIX)
+EXTRA_CFLAGS = -I$(LIBHTTP_PREFIX)/include -I$(LIBURI_PREFIX)
 DEFS = -DRELEASE=$(RELEASE)
 BINARY = download
Index: uspace/app/download/main.c
===================================================================
--- uspace/app/download/main.c	(revision 3ce68b7bc50391278f778663dd78d5162fbda5d0)
+++ uspace/app/download/main.c	(revision b623b68e159f4973ecd11ab5fb53eca272b74c6d)
@@ -47,5 +47,5 @@
 #include <net/socket.h>
 
-#include <http.h>
+#include <http/http.h>
 #include <uri.h>
 
Index: uspace/lib/http/Makefile
===================================================================
--- uspace/lib/http/Makefile	(revision 3ce68b7bc50391278f778663dd78d5162fbda5d0)
+++ uspace/lib/http/Makefile	(revision b623b68e159f4973ecd11ab5fb53eca272b74c6d)
@@ -31,12 +31,12 @@
 SLIBRARY = libhttp.so.0.0
 LSONAME = libhttp.so0
-#EXTRA_CFLAGS += 
+EXTRA_CFLAGS += -Iinclude
 
 SOURCES = \
-	http.c \
-	headers.c \
-	request.c \
-	response.c \
-	receive-buffer.c
+	src/http.c \
+	src/headers.c \
+	src/request.c \
+	src/response.c \
+	src/receive-buffer.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/http/headers.c
===================================================================
--- uspace/lib/http/headers.c	(revision 3ce68b7bc50391278f778663dd78d5162fbda5d0)
+++ 	(revision )
@@ -1,250 +1,0 @@
-/*
- * Copyright (c) 2013 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup http
- * @{
- */
-/**
- * @file
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <str.h>
-#include <macros.h>
-
-#include "http.h"
-#include "http-ctype.h"
-
-#define HTTP_HEADER_LINE "%s: %s\r\n"
-
-void http_header_init(http_header_t *header)
-{
-	link_initialize(&header->link);
-	header->name = NULL;
-	header->value = NULL;
-}
-
-http_header_t *http_header_create(const char *name, const char *value)
-{
-	http_header_t *header = malloc(sizeof(http_header_t));
-	if (header == NULL)
-		return NULL;
-	http_header_init(header);
-
-	header->name = str_dup(name);
-	if (header->name == NULL) {
-		free(header);
-		return NULL;
-	}
-	
-	header->value = str_dup(value);
-	if (header->value == NULL) {
-		free(header->name);
-		free(header);
-		return NULL;
-	}
-
-	return header;
-}
-
-void http_header_destroy(http_header_t *header)
-{
-	free(header->name);
-	free(header->value);
-	free(header);
-}
-
-ssize_t http_header_encode(http_header_t *header, char *buf, size_t buf_size)
-{
-	/* TODO properly split long header values */
-	if (buf == NULL) {
-		return printf_size(HTTP_HEADER_LINE, header->name, header->value);
-	}
-	else {
-		return snprintf(buf, buf_size,
-		    HTTP_HEADER_LINE, header->name, header->value);
-	}
-}
-
-int http_header_receive_name(receive_buffer_t *rb, char **out_name)
-{
-	receive_buffer_mark_t name_start;
-	receive_buffer_mark_t name_end;
-	
-	recv_mark(rb, &name_start);
-	recv_mark(rb, &name_end);
-	
-	char c = 0;
-	do {
-		recv_mark_update(rb, &name_end);
-		
-		int rc = recv_char(rb, &c, true);
-		if (rc != EOK) {
-			recv_unmark(rb, &name_start);
-			recv_unmark(rb, &name_end);
-			return rc;
-		}
-	} while (is_token(c));
-	
-	if (c != ':') {
-		recv_unmark(rb, &name_start);
-		recv_unmark(rb, &name_end);
-		return EINVAL;
-	}
-	
-	char *name = NULL;
-	int rc = recv_cut_str(rb, &name_start, &name_end, &name);
-	recv_unmark(rb, &name_start);
-	recv_unmark(rb, &name_end);
-	if (rc != EOK)
-		return rc;
-	
-	*out_name = name;
-	return EOK;
-}
-
-int http_header_receive_value(receive_buffer_t *rb, char **out_value)
-{
-	int rc = EOK;
-	char c = 0;
-	
-	receive_buffer_mark_t value_start;
-	recv_mark(rb, &value_start);
-	
-	/* Ignore any inline LWS */
-	while (true) {
-		recv_mark_update(rb, &value_start);
-		rc = recv_char(rb, &c, false);
-		if (rc != EOK)
-			goto error;
-		
-		if (c != ' ' && c != '\t')
-			break;
-		
-		rc = recv_char(rb, &c, true);
-		if (rc != EOK)
-			goto error;
-	}
-	
-	receive_buffer_mark_t value_end;
-	recv_mark(rb, &value_end);
-	
-	while (true) {
-		recv_mark_update(rb, &value_end);
-		
-		rc = recv_char(rb, &c, true);
-		if (rc != EOK)
-			goto error_end;
-		
-		if (c != '\r' && c != '\n')
-			continue;
-		
-		rc = recv_discard(rb, (c == '\r' ? '\n' : '\r'));
-		if (rc < 0)
-			goto error_end;
-		
-		rc = recv_char(rb, &c, false);
-		if (rc != EOK)
-			goto error_end;
-		
-		if (c != ' ' && c != '\t')
-			break;
-		
-		/* Ignore the char */
-		rc = recv_char(rb, &c, true);
-		if (rc != EOK)
-			goto error_end;
-	}
-	
-	char *value = NULL;
-	rc = recv_cut_str(rb, &value_start, &value_end, &value);
-	recv_unmark(rb, &value_start);
-	recv_unmark(rb, &value_end);
-	if (rc != EOK)
-		return rc;
-	
-	*out_value = value;
-	return EOK;
-error_end:
-	recv_unmark(rb, &value_end);
-error:
-	recv_unmark(rb, &value_start);
-	return rc;
-}
-
-int http_header_receive(receive_buffer_t *rb, http_header_t *header)
-{
-	char *name = NULL;
-	int rc = http_header_receive_name(rb, &name);
-	if (rc != EOK) {
-		printf("Failed receiving header name\n");
-		return rc;
-	}
-	
-	char *value = NULL;
-	rc = http_header_receive_value(rb, &value);
-	if (rc != EOK) {
-		free(name);
-		return rc;
-	}
-	
-	header->name = name;
-	header->value = value;
-	return EOK;
-}
-
-/** Normalize HTTP header value
- *
- * @see RFC2616 section 4.2
- */
-void http_header_normalize_value(char *value)
-{
-	size_t read_index = 0;
-	size_t write_index = 0;
-	
-	while (is_lws(value[read_index])) read_index++;
-	
-	while (value[read_index] != 0) {
-		if (is_lws(value[read_index])) {
-			while (is_lws(value[read_index])) read_index++;
-			
-			if (value[read_index] != 0)
-				value[write_index++] = ' ';
-			
-			continue;
-		}
-		
-		value[write_index++] = value[read_index++];
-	}
-	
-	value[write_index] = 0;
-}
-
-/** @}
- */
Index: uspace/lib/http/http-ctype.h
===================================================================
--- uspace/lib/http/http-ctype.h	(revision 3ce68b7bc50391278f778663dd78d5162fbda5d0)
+++ 	(revision )
@@ -1,94 +1,0 @@
-/*
- * Copyright (c) 2013 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup http
- * @{
- */
-/**
- * @file
- */
-
-#ifndef HTTP_CTYPE_H_
-#define HTTP_CTYPE_H_
-
-static inline bool is_separator(char c)
-{
-	switch (c) {
-	case '(':
-	case ')':
-	case '<':
-	case '>':
-	case '@':
-	case ',':
-	case ';':
-	case ':':
-	case '\\':
-	case '"':
-	case '/':
-	case '[':
-	case ']':
-	case '?':
-	case '=':
-	case '{':
-	case '}':
-	case ' ':
-	case '\t':
-		return true;
-	default:
-		return false;
-	}
-}
-
-static inline bool is_lws(char c)
-{
-	switch (c) {
-	case '\r':
-	case '\n':
-	case ' ':
-	case '\t':
-		return true;
-	default:
-		return false;
-	}
-}
-
-static inline bool is_ctl(char c)
-{
-	return c < 32 || c == 127;
-}
-
-static inline bool is_token(char c)
-{
-	return !is_separator(c) && !is_ctl(c);
-}
-
-
-#endif
-
-/** @}
- */
Index: uspace/lib/http/http.c
===================================================================
--- uspace/lib/http/http.c	(revision 3ce68b7bc50391278f778663dd78d5162fbda5d0)
+++ 	(revision )
@@ -1,136 +1,0 @@
-/*
- * Copyright (c) 2013 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup http
- * @{
- */
-/**
- * @file
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <str.h>
-#include <macros.h>
-
-#include <net/socket.h>
-#include <inet/dnsr.h>
-
-#include "http.h"
-#include "receive-buffer.h"
-
-static ssize_t http_receive(void *client_data, void *buf, size_t buf_size)
-{
-	http_t *http = client_data;
-	return recv(http->conn_sd, buf, buf_size, 0);
-}
-
-http_t *http_create(const char *host, uint16_t port)
-{
-	http_t *http = malloc(sizeof(http_t));
-	if (http == NULL)
-		return NULL;
-	
-	http->host = str_dup(host);
-	if (http->host == NULL) {
-		free(http);
-		return NULL;
-	}
-	http->port = port;
-	
-	http->buffer_size = 4096;
-	int rc = recv_buffer_init(&http->recv_buffer, http->buffer_size,
-	    http_receive, http);
-	if (rc != EOK) {
-		free(http);
-		return NULL;
-	}
-	
-	return http;
-}
-
-int http_connect(http_t *http)
-{
-	if (http->connected)
-		return EBUSY;
-	
-	/* Interpret as address */
-	int rc = inet_addr_parse(http->host, &http->addr);
-	
-	if (rc != EOK) {
-		/* Interpret as a host name */
-		dnsr_hostinfo_t *hinfo = NULL;
-		rc = dnsr_name2host(http->host, &hinfo, AF_NONE);
-		
-		if (rc != EOK)
-			return rc;
-		
-		http->addr = hinfo->addr;
-		dnsr_hostinfo_destroy(hinfo);
-	}
-	
-	struct sockaddr_in addr;
-	struct sockaddr_in6 addr6;
-	uint16_t af = inet_addr_sockaddr_in(&http->addr, &addr, &addr6);
-	
-	http->conn_sd = socket(PF_INET, SOCK_STREAM, 0);
-	if (http->conn_sd < 0)
-		return http->conn_sd;
-	
-	switch (af) {
-	case AF_INET:
-		addr.sin_port = htons(http->port);
-		rc = connect(http->conn_sd, (struct sockaddr *) &addr, sizeof(addr));
-		break;
-	case AF_INET6:
-		addr6.sin6_port = htons(http->port);
-		rc = connect(http->conn_sd, (struct sockaddr *) &addr6, sizeof(addr6));
-		break;
-	default:
-		return ENOTSUP;
-	}
-	
-	return rc;
-}
-
-int http_close(http_t *http)
-{
-	if (!http->connected)
-		return EINVAL;
-	
-	return closesocket(http->conn_sd);
-}
-
-void http_destroy(http_t *http)
-{
-	recv_buffer_fini(&http->recv_buffer);
-	free(http);
-}
-
-/** @}
- */
Index: uspace/lib/http/http.h
===================================================================
--- uspace/lib/http/http.h	(revision 3ce68b7bc50391278f778663dd78d5162fbda5d0)
+++ 	(revision )
@@ -1,108 +1,0 @@
-/*
- * Copyright (c) 2013 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup http
- * @{
- */
-/**
- * @file
- */
-
-#ifndef HTTP_HTTP_H_
-#define HTTP_HTTP_H_
-
-#include <net/socket.h>
-#include <adt/list.h>
-#include <inet/addr.h>
-
-#include "receive-buffer.h"
-
-typedef struct {
-	char *host;
-	uint16_t port;
-	inet_addr_t addr;
-
-	bool connected;
-	int conn_sd;
-	
-	size_t buffer_size;
-	receive_buffer_t recv_buffer;
-} http_t;
-
-typedef struct {
-	uint8_t minor;
-	uint8_t major;
-} http_version_t;
-
-typedef struct {
-	link_t link;
-	char *name;
-	char *value;
-} http_header_t;
-
-typedef struct {
-	char *method;
-	char *path;
-	list_t headers;
-} http_request_t;
-
-typedef struct {
-	http_version_t version;
-	uint16_t status;
-	char *message;
-	list_t headers;
-} http_response_t;
-
-extern http_t *http_create(const char *, uint16_t);
-extern int http_connect(http_t *);
-
-extern void http_header_init(http_header_t *);
-extern http_header_t *http_header_create(const char *, const char *);
-extern int http_header_receive_name(receive_buffer_t *, char **);
-extern int http_header_receive_value(receive_buffer_t *, char **);
-extern int http_header_receive(receive_buffer_t *, http_header_t *);
-extern void http_header_normalize_value(char *);
-ssize_t http_header_encode(http_header_t *, char *, size_t);
-extern void http_header_destroy(http_header_t *);
-
-extern http_request_t *http_request_create(const char *, const char *);
-extern void http_request_destroy(http_request_t *);
-extern int http_request_format(http_request_t *, char **, size_t *);
-extern int http_send_request(http_t *, http_request_t *);
-extern int http_parse_status(const char *, http_version_t *, uint16_t *,
-    char **);
-extern int http_receive_response(http_t *, http_response_t **);
-extern int http_receive_body(http_t *, void *, size_t);
-extern void http_response_destroy(http_response_t *);
-extern int http_close(http_t *);
-extern void http_destroy(http_t *);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/http/include/http/ctype.h
===================================================================
--- uspace/lib/http/include/http/ctype.h	(revision b623b68e159f4973ecd11ab5fb53eca272b74c6d)
+++ uspace/lib/http/include/http/ctype.h	(revision b623b68e159f4973ecd11ab5fb53eca272b74c6d)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2013 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup http
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef HTTP_CTYPE_H_
+#define HTTP_CTYPE_H_
+
+static inline bool is_separator(char c)
+{
+	switch (c) {
+	case '(':
+	case ')':
+	case '<':
+	case '>':
+	case '@':
+	case ',':
+	case ';':
+	case ':':
+	case '\\':
+	case '"':
+	case '/':
+	case '[':
+	case ']':
+	case '?':
+	case '=':
+	case '{':
+	case '}':
+	case ' ':
+	case '\t':
+		return true;
+	default:
+		return false;
+	}
+}
+
+static inline bool is_lws(char c)
+{
+	switch (c) {
+	case '\r':
+	case '\n':
+	case ' ':
+	case '\t':
+		return true;
+	default:
+		return false;
+	}
+}
+
+static inline bool is_ctl(char c)
+{
+	return c < 32 || c == 127;
+}
+
+static inline bool is_token(char c)
+{
+	return !is_separator(c) && !is_ctl(c);
+}
+
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/http/include/http/http.h
===================================================================
--- uspace/lib/http/include/http/http.h	(revision b623b68e159f4973ecd11ab5fb53eca272b74c6d)
+++ uspace/lib/http/include/http/http.h	(revision b623b68e159f4973ecd11ab5fb53eca272b74c6d)
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2013 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup http
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef HTTP_HTTP_H_
+#define HTTP_HTTP_H_
+
+#include <net/socket.h>
+#include <adt/list.h>
+#include <inet/addr.h>
+
+#include "receive-buffer.h"
+
+typedef struct {
+	char *host;
+	uint16_t port;
+	inet_addr_t addr;
+
+	bool connected;
+	int conn_sd;
+	
+	size_t buffer_size;
+	receive_buffer_t recv_buffer;
+} http_t;
+
+typedef struct {
+	uint8_t minor;
+	uint8_t major;
+} http_version_t;
+
+typedef struct {
+	link_t link;
+	char *name;
+	char *value;
+} http_header_t;
+
+typedef struct {
+	char *method;
+	char *path;
+	list_t headers;
+} http_request_t;
+
+typedef struct {
+	http_version_t version;
+	uint16_t status;
+	char *message;
+	list_t headers;
+} http_response_t;
+
+extern http_t *http_create(const char *, uint16_t);
+extern int http_connect(http_t *);
+
+extern void http_header_init(http_header_t *);
+extern http_header_t *http_header_create(const char *, const char *);
+extern int http_header_receive_name(receive_buffer_t *, char **);
+extern int http_header_receive_value(receive_buffer_t *, char **);
+extern int http_header_receive(receive_buffer_t *, http_header_t *);
+extern void http_header_normalize_value(char *);
+ssize_t http_header_encode(http_header_t *, char *, size_t);
+extern void http_header_destroy(http_header_t *);
+
+extern http_request_t *http_request_create(const char *, const char *);
+extern void http_request_destroy(http_request_t *);
+extern int http_request_format(http_request_t *, char **, size_t *);
+extern int http_send_request(http_t *, http_request_t *);
+extern int http_parse_status(const char *, http_version_t *, uint16_t *,
+    char **);
+extern int http_receive_response(http_t *, http_response_t **);
+extern int http_receive_body(http_t *, void *, size_t);
+extern void http_response_destroy(http_response_t *);
+extern int http_close(http_t *);
+extern void http_destroy(http_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/http/include/http/receive-buffer.h
===================================================================
--- uspace/lib/http/include/http/receive-buffer.h	(revision b623b68e159f4973ecd11ab5fb53eca272b74c6d)
+++ uspace/lib/http/include/http/receive-buffer.h	(revision b623b68e159f4973ecd11ab5fb53eca272b74c6d)
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup http
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef HTTP_RECEIVE_BUFFER_H_
+#define HTTP_RECEIVE_BUFFER_H_
+
+#include <adt/list.h>
+
+/** Receive data.
+ *
+ * @param client_data client data
+ * @param buf buffer to store the data
+ * @param buf_size buffer size
+ * @return number of bytes received or negative error code
+ */
+typedef ssize_t (*receive_func_t)(void *, void *, size_t);
+
+typedef struct {
+	size_t size;
+	char *buffer;
+	size_t in;
+	size_t out;
+	
+	void *client_data;
+	receive_func_t receive;
+	
+	list_t marks;
+} receive_buffer_t;
+
+typedef struct {
+	link_t link;
+	size_t offset;
+} receive_buffer_mark_t;
+
+extern int recv_buffer_init(receive_buffer_t *, size_t, receive_func_t, void *);
+extern int recv_buffer_init_const(receive_buffer_t *, void *, size_t);
+extern void recv_buffer_fini(receive_buffer_t *);
+extern void recv_reset(receive_buffer_t *);
+extern void recv_mark(receive_buffer_t *, receive_buffer_mark_t *);
+extern void recv_unmark(receive_buffer_t *, receive_buffer_mark_t *);
+extern void recv_mark_update(receive_buffer_t *, receive_buffer_mark_t *);
+extern int recv_cut(receive_buffer_t *, receive_buffer_mark_t *,
+    receive_buffer_mark_t *, void **, size_t *);
+extern int recv_cut_str(receive_buffer_t *, receive_buffer_mark_t *,
+    receive_buffer_mark_t *, char **);
+extern int recv_char(receive_buffer_t *, char *, bool);
+extern ssize_t recv_buffer(receive_buffer_t *, char *, size_t);
+extern ssize_t recv_discard(receive_buffer_t *, char);
+extern ssize_t recv_eol(receive_buffer_t *);
+extern ssize_t recv_line(receive_buffer_t *, char *, size_t);
+
+
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/http/receive-buffer.c
===================================================================
--- uspace/lib/http/receive-buffer.c	(revision 3ce68b7bc50391278f778663dd78d5162fbda5d0)
+++ 	(revision )
@@ -1,265 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * Copyright (c) 2013 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup http
- * @{
- */
-/**
- * @file
- */
-
-#include <stdlib.h>
-#include <str.h>
-#include <errno.h>
-#include <macros.h>
-#include <adt/list.h>
-
-#include "receive-buffer.h"
-
-int recv_buffer_init(receive_buffer_t *rb, size_t buffer_size,
-    receive_func_t receive, void *client_data)
-{
-	rb->receive = receive;
-	rb->client_data = client_data;
-	
-	rb->in = 0;
-	rb->out = 0;
-	rb->size = buffer_size;
-	
-	list_initialize(&rb->marks);
-	
-	rb->buffer = malloc(buffer_size);
-	if (rb->buffer == NULL)
-		return ENOMEM;
-	return EOK;
-}
-
-static ssize_t dummy_receive(void *unused, void *buf, size_t buf_size)
-{
-	return 0;
-}
-
-int recv_buffer_init_const(receive_buffer_t *rb, void *buf, size_t size)
-{
-	int rc = recv_buffer_init(rb, size, dummy_receive, NULL);
-	if (rc != EOK)
-		return rc;
-	
-	memcpy(rb->buffer, buf, size);
-	rb->in = size;
-	return EOK;
-}
-
-void recv_buffer_fini(receive_buffer_t *rb)
-{
-	free(rb->buffer);
-}
-
-void recv_reset(receive_buffer_t *rb)
-{
-	rb->in = 0;
-	rb->out = 0;
-}
-
-void recv_mark(receive_buffer_t *rb, receive_buffer_mark_t *mark)
-{
-	link_initialize(&mark->link);
-	list_append(&mark->link, &rb->marks);
-	recv_mark_update(rb, mark);
-}
-
-void recv_unmark(receive_buffer_t *rb, receive_buffer_mark_t *mark)
-{
-	list_remove(&mark->link);
-}
-
-void recv_mark_update(receive_buffer_t *rb, receive_buffer_mark_t *mark)
-{
-	mark->offset = rb->out;
-}
-
-int recv_cut(receive_buffer_t *rb, receive_buffer_mark_t *a, receive_buffer_mark_t *b, void **out_buf, size_t *out_size)
-{
-	if (a->offset > b->offset)
-		return EINVAL;
-	
-	size_t size = b->offset - a->offset;
-	void *buf = malloc(size);
-	if (buf == NULL)
-		return ENOMEM;
-	
-	memcpy(buf, rb->buffer + a->offset, size);
-	*out_buf = buf;
-	*out_size = size;
-	return EOK;
-}
-
-int recv_cut_str(receive_buffer_t *rb, receive_buffer_mark_t *a, receive_buffer_mark_t *b, char **out_buf)
-{
-	if (a->offset > b->offset)
-		return EINVAL;
-	
-	size_t size = b->offset - a->offset;
-	char *buf = malloc(size + 1);
-	if (buf == NULL)
-		return ENOMEM;
-	
-	memcpy(buf, rb->buffer + a->offset, size);
-	buf[size] = 0;
-	for (size_t i = 0; i < size; i++) {
-		if (buf[i] == 0) {
-			free(buf);
-			return EIO;
-		}
-	}
-	*out_buf = buf;
-	return EOK;
-}
-
-
-/** Receive one character (with buffering) */
-int recv_char(receive_buffer_t *rb, char *c, bool consume)
-{
-	if (rb->out == rb->in) {
-		size_t free = rb->size - rb->in;
-		if (free == 0) {
-			size_t min_mark = rb->size;
-			list_foreach(rb->marks, link, receive_buffer_mark_t, mark) {
-				min_mark = min(min_mark, mark->offset);
-			}
-			
-			if (min_mark == 0)
-				return ELIMIT;
-			
-			size_t new_in = rb->in - min_mark;
-			memmove(rb->buffer, rb->buffer + min_mark, new_in);
-			rb->out = rb->in = new_in;
-			free = rb->size - rb->in;
-			list_foreach(rb->marks, link, receive_buffer_mark_t, mark) {
-				mark->offset -= min_mark;
-			}
-		}
-		
-		ssize_t rc = rb->receive(rb->client_data, rb->buffer + rb->in, free);
-		if (rc <= 0)
-			return rc;
-		
-		rb->in = rc;
-	}
-	
-	*c = rb->buffer[rb->out];
-	if (consume)
-		rb->out++;
-	return EOK;
-}
-
-ssize_t recv_buffer(receive_buffer_t *rb, char *buf, size_t buf_size)
-{
-	/* Flush any buffered data*/
-	if (rb->out != rb->in) {
-		size_t size = min(rb->in - rb->out, buf_size);
-		memcpy(buf, rb->buffer + rb->out, size);
-		rb->out += size;
-		return size;
-	}
-	
-	return rb->receive(rb->client_data, buf, buf_size);
-}
-
-/** Receive a character and if it is c, discard it from input buffer
- * @return number of characters discarded (0 or 1) or negative error code
- */
-ssize_t recv_discard(receive_buffer_t *rb, char discard)
-{
-	char c = 0;
-	int rc = recv_char(rb, &c, false);
-	if (rc != EOK)
-		return rc;
-	if (c != discard)
-		return 0;
-	rc = recv_char(rb, &c, true);
-	if (rc != EOK)
-		return rc;
-	return 1;
-}
-
-/** Receive an end of line, either CR, LF, CRLF or LFCR
- *
- * @return number of bytes read (0 if no newline is present in the stream)
- *         or negative error code
- */
-ssize_t recv_eol(receive_buffer_t *rb)
-{
-	char c = 0;
-	int rc = recv_char(rb, &c, false);
-	if (rc != EOK)
-		return rc;
-	
-	if (c != '\r' && c != '\n')
-		return 0;
-	
-	rc = recv_char(rb, &c, true);
-	if (rc != EOK)
-		return rc;
-	
-	ssize_t rc2 = recv_discard(rb, (c == '\r' ? '\n' : '\r'));
-	if (rc2 < 0)
-		return rc2;
-	
-	return 1 + rc2;
-}
-
-/* Receive a single line */
-ssize_t recv_line(receive_buffer_t *rb, char *line, size_t size)
-{
-	size_t written = 0;
-	
-	while (written < size) {
-		char c = 0;
-		int rc = recv_char(rb, &c, true);
-		if (rc != EOK)
-			return rc;
-		if (c == '\n') {
-			recv_discard(rb, '\r');
-			line[written++] = 0;
-			return written;
-		}
-		else if (c == '\r') {
-			recv_discard(rb, '\n');
-			line[written++] = 0;
-			return written;
-		}
-		line[written++] = c;
-	}
-	
-	return ELIMIT;
-}
-
-/** @}
- */
Index: uspace/lib/http/receive-buffer.h
===================================================================
--- uspace/lib/http/receive-buffer.h	(revision 3ce68b7bc50391278f778663dd78d5162fbda5d0)
+++ 	(revision )
@@ -1,89 +1,0 @@
-/*
- * Copyright (c) 2013 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup http
- * @{
- */
-/**
- * @file
- */
-
-#ifndef HTTP_RECEIVE_BUFFER_H_
-#define HTTP_RECEIVE_BUFFER_H_
-
-#include <adt/list.h>
-
-/** Receive data.
- *
- * @param client_data client data
- * @param buf buffer to store the data
- * @param buf_size buffer size
- * @return number of bytes received or negative error code
- */
-typedef ssize_t (*receive_func_t)(void *, void *, size_t);
-
-typedef struct {
-	size_t size;
-	char *buffer;
-	size_t in;
-	size_t out;
-	
-	void *client_data;
-	receive_func_t receive;
-	
-	list_t marks;
-} receive_buffer_t;
-
-typedef struct {
-	link_t link;
-	size_t offset;
-} receive_buffer_mark_t;
-
-extern int recv_buffer_init(receive_buffer_t *, size_t, receive_func_t, void *);
-extern int recv_buffer_init_const(receive_buffer_t *, void *, size_t);
-extern void recv_buffer_fini(receive_buffer_t *);
-extern void recv_reset(receive_buffer_t *);
-extern void recv_mark(receive_buffer_t *, receive_buffer_mark_t *);
-extern void recv_unmark(receive_buffer_t *, receive_buffer_mark_t *);
-extern void recv_mark_update(receive_buffer_t *, receive_buffer_mark_t *);
-extern int recv_cut(receive_buffer_t *, receive_buffer_mark_t *,
-    receive_buffer_mark_t *, void **, size_t *);
-extern int recv_cut_str(receive_buffer_t *, receive_buffer_mark_t *,
-    receive_buffer_mark_t *, char **);
-extern int recv_char(receive_buffer_t *, char *, bool);
-extern ssize_t recv_buffer(receive_buffer_t *, char *, size_t);
-extern ssize_t recv_discard(receive_buffer_t *, char);
-extern ssize_t recv_eol(receive_buffer_t *);
-extern ssize_t recv_line(receive_buffer_t *, char *, size_t);
-
-
-
-#endif
-
-/** @}
- */
Index: uspace/lib/http/request.c
===================================================================
--- uspace/lib/http/request.c	(revision 3ce68b7bc50391278f778663dd78d5162fbda5d0)
+++ 	(revision )
@@ -1,164 +1,0 @@
-/*
- * Copyright (c) 2013 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup http
- * @{
- */
-/**
- * @file
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <str.h>
-#include <macros.h>
-
-#include <net/socket.h>
-
-#include "http.h"
-
-#define HTTP_METHOD_LINE "%s %s HTTP/1.1\r\n"
-#define HTTP_REQUEST_LINE "\r\n"
-
-http_request_t *http_request_create(const char *method, const char *path)
-{
-	http_request_t *req = malloc(sizeof(http_request_t));
-	if (req == NULL)
-		return NULL;
-	
-	req->method = str_dup(method);
-	if (req->method == NULL) {
-		free(req);
-		return NULL;
-	}
-	
-	req->path = str_dup(path);
-	if (req->path == NULL) {
-		free(req->method);
-		free(req);
-		return NULL;
-	}
-	
-	list_initialize(&req->headers);
-	
-	return req;
-}
-
-void http_request_destroy(http_request_t *req)
-{
-	free(req->method);
-	free(req->path);
-	link_t *link = req->headers.head.next;
-	while (link != &req->headers.head) {
-		link_t *next = link->next;
-		http_header_t *header = list_get_instance(link, http_header_t, link);
-		http_header_destroy(header);
-		link = next;
-	}
-	free(req);
-}
-
-static ssize_t http_encode_method(char *buf, size_t buf_size,
-    const char *method, const char *path)
-{
-	if (buf == NULL) {
-		return printf_size(HTTP_METHOD_LINE, method, path);
-	}
-	else {
-		return snprintf(buf, buf_size, HTTP_METHOD_LINE, method, path);
-	}
-}
-
-int http_request_format(http_request_t *req, char **out_buf,
-    size_t *out_buf_size)
-{
-	/* Compute the size of the request */
-	ssize_t meth_size = http_encode_method(NULL, 0, req->method, req->path);
-	if (meth_size < 0)
-		return meth_size;
-	size_t size = meth_size;
-	
-	list_foreach(req->headers, link, http_header_t, header) {
-		ssize_t header_size = http_header_encode(header, NULL, 0);
-		if (header_size < 0)
-			return header_size;
-		size += header_size;
-	}
-	size += str_length(HTTP_REQUEST_LINE);
-	
-	char *buf = malloc(size);
-	if (buf == NULL)
-		return ENOMEM;
-	
-	char *pos = buf;
-	size_t pos_size = size;
-	ssize_t written = http_encode_method(pos, pos_size, req->method, req->path);
-	if (written < 0) {
-		free(buf);
-		return written;
-	}
-	pos += written;
-	pos_size -= written;
-	
-	list_foreach(req->headers, link, http_header_t, header) {
-		written = http_header_encode(header, pos, pos_size);
-		if (written < 0) {
-			free(buf);
-			return written;
-		}
-		pos += written;
-		pos_size -= written;
-	}
-	
-	size_t rlsize = str_size(HTTP_REQUEST_LINE);
-	memcpy(pos, HTTP_REQUEST_LINE, rlsize);
-	pos_size -= rlsize;
-	assert(pos_size == 0);
-	
-	*out_buf = buf;
-	*out_buf_size = size;
-	return EOK;
-}
-
-int http_send_request(http_t *http, http_request_t *req)
-{
-	char *buf;
-	size_t buf_size;
-	
-	int rc = http_request_format(req, &buf, &buf_size);
-	if (rc != EOK)
-		return rc;
-	
-	rc = send(http->conn_sd, buf, buf_size, 0);
-	free(buf);
-	
-	return rc;
-}
-
-/** @}
- */
Index: uspace/lib/http/response.c
===================================================================
--- uspace/lib/http/response.c	(revision 3ce68b7bc50391278f778663dd78d5162fbda5d0)
+++ 	(revision )
@@ -1,170 +1,0 @@
-/*
- * Copyright (c) 2013 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup http
- * @{
- */
-/**
- * @file
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <str.h>
-#include <macros.h>
-
-#include "http.h"
-
-int http_parse_status(const char *line, http_version_t *out_version,
-    uint16_t *out_status, char **out_message)
-{
-	http_version_t version;
-	uint16_t status;
-	char *message = NULL;
-	
-	if (!str_test_prefix(line, "HTTP/"))
-		return EINVAL;
-	
-	const char *pos_version = line + 5;
-	const char *pos = pos_version;
-	
-	int rc = str_uint8_t(pos_version, &pos, 10, false, &version.major);
-	if (rc != EOK)
-		return rc;
-	if (*pos != '.')
-		return EINVAL;
-	pos++;
-	
-	pos_version = pos;
-	rc = str_uint8_t(pos_version, &pos, 10, false, &version.minor);
-	if (rc != EOK)
-		return rc;
-	if (*pos != ' ')
-		return EINVAL;
-	pos++;
-	
-	const char *pos_status = pos;
-	rc = str_uint16_t(pos_status, &pos, 10, false, &status);
-	if (rc != EOK)
-		return rc;
-	if (*pos != ' ')
-		return EINVAL;
-	pos++;
-	
-	if (out_message) {
-		message = str_dup(pos);
-		if (message == NULL)
-			return ENOMEM;
-	}
-	
-	if (out_version)
-		*out_version = version;
-	if (out_status)
-		*out_status = status;
-	if (out_message)
-		*out_message = message;
-	return EOK;
-}
-
-int http_receive_response(http_t *http, http_response_t **out_response)
-{
-	http_response_t *resp = malloc(sizeof(http_response_t));
-	if (resp == NULL)
-		return ENOMEM;
-	memset(resp, 0, sizeof(http_response_t));
-	list_initialize(&resp->headers);
-	
-	char *line = malloc(http->buffer_size);
-	if (line == NULL) {
-		free(resp);
-		return ENOMEM;
-	}
-	
-	int rc = recv_line(&http->recv_buffer, line, http->buffer_size);
-	if (rc < 0)
-		goto error;
-	
-	rc = http_parse_status(line, &resp->version, &resp->status,
-	    &resp->message);
-	if (rc != EOK)
-		goto error;
-	
-	while (true) {
-		rc = recv_eol(&http->recv_buffer);
-		if (rc < 0)
-			goto error;
-		
-		/* Empty line ends header part */
-		if (rc > 0)
-			break;
-		
-		http_header_t *header = malloc(sizeof(http_header_t));
-		if (header == NULL) {
-			rc = ENOMEM;
-			goto error;
-		}
-		http_header_init(header);
-		
-		rc = http_header_receive(&http->recv_buffer, header);
-		if (rc != EOK) {
-			free(header);
-			goto error;
-		}
-		
-		list_append(&header->link, &resp->headers);
-	}
-	
-	*out_response = resp;
-	
-	return EOK;
-error:
-	free(line);
-	http_response_destroy(resp);
-	return rc;
-}
-
-int http_receive_body(http_t *http, void *buf, size_t buf_size)
-{
-	return recv_buffer(&http->recv_buffer, buf, buf_size);
-}
-
-void http_response_destroy(http_response_t *resp)
-{
-	free(resp->message);
-	link_t *link = resp->headers.head.next;
-	while (link != &resp->headers.head) {
-		link_t *next = link->next;
-		http_header_t *header = list_get_instance(link, http_header_t, link);
-		http_header_destroy(header);
-		link = next;
-	}
-	free(resp);
-}
-
-/** @}
- */
Index: uspace/lib/http/src/headers.c
===================================================================
--- uspace/lib/http/src/headers.c	(revision b623b68e159f4973ecd11ab5fb53eca272b74c6d)
+++ uspace/lib/http/src/headers.c	(revision b623b68e159f4973ecd11ab5fb53eca272b74c6d)
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2013 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup http
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <str.h>
+#include <macros.h>
+
+#include <http/http.h>
+#include <http/ctype.h>
+
+#define HTTP_HEADER_LINE "%s: %s\r\n"
+
+void http_header_init(http_header_t *header)
+{
+	link_initialize(&header->link);
+	header->name = NULL;
+	header->value = NULL;
+}
+
+http_header_t *http_header_create(const char *name, const char *value)
+{
+	http_header_t *header = malloc(sizeof(http_header_t));
+	if (header == NULL)
+		return NULL;
+	http_header_init(header);
+
+	header->name = str_dup(name);
+	if (header->name == NULL) {
+		free(header);
+		return NULL;
+	}
+	
+	header->value = str_dup(value);
+	if (header->value == NULL) {
+		free(header->name);
+		free(header);
+		return NULL;
+	}
+
+	return header;
+}
+
+void http_header_destroy(http_header_t *header)
+{
+	free(header->name);
+	free(header->value);
+	free(header);
+}
+
+ssize_t http_header_encode(http_header_t *header, char *buf, size_t buf_size)
+{
+	/* TODO properly split long header values */
+	if (buf == NULL) {
+		return printf_size(HTTP_HEADER_LINE, header->name, header->value);
+	}
+	else {
+		return snprintf(buf, buf_size,
+		    HTTP_HEADER_LINE, header->name, header->value);
+	}
+}
+
+int http_header_receive_name(receive_buffer_t *rb, char **out_name)
+{
+	receive_buffer_mark_t name_start;
+	receive_buffer_mark_t name_end;
+	
+	recv_mark(rb, &name_start);
+	recv_mark(rb, &name_end);
+	
+	char c = 0;
+	do {
+		recv_mark_update(rb, &name_end);
+		
+		int rc = recv_char(rb, &c, true);
+		if (rc != EOK) {
+			recv_unmark(rb, &name_start);
+			recv_unmark(rb, &name_end);
+			return rc;
+		}
+	} while (is_token(c));
+	
+	if (c != ':') {
+		recv_unmark(rb, &name_start);
+		recv_unmark(rb, &name_end);
+		return EINVAL;
+	}
+	
+	char *name = NULL;
+	int rc = recv_cut_str(rb, &name_start, &name_end, &name);
+	recv_unmark(rb, &name_start);
+	recv_unmark(rb, &name_end);
+	if (rc != EOK)
+		return rc;
+	
+	*out_name = name;
+	return EOK;
+}
+
+int http_header_receive_value(receive_buffer_t *rb, char **out_value)
+{
+	int rc = EOK;
+	char c = 0;
+	
+	receive_buffer_mark_t value_start;
+	recv_mark(rb, &value_start);
+	
+	/* Ignore any inline LWS */
+	while (true) {
+		recv_mark_update(rb, &value_start);
+		rc = recv_char(rb, &c, false);
+		if (rc != EOK)
+			goto error;
+		
+		if (c != ' ' && c != '\t')
+			break;
+		
+		rc = recv_char(rb, &c, true);
+		if (rc != EOK)
+			goto error;
+	}
+	
+	receive_buffer_mark_t value_end;
+	recv_mark(rb, &value_end);
+	
+	while (true) {
+		recv_mark_update(rb, &value_end);
+		
+		rc = recv_char(rb, &c, true);
+		if (rc != EOK)
+			goto error_end;
+		
+		if (c != '\r' && c != '\n')
+			continue;
+		
+		rc = recv_discard(rb, (c == '\r' ? '\n' : '\r'));
+		if (rc < 0)
+			goto error_end;
+		
+		rc = recv_char(rb, &c, false);
+		if (rc != EOK)
+			goto error_end;
+		
+		if (c != ' ' && c != '\t')
+			break;
+		
+		/* Ignore the char */
+		rc = recv_char(rb, &c, true);
+		if (rc != EOK)
+			goto error_end;
+	}
+	
+	char *value = NULL;
+	rc = recv_cut_str(rb, &value_start, &value_end, &value);
+	recv_unmark(rb, &value_start);
+	recv_unmark(rb, &value_end);
+	if (rc != EOK)
+		return rc;
+	
+	*out_value = value;
+	return EOK;
+error_end:
+	recv_unmark(rb, &value_end);
+error:
+	recv_unmark(rb, &value_start);
+	return rc;
+}
+
+int http_header_receive(receive_buffer_t *rb, http_header_t *header)
+{
+	char *name = NULL;
+	int rc = http_header_receive_name(rb, &name);
+	if (rc != EOK) {
+		printf("Failed receiving header name\n");
+		return rc;
+	}
+	
+	char *value = NULL;
+	rc = http_header_receive_value(rb, &value);
+	if (rc != EOK) {
+		free(name);
+		return rc;
+	}
+	
+	header->name = name;
+	header->value = value;
+	return EOK;
+}
+
+/** Normalize HTTP header value
+ *
+ * @see RFC2616 section 4.2
+ */
+void http_header_normalize_value(char *value)
+{
+	size_t read_index = 0;
+	size_t write_index = 0;
+	
+	while (is_lws(value[read_index])) read_index++;
+	
+	while (value[read_index] != 0) {
+		if (is_lws(value[read_index])) {
+			while (is_lws(value[read_index])) read_index++;
+			
+			if (value[read_index] != 0)
+				value[write_index++] = ' ';
+			
+			continue;
+		}
+		
+		value[write_index++] = value[read_index++];
+	}
+	
+	value[write_index] = 0;
+}
+
+/** @}
+ */
Index: uspace/lib/http/src/http.c
===================================================================
--- uspace/lib/http/src/http.c	(revision b623b68e159f4973ecd11ab5fb53eca272b74c6d)
+++ uspace/lib/http/src/http.c	(revision b623b68e159f4973ecd11ab5fb53eca272b74c6d)
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2013 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup http
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <str.h>
+#include <macros.h>
+
+#include <net/socket.h>
+#include <inet/dnsr.h>
+
+#include <http/http.h>
+#include <http/receive-buffer.h>
+
+static ssize_t http_receive(void *client_data, void *buf, size_t buf_size)
+{
+	http_t *http = client_data;
+	return recv(http->conn_sd, buf, buf_size, 0);
+}
+
+http_t *http_create(const char *host, uint16_t port)
+{
+	http_t *http = malloc(sizeof(http_t));
+	if (http == NULL)
+		return NULL;
+	
+	http->host = str_dup(host);
+	if (http->host == NULL) {
+		free(http);
+		return NULL;
+	}
+	http->port = port;
+	
+	http->buffer_size = 4096;
+	int rc = recv_buffer_init(&http->recv_buffer, http->buffer_size,
+	    http_receive, http);
+	if (rc != EOK) {
+		free(http);
+		return NULL;
+	}
+	
+	return http;
+}
+
+int http_connect(http_t *http)
+{
+	if (http->connected)
+		return EBUSY;
+	
+	/* Interpret as address */
+	int rc = inet_addr_parse(http->host, &http->addr);
+	
+	if (rc != EOK) {
+		/* Interpret as a host name */
+		dnsr_hostinfo_t *hinfo = NULL;
+		rc = dnsr_name2host(http->host, &hinfo, AF_NONE);
+		
+		if (rc != EOK)
+			return rc;
+		
+		http->addr = hinfo->addr;
+		dnsr_hostinfo_destroy(hinfo);
+	}
+	
+	struct sockaddr_in addr;
+	struct sockaddr_in6 addr6;
+	uint16_t af = inet_addr_sockaddr_in(&http->addr, &addr, &addr6);
+	
+	http->conn_sd = socket(PF_INET, SOCK_STREAM, 0);
+	if (http->conn_sd < 0)
+		return http->conn_sd;
+	
+	switch (af) {
+	case AF_INET:
+		addr.sin_port = htons(http->port);
+		rc = connect(http->conn_sd, (struct sockaddr *) &addr, sizeof(addr));
+		break;
+	case AF_INET6:
+		addr6.sin6_port = htons(http->port);
+		rc = connect(http->conn_sd, (struct sockaddr *) &addr6, sizeof(addr6));
+		break;
+	default:
+		return ENOTSUP;
+	}
+	
+	return rc;
+}
+
+int http_close(http_t *http)
+{
+	if (!http->connected)
+		return EINVAL;
+	
+	return closesocket(http->conn_sd);
+}
+
+void http_destroy(http_t *http)
+{
+	recv_buffer_fini(&http->recv_buffer);
+	free(http);
+}
+
+/** @}
+ */
Index: uspace/lib/http/src/receive-buffer.c
===================================================================
--- uspace/lib/http/src/receive-buffer.c	(revision b623b68e159f4973ecd11ab5fb53eca272b74c6d)
+++ uspace/lib/http/src/receive-buffer.c	(revision b623b68e159f4973ecd11ab5fb53eca272b74c6d)
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2013 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup http
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <stdlib.h>
+#include <str.h>
+#include <errno.h>
+#include <macros.h>
+#include <adt/list.h>
+
+#include <http/receive-buffer.h>
+
+int recv_buffer_init(receive_buffer_t *rb, size_t buffer_size,
+    receive_func_t receive, void *client_data)
+{
+	rb->receive = receive;
+	rb->client_data = client_data;
+	
+	rb->in = 0;
+	rb->out = 0;
+	rb->size = buffer_size;
+	
+	list_initialize(&rb->marks);
+	
+	rb->buffer = malloc(buffer_size);
+	if (rb->buffer == NULL)
+		return ENOMEM;
+	return EOK;
+}
+
+static ssize_t dummy_receive(void *unused, void *buf, size_t buf_size)
+{
+	return 0;
+}
+
+int recv_buffer_init_const(receive_buffer_t *rb, void *buf, size_t size)
+{
+	int rc = recv_buffer_init(rb, size, dummy_receive, NULL);
+	if (rc != EOK)
+		return rc;
+	
+	memcpy(rb->buffer, buf, size);
+	rb->in = size;
+	return EOK;
+}
+
+void recv_buffer_fini(receive_buffer_t *rb)
+{
+	free(rb->buffer);
+}
+
+void recv_reset(receive_buffer_t *rb)
+{
+	rb->in = 0;
+	rb->out = 0;
+}
+
+void recv_mark(receive_buffer_t *rb, receive_buffer_mark_t *mark)
+{
+	link_initialize(&mark->link);
+	list_append(&mark->link, &rb->marks);
+	recv_mark_update(rb, mark);
+}
+
+void recv_unmark(receive_buffer_t *rb, receive_buffer_mark_t *mark)
+{
+	list_remove(&mark->link);
+}
+
+void recv_mark_update(receive_buffer_t *rb, receive_buffer_mark_t *mark)
+{
+	mark->offset = rb->out;
+}
+
+int recv_cut(receive_buffer_t *rb, receive_buffer_mark_t *a, receive_buffer_mark_t *b, void **out_buf, size_t *out_size)
+{
+	if (a->offset > b->offset)
+		return EINVAL;
+	
+	size_t size = b->offset - a->offset;
+	void *buf = malloc(size);
+	if (buf == NULL)
+		return ENOMEM;
+	
+	memcpy(buf, rb->buffer + a->offset, size);
+	*out_buf = buf;
+	*out_size = size;
+	return EOK;
+}
+
+int recv_cut_str(receive_buffer_t *rb, receive_buffer_mark_t *a, receive_buffer_mark_t *b, char **out_buf)
+{
+	if (a->offset > b->offset)
+		return EINVAL;
+	
+	size_t size = b->offset - a->offset;
+	char *buf = malloc(size + 1);
+	if (buf == NULL)
+		return ENOMEM;
+	
+	memcpy(buf, rb->buffer + a->offset, size);
+	buf[size] = 0;
+	for (size_t i = 0; i < size; i++) {
+		if (buf[i] == 0) {
+			free(buf);
+			return EIO;
+		}
+	}
+	*out_buf = buf;
+	return EOK;
+}
+
+
+/** Receive one character (with buffering) */
+int recv_char(receive_buffer_t *rb, char *c, bool consume)
+{
+	if (rb->out == rb->in) {
+		size_t free = rb->size - rb->in;
+		if (free == 0) {
+			size_t min_mark = rb->size;
+			list_foreach(rb->marks, link, receive_buffer_mark_t, mark) {
+				min_mark = min(min_mark, mark->offset);
+			}
+			
+			if (min_mark == 0)
+				return ELIMIT;
+			
+			size_t new_in = rb->in - min_mark;
+			memmove(rb->buffer, rb->buffer + min_mark, new_in);
+			rb->out = rb->in = new_in;
+			free = rb->size - rb->in;
+			list_foreach(rb->marks, link, receive_buffer_mark_t, mark) {
+				mark->offset -= min_mark;
+			}
+		}
+		
+		ssize_t rc = rb->receive(rb->client_data, rb->buffer + rb->in, free);
+		if (rc <= 0)
+			return rc;
+		
+		rb->in = rc;
+	}
+	
+	*c = rb->buffer[rb->out];
+	if (consume)
+		rb->out++;
+	return EOK;
+}
+
+ssize_t recv_buffer(receive_buffer_t *rb, char *buf, size_t buf_size)
+{
+	/* Flush any buffered data*/
+	if (rb->out != rb->in) {
+		size_t size = min(rb->in - rb->out, buf_size);
+		memcpy(buf, rb->buffer + rb->out, size);
+		rb->out += size;
+		return size;
+	}
+	
+	return rb->receive(rb->client_data, buf, buf_size);
+}
+
+/** Receive a character and if it is c, discard it from input buffer
+ * @return number of characters discarded (0 or 1) or negative error code
+ */
+ssize_t recv_discard(receive_buffer_t *rb, char discard)
+{
+	char c = 0;
+	int rc = recv_char(rb, &c, false);
+	if (rc != EOK)
+		return rc;
+	if (c != discard)
+		return 0;
+	rc = recv_char(rb, &c, true);
+	if (rc != EOK)
+		return rc;
+	return 1;
+}
+
+/** Receive an end of line, either CR, LF, CRLF or LFCR
+ *
+ * @return number of bytes read (0 if no newline is present in the stream)
+ *         or negative error code
+ */
+ssize_t recv_eol(receive_buffer_t *rb)
+{
+	char c = 0;
+	int rc = recv_char(rb, &c, false);
+	if (rc != EOK)
+		return rc;
+	
+	if (c != '\r' && c != '\n')
+		return 0;
+	
+	rc = recv_char(rb, &c, true);
+	if (rc != EOK)
+		return rc;
+	
+	ssize_t rc2 = recv_discard(rb, (c == '\r' ? '\n' : '\r'));
+	if (rc2 < 0)
+		return rc2;
+	
+	return 1 + rc2;
+}
+
+/* Receive a single line */
+ssize_t recv_line(receive_buffer_t *rb, char *line, size_t size)
+{
+	size_t written = 0;
+	
+	while (written < size) {
+		char c = 0;
+		int rc = recv_char(rb, &c, true);
+		if (rc != EOK)
+			return rc;
+		if (c == '\n') {
+			recv_discard(rb, '\r');
+			line[written++] = 0;
+			return written;
+		}
+		else if (c == '\r') {
+			recv_discard(rb, '\n');
+			line[written++] = 0;
+			return written;
+		}
+		line[written++] = c;
+	}
+	
+	return ELIMIT;
+}
+
+/** @}
+ */
Index: uspace/lib/http/src/request.c
===================================================================
--- uspace/lib/http/src/request.c	(revision b623b68e159f4973ecd11ab5fb53eca272b74c6d)
+++ uspace/lib/http/src/request.c	(revision b623b68e159f4973ecd11ab5fb53eca272b74c6d)
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2013 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup http
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <str.h>
+#include <macros.h>
+
+#include <net/socket.h>
+
+#include <http/http.h>
+
+#define HTTP_METHOD_LINE "%s %s HTTP/1.1\r\n"
+#define HTTP_REQUEST_LINE "\r\n"
+
+http_request_t *http_request_create(const char *method, const char *path)
+{
+	http_request_t *req = malloc(sizeof(http_request_t));
+	if (req == NULL)
+		return NULL;
+	
+	req->method = str_dup(method);
+	if (req->method == NULL) {
+		free(req);
+		return NULL;
+	}
+	
+	req->path = str_dup(path);
+	if (req->path == NULL) {
+		free(req->method);
+		free(req);
+		return NULL;
+	}
+	
+	list_initialize(&req->headers);
+	
+	return req;
+}
+
+void http_request_destroy(http_request_t *req)
+{
+	free(req->method);
+	free(req->path);
+	link_t *link = req->headers.head.next;
+	while (link != &req->headers.head) {
+		link_t *next = link->next;
+		http_header_t *header = list_get_instance(link, http_header_t, link);
+		http_header_destroy(header);
+		link = next;
+	}
+	free(req);
+}
+
+static ssize_t http_encode_method(char *buf, size_t buf_size,
+    const char *method, const char *path)
+{
+	if (buf == NULL) {
+		return printf_size(HTTP_METHOD_LINE, method, path);
+	}
+	else {
+		return snprintf(buf, buf_size, HTTP_METHOD_LINE, method, path);
+	}
+}
+
+int http_request_format(http_request_t *req, char **out_buf,
+    size_t *out_buf_size)
+{
+	/* Compute the size of the request */
+	ssize_t meth_size = http_encode_method(NULL, 0, req->method, req->path);
+	if (meth_size < 0)
+		return meth_size;
+	size_t size = meth_size;
+	
+	list_foreach(req->headers, link, http_header_t, header) {
+		ssize_t header_size = http_header_encode(header, NULL, 0);
+		if (header_size < 0)
+			return header_size;
+		size += header_size;
+	}
+	size += str_length(HTTP_REQUEST_LINE);
+	
+	char *buf = malloc(size);
+	if (buf == NULL)
+		return ENOMEM;
+	
+	char *pos = buf;
+	size_t pos_size = size;
+	ssize_t written = http_encode_method(pos, pos_size, req->method, req->path);
+	if (written < 0) {
+		free(buf);
+		return written;
+	}
+	pos += written;
+	pos_size -= written;
+	
+	list_foreach(req->headers, link, http_header_t, header) {
+		written = http_header_encode(header, pos, pos_size);
+		if (written < 0) {
+			free(buf);
+			return written;
+		}
+		pos += written;
+		pos_size -= written;
+	}
+	
+	size_t rlsize = str_size(HTTP_REQUEST_LINE);
+	memcpy(pos, HTTP_REQUEST_LINE, rlsize);
+	pos_size -= rlsize;
+	assert(pos_size == 0);
+	
+	*out_buf = buf;
+	*out_buf_size = size;
+	return EOK;
+}
+
+int http_send_request(http_t *http, http_request_t *req)
+{
+	char *buf;
+	size_t buf_size;
+	
+	int rc = http_request_format(req, &buf, &buf_size);
+	if (rc != EOK)
+		return rc;
+	
+	rc = send(http->conn_sd, buf, buf_size, 0);
+	free(buf);
+	
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/http/src/response.c
===================================================================
--- uspace/lib/http/src/response.c	(revision b623b68e159f4973ecd11ab5fb53eca272b74c6d)
+++ uspace/lib/http/src/response.c	(revision b623b68e159f4973ecd11ab5fb53eca272b74c6d)
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2013 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup http
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <str.h>
+#include <macros.h>
+
+#include <http/http.h>
+
+int http_parse_status(const char *line, http_version_t *out_version,
+    uint16_t *out_status, char **out_message)
+{
+	http_version_t version;
+	uint16_t status;
+	char *message = NULL;
+	
+	if (!str_test_prefix(line, "HTTP/"))
+		return EINVAL;
+	
+	const char *pos_version = line + 5;
+	const char *pos = pos_version;
+	
+	int rc = str_uint8_t(pos_version, &pos, 10, false, &version.major);
+	if (rc != EOK)
+		return rc;
+	if (*pos != '.')
+		return EINVAL;
+	pos++;
+	
+	pos_version = pos;
+	rc = str_uint8_t(pos_version, &pos, 10, false, &version.minor);
+	if (rc != EOK)
+		return rc;
+	if (*pos != ' ')
+		return EINVAL;
+	pos++;
+	
+	const char *pos_status = pos;
+	rc = str_uint16_t(pos_status, &pos, 10, false, &status);
+	if (rc != EOK)
+		return rc;
+	if (*pos != ' ')
+		return EINVAL;
+	pos++;
+	
+	if (out_message) {
+		message = str_dup(pos);
+		if (message == NULL)
+			return ENOMEM;
+	}
+	
+	if (out_version)
+		*out_version = version;
+	if (out_status)
+		*out_status = status;
+	if (out_message)
+		*out_message = message;
+	return EOK;
+}
+
+int http_receive_response(http_t *http, http_response_t **out_response)
+{
+	http_response_t *resp = malloc(sizeof(http_response_t));
+	if (resp == NULL)
+		return ENOMEM;
+	memset(resp, 0, sizeof(http_response_t));
+	list_initialize(&resp->headers);
+	
+	char *line = malloc(http->buffer_size);
+	if (line == NULL) {
+		free(resp);
+		return ENOMEM;
+	}
+	
+	int rc = recv_line(&http->recv_buffer, line, http->buffer_size);
+	if (rc < 0)
+		goto error;
+	
+	rc = http_parse_status(line, &resp->version, &resp->status,
+	    &resp->message);
+	if (rc != EOK)
+		goto error;
+	
+	while (true) {
+		rc = recv_eol(&http->recv_buffer);
+		if (rc < 0)
+			goto error;
+		
+		/* Empty line ends header part */
+		if (rc > 0)
+			break;
+		
+		http_header_t *header = malloc(sizeof(http_header_t));
+		if (header == NULL) {
+			rc = ENOMEM;
+			goto error;
+		}
+		http_header_init(header);
+		
+		rc = http_header_receive(&http->recv_buffer, header);
+		if (rc != EOK) {
+			free(header);
+			goto error;
+		}
+		
+		list_append(&header->link, &resp->headers);
+	}
+	
+	*out_response = resp;
+	
+	return EOK;
+error:
+	free(line);
+	http_response_destroy(resp);
+	return rc;
+}
+
+int http_receive_body(http_t *http, void *buf, size_t buf_size)
+{
+	return recv_buffer(&http->recv_buffer, buf, buf_size);
+}
+
+void http_response_destroy(http_response_t *resp)
+{
+	free(resp->message);
+	link_t *link = resp->headers.head.next;
+	while (link != &resp->headers.head) {
+		link_t *next = link->next;
+		http_header_t *header = list_get_instance(link, http_header_t, link);
+		http_header_destroy(header);
+		link = next;
+	}
+	free(resp);
+}
+
+/** @}
+ */
