Free (GPLv2) TCP/IP stack developed by TASS Belgium

Dependents:   lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

Different licensing models may exist, at the sole discretion of the Copyright holders.

Official homepage: http://www.picotcp.com

Bug tracker: https://github.com/tass-belgium/picotcp/issues

Development steps:

  • initial integration with mbed RTOS
  • generic mbed Ethernet driver
  • high performance NXP LPC1768 specific Ethernet driver
  • Multi-threading support for mbed RTOS
  • Berkeley sockets and integration with the New Socket API
  • Fork of the apps running on top of the New Socket API
  • Scheduling optimizations
  • Debugging/benchmarking/testing

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

A PicoTCP demo app testing the ethernet throughput on the lpc1768 mbed board.

Revision:
51:ab4529a384a6
Parent:
3:b4047e8a0123
Child:
63:97f481e33cb2
--- a/modules/pico_http_server.c	Tue Aug 06 08:04:03 2013 +0000
+++ b/modules/pico_http_server.c	Mon Sep 02 08:02:21 2013 +0000
@@ -13,30 +13,30 @@
 
 #ifdef PICO_SUPPORT_HTTP_SERVER
 
-#define BACKLOG                              10
+#define BACKLOG 						 	10
 
-#define HTTP_SERVER_CLOSED         0
-#define HTTP_SERVER_LISTEN         1
+#define HTTP_SERVER_CLOSED	 	0
+#define HTTP_SERVER_LISTEN	 	1
 
-#define HTTP_HEADER_MAX_LINE     256u
+#define HTTP_HEADER_MAX_LINE 	256u
 
 #define consumeChar(c) (pico_socket_read(client->sck,&c,1u))
 
-static char returnOkHeader[] =
+static const char returnOkHeader[] =
 "HTTP/1.1 200 OK\r\n\
 Host: localhost\r\n\
 Transfer-Encoding: chunked\r\n\
 Connection: close\r\n\
 \r\n";
 
-static char returnFailHeader[] =
+static const char returnFailHeader[] =
 "HTTP/1.1 404 Not Found\r\n\
 Host: localhost\r\n\
 Connection: close\r\n\
 \r\n\
 <html><body>The resource you requested cannot be found !</body></html>";
 
-static char errorHeader[] =
+static const char errorHeader[] =
 "HTTP/1.1 400 Bad Request\r\n\
 Host: localhost\r\n\
 Connection: close\r\n\
@@ -45,35 +45,35 @@
 
 struct httpServer
 {
-    uint16_t state;
-    struct pico_socket * sck;
-    uint16_t port;
-    void (*wakeup)(uint16_t ev, uint16_t param);
-    uint8_t accepted;
+	uint16_t state;
+	struct pico_socket * sck;
+	uint16_t port;
+	void (*wakeup)(uint16_t ev, uint16_t param);
+	uint8_t accepted;
 };
 
 struct httpClient
 {
-    uint16_t connectionID;
-    struct pico_socket * sck;
-    void * buffer;
-    uint16_t bufferSize;
-    uint16_t bufferSent;
-    char * resource;
-    uint16_t state;
+	uint16_t connectionID;
+	struct pico_socket * sck;
+	void * buffer;
+	uint16_t bufferSize;
+	uint16_t bufferSent;
+	char * resource;
+	uint16_t state;
 };
 
 /* Local states for clients */
-#define HTTP_WAIT_HDR                0
-#define HTTP_WAIT_EOF_HDR        1
-#define HTTP_EOF_HDR                2
+#define HTTP_WAIT_HDR				0
+#define HTTP_WAIT_EOF_HDR		1
+#define HTTP_EOF_HDR				2
 #define HTTP_WAIT_RESPONSE  3
-#define HTTP_WAIT_DATA            4
-#define HTTP_SENDING_DATA        5
-#define HTTP_ERROR                    6
-#define HTTP_CLOSED                    7
+#define HTTP_WAIT_DATA			4
+#define HTTP_SENDING_DATA		5
+#define HTTP_ERROR					6
+#define HTTP_CLOSED					7
 
-static struct httpServer server = {};
+static struct httpServer server = {0};
 
 /*
  * Private functions
@@ -86,76 +86,76 @@
 
 static int compareClients(void * ka, void * kb)
 {
-    return ((struct httpClient *)ka)->connectionID - ((struct httpClient *)kb)->connectionID;
+	return ((struct httpClient *)ka)->connectionID - ((struct httpClient *)kb)->connectionID;
 }
 
 PICO_TREE_DECLARE(pico_http_clients,compareClients);
 
 void httpServerCbk(uint16_t ev, struct pico_socket *s)
 {
-    struct pico_tree_node * index;
-    struct httpClient * client = NULL;
+	struct pico_tree_node * index;
+	struct httpClient * client = NULL;
   uint8_t serverEvent = FALSE;
 
   // determine the client for the socket
   if( s == server.sck)
   {
-        serverEvent = TRUE;
+		serverEvent = TRUE;
   }
   else
   {
-        pico_tree_foreach(index,&pico_http_clients)
-        {
-            client = index->keyValue;
-            if(client->sck == s) break;
-            client = NULL;
-        }
+		pico_tree_foreach(index,&pico_http_clients)
+		{
+			client = index->keyValue;
+			if(client->sck == s) break;
+			client = NULL;
+		}
   }
 
-    if(!client && !serverEvent)
-    {
-        return;
-    }
+	if(!client && !serverEvent)
+	{
+		return;
+	}
 
-    if (ev & PICO_SOCK_EV_RD)
-    {
+	if (ev & PICO_SOCK_EV_RD)
+	{
 
-        if(readData(client) == HTTP_RETURN_ERROR)
-        {
-            // send out error
-            client->state = HTTP_ERROR;
-            pico_socket_write(client->sck,errorHeader,sizeof(errorHeader)-1);
-            server.wakeup(EV_HTTP_ERROR,client->connectionID);
-        }
-    }
+		if(readData(client) == HTTP_RETURN_ERROR)
+		{
+			// send out error
+			client->state = HTTP_ERROR;
+			pico_socket_write(client->sck,(char *)errorHeader,sizeof(errorHeader)-1);
+			server.wakeup(EV_HTTP_ERROR,client->connectionID);
+		}
+	}
 
-    if(ev & PICO_SOCK_EV_WR)
-    {
-        if(client->state == HTTP_SENDING_DATA)
-        {
-            sendData(client);
-        }
-    }
+	if(ev & PICO_SOCK_EV_WR)
+	{
+		if(client->state == HTTP_SENDING_DATA)
+		{
+			sendData(client);
+		}
+	}
 
-    if(ev & PICO_SOCK_EV_CONN)
-    {
-        server.accepted = FALSE;
-        server.wakeup(EV_HTTP_CON,HTTP_SERVER_ID);
-        if(!server.accepted)
-        {
-            pico_socket_close(s); // reject socket
-        }
-    }
+	if(ev & PICO_SOCK_EV_CONN)
+	{
+		server.accepted = FALSE;
+		server.wakeup(EV_HTTP_CON,HTTP_SERVER_ID);
+		if(!server.accepted)
+		{
+			pico_socket_close(s); // reject socket
+		}
+	}
 
-    if( (ev & PICO_SOCK_EV_CLOSE) || (ev & PICO_SOCK_EV_FIN) )
-    {
-        server.wakeup(EV_HTTP_CLOSE,(serverEvent ? HTTP_SERVER_ID : client->connectionID));
-    }
+	if( (ev & PICO_SOCK_EV_CLOSE) || (ev & PICO_SOCK_EV_FIN) )
+	{
+		server.wakeup(EV_HTTP_CLOSE,(serverEvent ? HTTP_SERVER_ID : client->connectionID));
+	}
 
-    if(ev & PICO_SOCK_EV_ERR)
-    {
-        server.wakeup(EV_HTTP_ERROR,(serverEvent ? HTTP_SERVER_ID : client->connectionID));
-    }
+	if(ev & PICO_SOCK_EV_ERR)
+	{
+		server.wakeup(EV_HTTP_ERROR,(serverEvent ? HTTP_SERVER_ID : client->connectionID));
+	}
 }
 
 /*
@@ -164,38 +164,38 @@
  */
 int pico_http_server_start(uint16_t port, void (*wakeup)(uint16_t ev, uint16_t conn))
 {
-    struct pico_ip4 anything = {};
+	struct pico_ip4 anything = {0};
 
-    server.port = port ? short_be(port) : short_be(80u);
+	server.port = port ? short_be(port) : short_be(80u);
 
-    if(!wakeup)
-    {
-        pico_err = PICO_ERR_EINVAL;
-        return HTTP_RETURN_ERROR;
-    }
+	if(!wakeup)
+	{
+		pico_err = PICO_ERR_EINVAL;
+		return HTTP_RETURN_ERROR;
+	}
 
-    server.sck = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &httpServerCbk);
+	server.sck = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &httpServerCbk);
 
-    if(!server.sck)
-    {
-        pico_err = PICO_ERR_EFAULT;
-        return HTTP_RETURN_ERROR;
-    }
+	if(!server.sck)
+	{
+		pico_err = PICO_ERR_EFAULT;
+		return HTTP_RETURN_ERROR;
+	}
 
-    if(pico_socket_bind(server.sck , &anything, &server.port)!=0)
-    {
-        pico_err = PICO_ERR_EADDRNOTAVAIL;
-        return HTTP_RETURN_ERROR;
-    }
+	if(pico_socket_bind(server.sck , &anything, &server.port)!=0)
+	{
+		pico_err = PICO_ERR_EADDRNOTAVAIL;
+		return HTTP_RETURN_ERROR;
+	}
 
-    if (pico_socket_listen(server.sck, BACKLOG) != 0)
-    {
-        pico_err = PICO_ERR_EADDRINUSE;
-        return HTTP_RETURN_ERROR;
-    }
-    server.wakeup = wakeup;
-    server.state = HTTP_SERVER_LISTEN;
-    return HTTP_RETURN_OK;
+	if (pico_socket_listen(server.sck, BACKLOG) != 0)
+	{
+		pico_err = PICO_ERR_EADDRINUSE;
+		return HTTP_RETURN_ERROR;
+	}
+	server.wakeup = wakeup;
+	server.state = HTTP_SERVER_LISTEN;
+	return HTTP_RETURN_OK;
 }
 
 /*
@@ -215,32 +215,32 @@
   client = pico_zalloc(sizeof(struct httpClient));
   if(!client)
   {
-        pico_err = PICO_ERR_ENOMEM;
-      return HTTP_RETURN_ERROR;
+		pico_err = PICO_ERR_ENOMEM;
+  	return HTTP_RETURN_ERROR;
   }
 
-    client->sck = pico_socket_accept(server.sck,&orig,&port);
+	client->sck = pico_socket_accept(server.sck,&orig,&port);
 
-    if(!client->sck)
-    {
-        pico_err = PICO_ERR_ENOMEM;
-        pico_free(client);
-        return HTTP_RETURN_ERROR;
-    }
+	if(!client->sck)
+	{
+		pico_err = PICO_ERR_ENOMEM;
+		pico_free(client);
+		return HTTP_RETURN_ERROR;
+	}
 
-    server.accepted = TRUE;
-    // buffer used for async sending
-    client->state = HTTP_WAIT_HDR;
-    client->buffer = NULL;
-    client->bufferSize = 0;
-    client->connectionID = pico_rand() & 0x7FFF;
+	server.accepted = TRUE;
+	// buffer used for async sending
+	client->state = HTTP_WAIT_HDR;
+	client->buffer = NULL;
+	client->bufferSize = 0;
+	client->connectionID = pico_rand() & 0x7FFF;
 
-    //add element to the tree, if duplicate because the rand
-    //regenerate
-    while(pico_tree_insert(&pico_http_clients,client)!=NULL)
-        client->connectionID = pico_rand() & 0x7FFF;
+	//add element to the tree, if duplicate because the rand
+	//regenerate
+	while(pico_tree_insert(&pico_http_clients,client)!=NULL)
+		client->connectionID = pico_rand() & 0x7FFF;
 
-    return client->connectionID;
+	return client->connectionID;
 }
 
 /*
@@ -250,12 +250,12 @@
  */
 char * pico_http_getResource(uint16_t conn)
 {
-    struct httpClient * client = findClient(conn);
+	struct httpClient * client = findClient(conn);
 
-    if(!client)
-        return NULL;
-    else
-        return client->resource;
+	if(!client)
+		return NULL;
+	else
+		return client->resource;
 }
 
 /*
@@ -275,37 +275,37 @@
  */
 int pico_http_respond(uint16_t conn, uint16_t code)
 {
-    struct httpClient * client = findClient(conn);
+	struct httpClient * client = findClient(conn);
 
-    if(!client)
-    {
-        dbg("Client not found !\n");
-        return HTTP_RETURN_ERROR;
-    }
+	if(!client)
+	{
+		dbg("Client not found !\n");
+		return HTTP_RETURN_ERROR;
+	}
 
-    if(client->state == HTTP_WAIT_RESPONSE)
-    {
-        if(code == HTTP_RESOURCE_FOUND)
-        {
-            client->state = HTTP_WAIT_DATA;
-            return pico_socket_write(client->sck,returnOkHeader,sizeof(returnOkHeader)-1);//remove \0
-        }
-        else
-        {
-            int length;
+	if(client->state == HTTP_WAIT_RESPONSE)
+	{
+		if(code == HTTP_RESOURCE_FOUND)
+		{
+			client->state = HTTP_WAIT_DATA;
+			return pico_socket_write(client->sck,(char *)returnOkHeader,sizeof(returnOkHeader)-1);//remove \0
+		}
+		else
+		{
+			int length;
 
-            length = pico_socket_write(client->sck,returnFailHeader,sizeof(returnFailHeader)-1);//remove \0
-            pico_socket_close(client->sck);
-            client->state = HTTP_CLOSED;
-            return length;
+			length = pico_socket_write(client->sck,(char *)returnFailHeader,sizeof(returnFailHeader)-1);//remove \0
+			pico_socket_close(client->sck);
+			client->state = HTTP_CLOSED;
+			return length;
 
-        }
-    }
-    else
-    {
-        dbg("Bad state for the client \n");
-        return HTTP_RETURN_ERROR;
-    }
+		}
+	}
+	else
+	{
+		dbg("Bad state for the client \n");
+		return HTTP_RETURN_ERROR;
+	}
 
 }
 
@@ -326,71 +326,71 @@
 int pico_http_submitData(uint16_t conn, void * buffer, int len)
 {
 
-    struct httpClient * client = findClient(conn);
-    char chunkStr[10];
-    int chunkCount;
+	struct httpClient * client = findClient(conn);
+	char chunkStr[10];
+	int chunkCount;
 
-    if(client->state != HTTP_WAIT_DATA)
-    {
-        dbg("Client is in a different state than accepted\n");
-        return HTTP_RETURN_ERROR;
-    }
+	if(client->state != HTTP_WAIT_DATA)
+	{
+		dbg("Client is in a different state than accepted\n");
+		return HTTP_RETURN_ERROR;
+	}
 
-    if(client->buffer)
-    {
-        dbg("Already a buffer submited\n");
-        return HTTP_RETURN_ERROR;
-    }
+	if(client->buffer)
+	{
+		dbg("Already a buffer submited\n");
+		return HTTP_RETURN_ERROR;
+	}
 
-    if(!client)
-    {
-        dbg("Wrong connection ID\n");
-        return HTTP_RETURN_ERROR;
-    }
+	if(!client)
+	{
+		dbg("Wrong connection ID\n");
+		return HTTP_RETURN_ERROR;
+	}
 
-    if(!buffer)
-    {
-        len = 0;
-    }
+	if(!buffer)
+	{
+		len = 0;
+	}
 
-    if(len > 0)
-    {
-        client->buffer = pico_zalloc(len);
-        if(!client->buffer)
-        {
-            pico_err = PICO_ERR_ENOMEM;
-            return HTTP_RETURN_ERROR;
-        }
-        // taking over the buffer
-        memcpy(client->buffer,buffer,len);
-    }
-    else
-        client->buffer = NULL;
+	if(len > 0)
+	{
+		client->buffer = pico_zalloc(len);
+		if(!client->buffer)
+		{
+			pico_err = PICO_ERR_ENOMEM;
+			return HTTP_RETURN_ERROR;
+		}
+		// taking over the buffer
+		memcpy(client->buffer,buffer,len);
+	}
+	else
+		client->buffer = NULL;
 
 
-    client->bufferSize = len;
-    client->bufferSent = 0;
+	client->bufferSize = len;
+	client->bufferSent = 0;
 
-    // create the chunk size and send it
-    if(len > 0)
-    {
-        client->state = HTTP_SENDING_DATA;
-        chunkCount = pico_itoaHex(client->bufferSize,chunkStr);
-        chunkStr[chunkCount++] = '\r';
-        chunkStr[chunkCount++] = '\n';
-        pico_socket_write(client->sck,chunkStr,chunkCount);
-    }
-    else if(len == 0)
-    {
-        dbg("->\n");
-        // end of transmision
-        pico_socket_write(client->sck,"0\r\n\r\n",5u);
-        // nothing left, close the client
-        pico_socket_close(client->sck);
-        client->state = HTTP_CLOSED;
-    }
+	// create the chunk size and send it
+	if(len > 0)
+	{
+		client->state = HTTP_SENDING_DATA;
+		chunkCount = pico_itoaHex(client->bufferSize,chunkStr);
+		chunkStr[chunkCount++] = '\r';
+		chunkStr[chunkCount++] = '\n';
+		pico_socket_write(client->sck,chunkStr,chunkCount);
+	}
+	else if(len == 0)
+	{
+		dbg("->\n");
+		// end of transmision
+		pico_socket_write(client->sck,"0\r\n\r\n",5u);
+		// nothing left, close the client
+		pico_socket_close(client->sck);
+		client->state = HTTP_CLOSED;
+	}
 
-    return HTTP_RETURN_OK;
+	return HTTP_RETURN_OK;
 }
 
 /*
@@ -400,18 +400,18 @@
 
 int pico_http_getProgress(uint16_t conn, uint16_t * sent, uint16_t *total)
 {
-    struct httpClient * client = findClient(conn);
+	struct httpClient * client = findClient(conn);
 
-    if(!client)
-    {
-        dbg("Wrong connection id !\n");
-        return HTTP_RETURN_ERROR;
-    }
+	if(!client)
+	{
+		dbg("Wrong connection id !\n");
+		return HTTP_RETURN_ERROR;
+	}
 
-    *sent = client->bufferSent;
-    *total = client->bufferSize;
+	*sent = client->bufferSent;
+	*total = client->bufferSize;
 
-    return HTTP_RETURN_OK;
+	return HTTP_RETURN_OK;
 }
 
 /*
@@ -420,217 +420,217 @@
  */
 int pico_http_close(uint16_t conn)
 {
-    // close the server
-    if(conn == HTTP_SERVER_ID)
-    {
-        if(server.state == HTTP_SERVER_LISTEN)
-        {
-            struct pico_tree_node * index, * tmp;
-            // close the server
-            pico_socket_close(server.sck);
-            server.sck = NULL;
+	// close the server
+	if(conn == HTTP_SERVER_ID)
+	{
+		if(server.state == HTTP_SERVER_LISTEN)
+		{
+			struct pico_tree_node * index, * tmp;
+			// close the server
+			pico_socket_close(server.sck);
+			server.sck = NULL;
 
-            // destroy the tree
-            pico_tree_foreach_safe(index,&pico_http_clients,tmp)
-            {
-                struct httpClient * client = index->keyValue;
+			// destroy the tree
+			pico_tree_foreach_safe(index,&pico_http_clients,tmp)
+			{
+				struct httpClient * client = index->keyValue;
 
-                if(client->resource)
-                    pico_free(client->resource);
+				if(client->resource)
+					pico_free(client->resource);
 
-                pico_socket_close(client->sck);
-                pico_tree_delete(&pico_http_clients,client);
-            }
+				pico_socket_close(client->sck);
+				pico_tree_delete(&pico_http_clients,client);
+			}
 
-            server.state = HTTP_SERVER_CLOSED;
-            return HTTP_RETURN_OK;
-        }
-        else // nothing to close
-            return HTTP_RETURN_ERROR;
-    } // close a connection in this case
-    else
-    {
+			server.state = HTTP_SERVER_CLOSED;
+			return HTTP_RETURN_OK;
+		}
+		else // nothing to close
+			return HTTP_RETURN_ERROR;
+	} // close a connection in this case
+	else
+	{
 
-        struct httpClient * client = findClient(conn);
+		struct httpClient * client = findClient(conn);
 
-        if(!client)
-        {
-            dbg("Client not found..\n");
-            return HTTP_RETURN_ERROR;
-        }
+		if(!client)
+		{
+			dbg("Client not found..\n");
+			return HTTP_RETURN_ERROR;
+		}
 
-        pico_tree_delete(&pico_http_clients,client);
+		pico_tree_delete(&pico_http_clients,client);
 
-        if(client->resource)
-            pico_free(client->resource);
+		if(client->resource)
+			pico_free(client->resource);
 
-        if(client->buffer)
-            pico_free(client->buffer);
+		if(client->buffer)
+			pico_free(client->buffer);
 
-        if(client->state != HTTP_CLOSED || !client->sck)
-            pico_socket_close(client->sck);
+		if(client->state != HTTP_CLOSED || !client->sck)
+			pico_socket_close(client->sck);
 
-        pico_free(client);
-        return HTTP_RETURN_OK;
-    }
+		pico_free(client);
+		return HTTP_RETURN_OK;
+	}
 }
 
 // check the integrity of the request
 int parseRequest(struct httpClient * client)
 {
-    char c;
-    //read first line
-    consumeChar(c);
-    if(c == 'G')
-    { // possible GET
+	char c;
+	//read first line
+	consumeChar(c);
+	if(c == 'G')
+	{ // possible GET
 
-        char line[HTTP_HEADER_MAX_LINE];
-        int index = 0;
+		char line[HTTP_HEADER_MAX_LINE];
+		uint32_t index = 0;
 
-        line[index] = c;
+		line[index] = c;
 
-        // consume the full line
-        while(consumeChar(c)>0) // read char by char only the first line
-        {
-            line[++index] = c;
-            if(c == '\n')
-                break;
+		// consume the full line
+		while(consumeChar(c)>0) // read char by char only the first line
+		{
+			line[++index] = c;
+			if(c == '\n')
+				break;
 
-                if(index >= HTTP_HEADER_MAX_LINE)
-            {
-                dbg("Size exceeded \n");
-                return HTTP_RETURN_ERROR;
-            }
-        }
+			if(index >= HTTP_HEADER_MAX_LINE)
+			{
+				dbg("Size exceeded \n");
+				return HTTP_RETURN_ERROR;
+			}
+		}
 
-        // extract the function and the resource
-        if(memcmp(line,"GET",3u) || line[3u]!=' ' || index < 10u || line[index] !='\n')
-        {
-            dbg("Wrong command or wrong ending\n");
-            return HTTP_RETURN_ERROR;
-        }
+		// extract the function and the resource
+		if(memcmp(line,"GET",3u) || line[3u]!=' ' || index < 10u || line[index] !='\n')
+		{
+			dbg("Wrong command or wrong ending\n");
+			return HTTP_RETURN_ERROR;
+		}
 
-        // start reading the resource
-        index = 4u; // go after ' '
-        while(line[index]!=' ')
-        {
-            if(line[index]=='\n') // no terminator ' '
-            {
-                dbg("No terminator...\n");
-                return HTTP_RETURN_ERROR;
-            }
+		// start reading the resource
+		index = 4u; // go after ' '
+		while(line[index]!=' ')
+		{
+			if(line[index]=='\n') // no terminator ' '
+			{
+				dbg("No terminator...\n");
+				return HTTP_RETURN_ERROR;
+			}
 
-            index++;
-        }
+			index++;
+		}
 
-        client->resource = pico_zalloc(index - 3u);// allocate without the GET in front + 1 which is \0
+		client->resource = pico_zalloc(index - 3u);// allocate without the GET in front + 1 which is \0
 
-        if(!client)
-        {
-            pico_err = PICO_ERR_ENOMEM;
-            return HTTP_RETURN_ERROR;
-        }
+		if(!client)
+		{
+			pico_err = PICO_ERR_ENOMEM;
+			return HTTP_RETURN_ERROR;
+		}
 
-        // copy the resource
-        memcpy(client->resource,line+4u,index-4u);// copy without the \0 which was already set by pico_zalloc
+		// copy the resource
+		memcpy(client->resource,line+4u,index-4u);// copy without the \0 which was already set by pico_zalloc
 
-        client->state = HTTP_WAIT_EOF_HDR;
-        return HTTP_RETURN_OK;
+		client->state = HTTP_WAIT_EOF_HDR;
+		return HTTP_RETURN_OK;
 
-    }
+	}
 
-    return HTTP_RETURN_ERROR;
+	return HTTP_RETURN_ERROR;
 }
 
 
 
 int readRemainingHeader(struct httpClient * client)
 {
-    char line[100];
-    int count = 0;
-    int len;
+	char line[100];
+	int count = 0;
+	int len;
 
-    while( (len = pico_socket_read(client->sck,line,100u)) > 0)
-    {
-        char c;
-        int index = 0;
-        // parse the response
-        while(index < len)
-        {
-            c = line[index++];
-            if(c!='\r' && c!='\n')
-                count++;
-            if(c=='\n')
-            {
-                if(!count)
-                {
-                    client->state = HTTP_EOF_HDR;
-                    dbg("End of header !\n");
-                    break;
-                }
-                count = 0;
+	while( (len = pico_socket_read(client->sck,line,100u)) > 0)
+	{
+		char c;
+		int index = 0;
+		// parse the response
+		while(index < len)
+		{
+			c = line[index++];
+			if(c!='\r' && c!='\n')
+				count++;
+			if(c=='\n')
+			{
+				if(!count)
+				{
+					client->state = HTTP_EOF_HDR;
+					dbg("End of header !\n");
+					break;
+				}
+				count = 0;
 
-            }
-        }
-    }
+			}
+		}
+	}
 
-    return HTTP_RETURN_OK;
+	return HTTP_RETURN_OK;
 }
 
 void sendData(struct httpClient * client)
 {
-    int length;
-    while( client->bufferSent < client->bufferSize &&
-    (length = pico_socket_write(client->sck,client->buffer+client->bufferSent,client->bufferSize-client->bufferSent)) > 0 )
-    {
-        client->bufferSent += length;
-        server.wakeup(EV_HTTP_PROGRESS,client->connectionID);
-    }
+	int length;
+	while( client->bufferSent < client->bufferSize &&
+	(length = pico_socket_write(client->sck,client->buffer+client->bufferSent,client->bufferSize-client->bufferSent)) > 0 )
+	{
+		client->bufferSent += length;
+		server.wakeup(EV_HTTP_PROGRESS,client->connectionID);
+	}
 
-    if(client->bufferSent == client->bufferSize && client->bufferSize)
-    {
-        //send chunk trail
-        if(pico_socket_write(client->sck,"\r\n",2) > 0)
-        {
-            client->state = HTTP_WAIT_DATA;
-            //free the buffer
-            pico_free(client->buffer);
-            client->buffer = NULL;
-            server.wakeup(EV_HTTP_SENT,client->connectionID);
-        }
-    }
+	if(client->bufferSent == client->bufferSize && client->bufferSize)
+	{
+		//send chunk trail
+		if(pico_socket_write(client->sck,"\r\n",2) > 0)
+		{
+			client->state = HTTP_WAIT_DATA;
+			//free the buffer
+			pico_free(client->buffer);
+			client->buffer = NULL;
+			server.wakeup(EV_HTTP_SENT,client->connectionID);
+		}
+	}
 
 }
 
 int readData(struct httpClient * client)
 {
-    if(client->state == HTTP_WAIT_HDR)
-    {
-        if(parseRequest(client)<0 || readRemainingHeader(client)<0)
-        {
-            return HTTP_RETURN_ERROR;
-        }
-    } // continue with this in case the header comes line by line not a big chunk
-    else if(client->state == HTTP_WAIT_EOF_HDR)
-    {
-        if(readRemainingHeader(client)<0 )
-            return HTTP_RETURN_ERROR;
-    }
+	if(client->state == HTTP_WAIT_HDR)
+	{
+		if(parseRequest(client)<0 || readRemainingHeader(client)<0)
+		{
+			return HTTP_RETURN_ERROR;
+		}
+	} // continue with this in case the header comes line by line not a big chunk
+	else if(client->state == HTTP_WAIT_EOF_HDR)
+	{
+		if(readRemainingHeader(client)<0 )
+			return HTTP_RETURN_ERROR;
+	}
 
-    if(client->state == HTTP_EOF_HDR)
-    {
-        client->state = HTTP_WAIT_RESPONSE;
-        pico_socket_shutdown(client->sck,PICO_SHUT_RD);
-        server.wakeup(EV_HTTP_REQ,client->connectionID);
-    }
+	if(client->state == HTTP_EOF_HDR)
+	{
+		client->state = HTTP_WAIT_RESPONSE;
+		pico_socket_shutdown(client->sck,PICO_SHUT_RD);
+		server.wakeup(EV_HTTP_REQ,client->connectionID);
+	}
 
-    return HTTP_RETURN_OK;
+	return HTTP_RETURN_OK;
 }
 
 struct httpClient * findClient(uint16_t conn)
 {
-    struct httpClient dummy = {.connectionID = conn};
+	struct httpClient dummy = {.connectionID = conn};
 
-    return pico_tree_findKey(&pico_http_clients,&dummy);
+	return pico_tree_findKey(&pico_http_clients,&dummy);
 }
 #endif