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.

Files at this revision

API Documentation at this revision

Comitter:
tass
Date:
Thu Nov 28 13:53:18 2013 +0000
Parent:
123:dd26752a4538
Child:
126:374ed597275a
Commit message:
Added IP Filter support to ethernet interface.; Synced with master branch.

Changed in this revision

EthernetInterface/EthernetInterface.cpp Show annotated file Show diff for this revision Revisions of this file
EthernetInterface/EthernetInterface.h Show annotated file Show diff for this revision Revisions of this file
include/pico_config.h Show annotated file Show diff for this revision Revisions of this file
modules/pico_http_client.c Show annotated file Show diff for this revision Revisions of this file
modules/pico_ipfilter.c Show annotated file Show diff for this revision Revisions of this file
modules/pico_ipfilter.h Show annotated file Show diff for this revision Revisions of this file
stack/pico_socket.c Show annotated file Show diff for this revision Revisions of this file
--- a/EthernetInterface/EthernetInterface.cpp	Wed Nov 27 10:20:00 2013 +0000
+++ b/EthernetInterface/EthernetInterface.cpp	Thu Nov 28 13:53:18 2013 +0000
@@ -40,7 +40,7 @@
 #include "cmsis_os.h"
 #include "pico_dhcp_client.h"
 #include "pico_dns_client.h"
-
+#include "pico_ipfilter.h"
 //#define eth_dbg mbed_dbg
 #define eth_dbg(...)
 
@@ -199,3 +199,58 @@
     pico_string_to_ipv4(name,&addr.addr);
     return pico_dns_client_nameserver(&addr,PICO_DNS_NS_ADD);
 }
+
+int EthernetInterface::createIpFilter(char *ipAddress, char * netmask, int port, filter_type filter)
+{
+    struct pico_ip4 addr, nm, local;
+    if(!ipAddress) addr.addr = 0;
+    else pico_string_to_ipv4(ipAddress,&addr.addr);
+    
+    if(!netmask) nm.addr = 0;
+    else pico_string_to_ipv4(netmask,&nm.addr);
+    
+    pico_string_to_ipv4(ip_addr,&local.addr);
+    
+    if(filter == INPUT_FILTER)
+    {
+        return pico_ipv4_filter_add(NULL,PICO_PROTO_IPV4,&local,&nm,&addr,&nm,0,port,0,0,FILTER_REJECT);
+    }
+    else if(filter == OUTPUT_FILTER)
+    {
+        return pico_ipv4_filter_add(NULL,PICO_PROTO_IPV4,&addr,&nm,&local,&nm,port,0,0,0,FILTER_DROP);
+    }
+    else 
+        return -1;
+}
+
+int EthernetInterface::createIpFilter(char *src, char * src_netmask, int src_port, char *dst, char * dst_netmask, int dst_port)
+{
+    struct pico_ip4 src4,src_nm4,dst4,dst_nm4;
+    
+    if(!src)
+        src4.addr=0;
+    else
+        pico_string_to_ipv4(src,&src4.addr);
+    
+    if(!src_netmask)
+        src_nm4.addr=0;
+    else
+        pico_string_to_ipv4(src,&src_nm4.addr);    
+        
+    if(!dst)
+        dst4.addr=0;
+    else
+        pico_string_to_ipv4(src,&dst4.addr);
+    
+    if(!dst_netmask)
+        dst_nm4.addr=0;
+    else
+        pico_string_to_ipv4(src,&dst_nm4.addr);   
+        
+    return pico_ipv4_filter_add(NULL,PICO_PROTO_IPV4,&dst4,&dst_nm4,&src4,&src_nm4,dst_port,src_port,0,0,FILTER_DROP);
+}
+
+int EthernetInterface::destroyIpFilter(int filter_id)
+{
+    return pico_ipv4_filter_del(filter_id);
+}
\ No newline at end of file
--- a/EthernetInterface/EthernetInterface.h	Wed Nov 27 10:20:00 2013 +0000
+++ b/EthernetInterface/EthernetInterface.h	Thu Nov 28 13:53:18 2013 +0000
@@ -43,6 +43,14 @@
 #ifdef __cplusplus    
 }
 #endif
+
+typedef enum
+{
+    INPUT_FILTER,
+    OUTPUT_FILTER
+}filter_type;
+
+#define PORT_ANY    (0)
  /** Interface using Ethernet to connect to an IP-based network
  *
  */
@@ -98,6 +106,38 @@
    */
   static int setDnsServer(const char *);
   
+  /**
+  * Creates a custom rule for dropping packets.
+  * If an incoming packet is destined for our stack and an input filter that matches
+  * input_src & filter_mask == filter_src & filter_mask and the ports are the same, port = 0 means any port and also filters icmp.
+  * the packet will be dropped.
+  * The same thing for an output filter.
+  * If we try to send a packet and 
+  * output_dst & filter_mask == filter_dst & filter_mask and the ports are the same, 
+  * the packet will be dropped.
+  * return > 0 if success, the number is the filter identifier and it will be used later to destroy the filter.
+  * return < 0 error.
+  */
+  static int createIpFilter(char *ipAddress, char * netmask, int port, filter_type filter);
+  
+  /*
+  * This will create a custom filter, more complex than the previous one.
+  * A packet will be dropped if 
+  * packet.port(s) == filter.port(s)
+  * packet.src & filter.src_mask == filter.src & filter.src_mask
+  * packet.dst & filter.dst_mask == filter.dst & filter.dst_mask
+  * if a value is passed null or 0.0.0.0 for address or 0 for port, will be considered as 
+  * accept any.
+  * return > 0 if success, the number is the filter identifier and it will be used later to destroy the filter.
+  * return < 0 error.
+  */
+  
+  static int createIpFilter(char *src, char * src_netmask, int src_port, char *dst, char * dst_netmask, int dst_port);
+  /*
+  * Destroy a custom filter.
+  */
+  static int destroyIpFilter(int filter_id);
+  
 };
 
 #include "TCPSocketConnection.h"
--- a/include/pico_config.h	Wed Nov 27 10:20:00 2013 +0000
+++ b/include/pico_config.h	Thu Nov 28 13:53:18 2013 +0000
@@ -23,7 +23,7 @@
 #define PICO_SUPPORT_ICMP4
 #define PICO_SUPPORT_PING
 #define PICO_SUPPORT_IGMP2
-//#define PICO_SUPPORT_IPFILTER
+#define PICO_SUPPORT_IPFILTER
 //#define PICO_SUPPORT_IPFRAG
 #define PICO_SUPPORT_IPV4
 #define PICO_SUPPORT_MCAST
--- a/modules/pico_http_client.c	Wed Nov 27 10:20:00 2013 +0000
+++ b/modules/pico_http_client.c	Thu Nov 28 13:53:18 2013 +0000
@@ -40,7 +40,7 @@
 #endif
 
 #define dbg(...) do{}while(0)
-
+#define nop() do{}while(0)
 
 #define consumeChar(c) 							(pico_socket_read(client->sck,&c,1u))
 #define isLocation(line) 						(memcmp(line,"Location",8u) == 0)
@@ -49,7 +49,7 @@
 #define isChunked(line)							(memcmp(line," chunked",8u) == 0u)
 #define isNotHTTPv1(line)						(memcmp(line,"HTTP/1.",7u))
 #define is_hex_digit(x) ((('0' <= x) && (x <= '9')) || (('a' <= x) && (x <= 'f')))
-#define hex_digit_to_dec(x) ( (('0' <= x) && (x <= '9')) ? (x-'0') : ( (('a' <= x) && (x <= 'f')) ? (x-'a' + 10) : -1) )
+#define hex_digit_to_dec(x) ( (('0' <= x) && (x <= '9')) ? (x-'0') : ( (('a' <= x) && (x <= 'f')) ? (x-'a' + 10) : (-1)) )
 
 struct pico_http_client
 {
@@ -79,7 +79,66 @@
 // Local functions
 int parseHeaderFromServer(struct pico_http_client * client, struct pico_http_header * header);
 int readChunkLine(struct pico_http_client * client);
+//
+static inline void processConnErrClose(uint16_t ev, struct pico_http_client * client)
+{
+	if(ev & PICO_SOCK_EV_CONN)
+		client->wakeup(EV_HTTP_CON,client->connectionID);
 
+	if(ev & PICO_SOCK_EV_ERR)
+	{
+		client->wakeup(EV_HTTP_ERROR,client->connectionID);
+	}
+
+	if( (ev & PICO_SOCK_EV_CLOSE) || (ev & PICO_SOCK_EV_FIN) )
+	{
+		client->wakeup(EV_HTTP_CLOSE,client->connectionID);
+	}
+}
+
+static inline void waitForHeader(struct pico_http_client * client)
+{
+	// wait for header
+	if(parseHeaderFromServer(client,client->header) < 0)
+	{
+		client->wakeup(EV_HTTP_ERROR,client->connectionID);
+	}
+	else
+	{
+		// call wakeup
+		if(client->header->responseCode != HTTP_CONTINUE)
+		{
+			client->wakeup(
+					(client->header->responseCode == HTTP_OK) ?
+					(EV_HTTP_REQ | EV_HTTP_BODY) : // data comes for sure only when 200 is received
+					EV_HTTP_REQ
+					,client->connectionID);
+		}
+	}
+}
+
+static inline void treatReadEvent(struct pico_http_client * client)
+{
+	// read the header, if not read
+	if(client->state == HTTP_READING_HEADER)
+	{
+		// wait for header
+		client->header = pico_zalloc(sizeof(struct pico_http_header));
+		if(!client->header)
+		{
+			pico_err = PICO_ERR_ENOMEM;
+			return;
+		}
+
+		waitForHeader(client);
+	}
+	else
+	{
+		// just let the user know that data has arrived, if chunked data comes, will be treated in the
+		// read api.
+		client->wakeup(EV_HTTP_BODY,client->connectionID);
+	}
+}
 void tcpCallback(uint16_t ev, struct pico_socket *s)
 {
 
@@ -102,59 +161,13 @@
 		return;
 	}
 
-	if(ev & PICO_SOCK_EV_CONN)
-		client->wakeup(EV_HTTP_CON,client->connectionID);
+	processConnErrClose(ev,client);
 
 	if(ev & PICO_SOCK_EV_RD)
 	{
-
-		// read the header, if not read
-		if(client->state == HTTP_READING_HEADER)
-		{
-			// wait for header
-			client->header = pico_zalloc(sizeof(struct pico_http_header));
-			if(!client->header)
-			{
-				pico_err = PICO_ERR_ENOMEM;
-				return;
-			}
+		treatReadEvent(client);
 
-			// wait for header
-			if(parseHeaderFromServer(client,client->header) < 0)
-			{
-				client->wakeup(EV_HTTP_ERROR,client->connectionID);
-			}
-			else
-			{
-				// call wakeup
-				if(client->header->responseCode != HTTP_CONTINUE)
-				{
-					client->wakeup(
-							(client->header->responseCode == HTTP_OK) ?
-							EV_HTTP_REQ | EV_HTTP_BODY : // data comes for sure only when 200 is received
-							EV_HTTP_REQ
-							,client->connectionID);
-				}
-			}
-		}
-		else
-		{
-			// just let the user know that data has arrived, if chunked data comes, will be treated in the
-			// read api.
-			client->wakeup(EV_HTTP_BODY,client->connectionID);
-		}
 	}
-
-	if(ev & PICO_SOCK_EV_ERR)
-	{
-		client->wakeup(EV_HTTP_ERROR,client->connectionID);
-	}
-
-	if( (ev & PICO_SOCK_EV_CLOSE) || (ev & PICO_SOCK_EV_FIN) )
-	{
-		client->wakeup(EV_HTTP_CLOSE,client->connectionID);
-	}
-
 }
 
 // used for getting a response from DNS servers
@@ -202,7 +215,7 @@
 /*
  * API used for opening a new HTTP Client.
  *
- * The accepted uri's are [http://]hostname[:port]/resource
+ * The accepted uri's are [http:]hostname[:port]/resource
  * no relative uri's are accepted.
  *
  * The function returns a connection ID >= 0 if successful
@@ -212,12 +225,6 @@
 {
 	struct pico_http_client * client;
 
-	if(!wakeup)
-	{
-		pico_err = PICO_ERR_EINVAL;
-		return HTTP_RETURN_ERROR;
-	}
-
 	client = pico_zalloc(sizeof(struct pico_http_client));
 	if(!client)
 	{
@@ -292,7 +299,7 @@
 		}
 	}
 
-	length = (int32_t)pico_socket_write(http->sck,(void *)header,(int)strlen(header)+1);
+	length = pico_socket_write(http->sck,(void *)header,(int)strlen(header)+1);
 
 	if(hdr == HTTP_HEADER_DEFAULT)
 		pico_free(header);
@@ -300,6 +307,117 @@
 	return length;
 }
 
+
+///
+
+static inline int checkChunkLine(struct pico_http_client *client,int tmpLenRead)
+{
+	if(readChunkLine(client) == HTTP_RETURN_ERROR)
+	{
+		dbg("Probably the chunk is malformed or parsed wrong...\n");
+		client->wakeup(EV_HTTP_ERROR,client->connectionID);
+		return HTTP_RETURN_ERROR;
+	}
+
+	if(client->state != HTTP_READING_BODY || !tmpLenRead)
+		return 0; // force out
+
+	return 1;
+}
+
+static inline void updateContentLength(struct pico_http_client *client,int tmpLenRead )
+{
+	if(tmpLenRead > 0)
+	{
+		client->header->contentLengthOrChunk = client->header->contentLengthOrChunk - (uint32_t)tmpLenRead;
+	}
+}
+
+static inline int readBody(struct pico_http_client *client,char * data, uint16_t size, int *lenRead,int *tmpLenRead)
+{
+	*tmpLenRead = 0;
+
+	if(client->state == HTTP_READING_BODY)
+	{
+
+		// if needed truncate the data
+		*tmpLenRead = pico_socket_read(client->sck,data + (*lenRead),
+		(client->header->contentLengthOrChunk < ((uint32_t)(size-(*lenRead)))) ? ((int)client->header->contentLengthOrChunk) : (size-(*lenRead)));
+
+		updateContentLength(client,*tmpLenRead);
+		if(*tmpLenRead < 0)
+		{
+			// error on reading
+			dbg(">>> Error returned pico_socket_read\n");
+			pico_err = PICO_ERR_EBUSY;
+			// return how much data was read until now
+			return (*lenRead);
+		}
+	}
+
+	*lenRead += *tmpLenRead;
+	return 0;
+}
+
+static inline int readBigChunk(struct pico_http_client *client,char * data, uint16_t size, int *lenRead)
+{
+	int value;
+	// check if we need more than one chunk
+	if(size >= client->header->contentLengthOrChunk)
+	{
+		// read the rest of the chunk, if chunk is done, proceed to the next chunk
+		while((uint16_t)(*lenRead) <= size)
+		{
+			int tmpLenRead = 0;
+			if(readBody(client,data,size,lenRead,&tmpLenRead))
+				return (*lenRead);
+
+			if((value = checkChunkLine(client,tmpLenRead)) <= 0)
+				return value;
+		}
+	}
+	return 0;
+}
+
+static inline void readSmallChunk(struct pico_http_client *client,char * data, uint16_t size, int *lenRead)
+{
+	if(size < client->header->contentLengthOrChunk)
+	{
+		// read the data from the chunk
+		*lenRead = pico_socket_read(client->sck,(void *)data,size);
+
+		if(*lenRead)
+			client->header->contentLengthOrChunk = client->header->contentLengthOrChunk - (uint32_t)(*lenRead);
+	}
+}
+static inline int readChunkedData(struct pico_http_client *client,char * data, uint16_t size)
+{
+	int lenRead = 0;
+	int value;
+	// read the chunk line
+	if(readChunkLine(client) == HTTP_RETURN_ERROR)
+	{
+		dbg("Probably the chunk is malformed or parsed wrong...\n");
+		client->wakeup(EV_HTTP_ERROR,client->connectionID);
+		return HTTP_RETURN_ERROR;
+	}
+
+	// nothing to read, no use to try
+	if(client->state != HTTP_READING_BODY)
+	{
+		pico_err = PICO_ERR_EAGAIN;
+		return HTTP_RETURN_OK;
+	}
+
+
+	readSmallChunk(client,data,size,&lenRead);
+
+	if((value = readBigChunk(client,data,size,&lenRead)))
+		return value;
+
+	return lenRead;
+}
+
 /*
  * API for reading received data.
  *
@@ -324,76 +442,7 @@
 	if(client->header->transferCoding == HTTP_TRANSFER_FULL)
 		return pico_socket_read(client->sck,(void *)data,size);
 	else
-	{
-		int lenRead = 0;
-
-		// read the chunk line
-		if(readChunkLine(client) == HTTP_RETURN_ERROR)
-		{
-			dbg("Probably the chunk is malformed or parsed wrong...\n");
-			client->wakeup(EV_HTTP_ERROR,client->connectionID);
-			return HTTP_RETURN_ERROR;
-		}
-
-		// nothing to read, no use to try
-		if(client->state != HTTP_READING_BODY)
-		{
-			pico_err = PICO_ERR_EAGAIN;
-			return HTTP_RETURN_OK;
-		}
-
-		// check if we need more than one chunk
-		if(size >= client->header->contentLengthOrChunk)
-		{
-			// read the rest of the chunk, if chunk is done, proceed to the next chunk
-			while((uint16_t)lenRead <= size)
-			{
-				int tmpLenRead = 0;
-
-				if(client->state == HTTP_READING_BODY)
-				{
-
-					// if needed truncate the data
-					tmpLenRead = pico_socket_read(client->sck,data + lenRead,
-					(client->header->contentLengthOrChunk < (uint32_t)(size-lenRead)) ? (int)client->header->contentLengthOrChunk : (int)(size-lenRead));
-
-					if(tmpLenRead > 0)
-					{
-						client->header->contentLengthOrChunk = client->header->contentLengthOrChunk - (uint32_t)tmpLenRead;
-					}
-					else if(tmpLenRead < 0)
-					{
-						// error on reading
-						dbg(">>> Error returned pico_socket_read\n");
-						pico_err = PICO_ERR_EBUSY;
-						// return how much data was read until now
-						return lenRead;
-					}
-				}
-
-				lenRead += tmpLenRead;
-				if(readChunkLine(client) == HTTP_RETURN_ERROR)
-				{
-					dbg("Probably the chunk is malformed or parsed wrong...\n");
-					client->wakeup(EV_HTTP_ERROR,client->connectionID);
-					return HTTP_RETURN_ERROR;
-				}
-
-				if(client->state != HTTP_READING_BODY || !tmpLenRead)  break;
-
-			}
-		}
-		else
-		{
-			// read the data from the chunk
-			lenRead = pico_socket_read(client->sck,(void *)data,size);
-
-			if(lenRead)
-				client->header->contentLengthOrChunk = client->header->contentLengthOrChunk - (uint32_t)lenRead;
-		}
-
-		return lenRead;
-	}
+		return readChunkedData(client,data,size);
 }
 
 /*
@@ -445,6 +494,30 @@
  *
  * Close the client.
  */
+static inline void freeHeader(struct pico_http_client * toBeRemoved)
+{
+	if(toBeRemoved->header)
+	{
+		// free space used
+			if(toBeRemoved->header->location)
+				pico_free(toBeRemoved->header->location);
+
+		pico_free(toBeRemoved->header);
+	}
+}
+
+static inline void freeUri(struct pico_http_client * toBeRemoved)
+{
+	if(toBeRemoved->uriKey)
+	{
+		if(toBeRemoved->uriKey->host)
+			pico_free(toBeRemoved->uriKey->host);
+
+		if(toBeRemoved->uriKey->resource)
+			pico_free(toBeRemoved->uriKey->resource);
+		pico_free(toBeRemoved->uriKey);
+	}
+}
 int pico_http_client_close(uint16_t conn)
 {
 	struct pico_http_client * toBeRemoved = NULL;
@@ -463,25 +536,9 @@
 	if(toBeRemoved->sck)
 	pico_socket_close(toBeRemoved->sck);
 
-
-	if(toBeRemoved->header)
-	{
-		// free space used
-			if(toBeRemoved->header->location)
-				pico_free(toBeRemoved->header->location);
-
-		pico_free(toBeRemoved->header);
-	}
+	freeHeader(toBeRemoved);
+	freeUri(toBeRemoved);
 
-	if(toBeRemoved->uriKey)
-	{
-		if(toBeRemoved->uriKey->host)
-			pico_free(toBeRemoved->uriKey->host);
-
-		if(toBeRemoved->uriKey->resource)
-			pico_free(toBeRemoved->uriKey->resource);
-		pico_free(toBeRemoved->uriKey);
-	}
 	pico_free(toBeRemoved);
 
 	return 0;
@@ -497,7 +554,7 @@
 	char * header;
 	char port[6u]; // 6 = max length of a uint16 + \0
 
-	uint16_t headerSize = HTTP_GET_BASIC_SIZE;
+	unsigned long headerSize = HTTP_GET_BASIC_SIZE;
 
 	if(!uriData->host || !uriData->resource || !uriData->port)
 	{
@@ -506,7 +563,9 @@
 	}
 
 	//
-	headerSize = (uint16_t)(headerSize + strlen(uriData->host) + strlen(uriData->resource) + pico_itoa(uriData->port,port) + 4u); // 3 = size(CRLF + \0)
+	headerSize = (headerSize + strlen(uriData->host));
+	headerSize = (headerSize + strlen(uriData->resource));
+	headerSize = (headerSize + pico_itoa(uriData->port,port) + 4u); // 3 = size(CRLF + \0)
 	header = pico_zalloc(headerSize);
 
 	if(!header)
@@ -530,21 +589,143 @@
 	return header;
 }
 
-int parseHeaderFromServer(struct pico_http_client * client, struct pico_http_header * header)
+
+//
+static inline void readFirstLine(struct pico_http_client * client, char * line, uint32_t * index)
 {
-	char line[HTTP_HEADER_LINE_SIZE];
 	char c;
-	uint32_t index = 0;
 
 	// read the first line of the header
 	while(consumeChar(c)>0 && c!='\r')
 	{
-		if(index < HTTP_HEADER_LINE_SIZE) // truncate if too long
-			line[index++] = c;
+		if(*index < HTTP_HEADER_LINE_SIZE) // truncate if too long
+			line[(*index)++] = c;
 	}
 
 	consumeChar(c); // consume \n
+}
 
+static inline void startReadingBody(struct pico_http_client * client, struct pico_http_header * header)
+{
+
+	if(header->transferCoding == HTTP_TRANSFER_CHUNKED)
+	{
+		// read the first chunk
+		header->contentLengthOrChunk = 0;
+
+		client->state = HTTP_READING_CHUNK_VALUE;
+		readChunkLine(client);
+
+	}
+	else
+		client->state = HTTP_READING_BODY;
+}
+
+static inline int parseLocAndCont(struct pico_http_client * client, struct pico_http_header * header, char *line, uint32_t * index)
+{
+	   char c;
+	   // Location:
+
+		if(isLocation(line))
+		{
+			*index = 0;
+			while(consumeChar(c)>0 && c!='\r')
+			{
+				line[(*index)++] = c;
+			}
+
+			// allocate space for the field
+			header->location = pico_zalloc((*index)+1u);
+
+			memcpy(header->location,line,(*index));
+			return 1;
+		}// Content-Length:
+		else if(isContentLength(line))
+		{
+			header->contentLengthOrChunk = 0u;
+			header->transferCoding = HTTP_TRANSFER_FULL;
+			// consume the first space
+			consumeChar(c);
+			while(consumeChar(c)>0 && c!='\r')
+			{
+				header->contentLengthOrChunk = header->contentLengthOrChunk*10u + (uint32_t)(c-'0');
+			}
+			return 1;
+		}// Transfer-Encoding: chunked
+		return 0;
+}
+
+static inline int parseTransferEncoding(struct pico_http_client * client, struct pico_http_header * header, char *line, uint32_t * index)
+{
+	char c;
+
+	if(isTransferEncoding(line))
+	{
+		(*index) = 0;
+		while(consumeChar(c)>0 && c!='\r')
+		{
+			line[(*index)++] = c;
+		}
+
+		if(isChunked(line))
+		{
+			header->contentLengthOrChunk = 0u;
+			header->transferCoding = HTTP_TRANSFER_CHUNKED;
+		}
+		return 1;
+	}// just ignore the line
+	return 0;
+}
+
+
+static inline void parseFields(struct pico_http_client * client, struct pico_http_header * header, char *line, uint32_t * index)
+{
+	char c;
+
+	if(!parseLocAndCont(client,header,line,index))
+	{
+		if(!parseTransferEncoding(client,header,line,index))
+		{
+			while(consumeChar(c)>0 && c!='\r') nop();
+		}
+	}
+
+	// consume the next one
+	consumeChar(c);
+	// reset the index
+	(*index) = 0u;
+}
+
+static inline void parseRestOfHeader(struct pico_http_client * client, struct pico_http_header * header, char *line, uint32_t * index)
+{
+	char c;
+
+	// parse the rest of the header
+	while(consumeChar(c)>0)
+	{
+		if(c==':')
+		{
+			parseFields(client,header,line,index);
+		}
+		else if(c=='\r' && !(*index))
+		{
+				// consume the \n
+				consumeChar(c);
+				break;
+		}
+		else
+		{
+			line[(*index)++] = c;
+		}
+	}
+}
+
+int parseHeaderFromServer(struct pico_http_client * client, struct pico_http_header * header)
+{
+	char line[HTTP_HEADER_LINE_SIZE];
+	uint32_t index = 0;
+
+	readFirstLine(client,line,&index);
 	// check the integrity of the response
 	// make sure we have enough characters to include the response code
 	// make sure the server response starts with HTTP/1.
@@ -560,7 +741,6 @@
 												 (line[RESPONSE_INDEX+1] - '0') * 10 +
 												 (line[RESPONSE_INDEX+2] - '0'));
 
-
 	if(header->responseCode/100u > 5u)
 	{
 		// invalid response type
@@ -570,133 +750,57 @@
 
 	dbg("Server response : %d \n",header->responseCode);
 
-	// parse the rest of the header
-	while(consumeChar(c)>0)
-	{
-		if(c==':')
-		{
-			// check for interesting fields
-
-			// Location:
-			if(isLocation(line))
-			{
-				index = 0;
-				while(consumeChar(c)>0 && c!='\r')
-				{
-					line[index++] = c;
-				}
-
-				// allocate space for the field
-				header->location = pico_zalloc(index+1u);
-				if(!header->location)
-				{
-					pico_err = PICO_ERR_ENOMEM;
-					return HTTP_RETURN_ERROR;
-				}
-
-				memcpy(header->location,line,index);
-
-			}// Content-Length:
-			else if(isContentLength(line))
-			{
-				header->contentLengthOrChunk = 0u;
-				header->transferCoding = HTTP_TRANSFER_FULL;
-				// consume the first space
-				consumeChar(c);
-				while(consumeChar(c)>0 && c!='\r')
-				{
-					header->contentLengthOrChunk = header->contentLengthOrChunk*10u + (uint32_t)(c-'0');
-				}
+	parseRestOfHeader(client,header,line,&index);
 
-			}// Transfer-Encoding: chunked
-			else if(isTransferEncoding(line))
-			{
-				index = 0;
-				while(consumeChar(c)>0 && c!='\r')
-				{
-					line[index++] = c;
-				}
-
-				if(isChunked(line))
-				{
-					header->contentLengthOrChunk = 0u;
-					header->transferCoding = HTTP_TRANSFER_CHUNKED;
-				}
-
-			}// just ignore the line
-			else
-			{
-				while(consumeChar(c)>0 && c!='\r');
-			}
-
-			// consume the next one
-			consumeChar(c);
-			// reset the index
-			index = 0u;
-		}
-		else if(c=='\r' && !index)
-		{
-				// consume the \n
-				consumeChar(c);
-				break;
-		}
-		else
-		{
-			line[index++] = c;
-		}
-	}
-
-	if(header->transferCoding == HTTP_TRANSFER_CHUNKED)
-	{
-		// read the first chunk
-		header->contentLengthOrChunk = 0;
-
-		client->state = HTTP_READING_CHUNK_VALUE;
-		readChunkLine(client);
-
-	}
-	else
-		client->state = HTTP_READING_BODY;
-
+	startReadingBody(client,header);
 	dbg("End of header\n");
 	return HTTP_RETURN_OK;
 
 }
 
 // an async read of the chunk part, since in theory a chunk can be split in 2 packets
-int readChunkLine(struct pico_http_client * client)
+static inline void setClientChunkState(struct pico_http_client * client)
 {
-	char c = 0;
 
 	if(client->header->contentLengthOrChunk==0 && client->state == HTTP_READING_BODY)
 	{
 		client->state = HTTP_READING_CHUNK_VALUE;
 	}
-
-	if(client->state == HTTP_READING_CHUNK_VALUE)
-	{
-		while(consumeChar(c)>0 && c!='\r' && c!=';')
-		{
-			if(is_hex_digit(c))
-				client->header->contentLengthOrChunk = (client->header->contentLengthOrChunk << 4u) + (uint32_t)hex_digit_to_dec(c);
-			else
-			{
-				pico_err = PICO_ERR_EINVAL;
-				// something went wrong
-				return HTTP_RETURN_ERROR;
-			}
-		}
-
-		if(c=='\r' || c==';') client->state = HTTP_READING_CHUNK_TRAIL;
-	}
+}
+static inline void readChunkTrail(struct pico_http_client * client)
+{
+	char c;
 
 	if(client->state == HTTP_READING_CHUNK_TRAIL)
 	{
 
-		while(consumeChar(c)>0 && c!='\n');
+		while(consumeChar(c)>0 && c!='\n') nop();
+
 
 		if(c=='\n') client->state = HTTP_READING_BODY;
 	}
+}
+static inline void readChunkValue(struct pico_http_client * client)
+{
+	char c;
+
+	while(consumeChar(c)>0 && c!='\r' && c!=';')
+	{
+		if(is_hex_digit(c))
+			client->header->contentLengthOrChunk = (client->header->contentLengthOrChunk << 4u) + (uint32_t)hex_digit_to_dec(c);
+	}
+
+	if(c=='\r' || c==';') client->state = HTTP_READING_CHUNK_TRAIL;
+}
+int readChunkLine(struct pico_http_client * client)
+{
+	setClientChunkState(client);
+
+	if(client->state == HTTP_READING_CHUNK_VALUE)
+	{
+		readChunkValue(client);
+	}
+	readChunkTrail(client);
 
 	return HTTP_RETURN_OK;
 }
--- a/modules/pico_ipfilter.c	Wed Nov 27 10:20:00 2013 +0000
+++ b/modules/pico_ipfilter.c	Thu Nov 28 13:53:18 2013 +0000
@@ -2,7 +2,8 @@
 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
 See LICENSE and COPYING for usage.
 
-Authors: Simon Maes
+Authors: Andrei Carp
+		 Simon  Maes
 *********************************************************************/
 
 #include "pico_ipv4.h"
@@ -15,23 +16,33 @@
 #include "pico_ipfilter.h"
 #include "pico_tcp.h"
 #include "pico_udp.h"
-
+#include "pico_tree.h"
 
-//#define ipf_dbg dbg
+/**************** LOCAL MACROS ****************/
+#define MAX_PRIORITY	(10)
+#define MIN_PRIORITY	(-10)
+
 #define ipf_dbg(...) do{}while(0)
 
+/**************** LOCAL DECLARATIONS ****************/
 struct filter_node;
 typedef int (*func_pntr)(struct filter_node *filter, struct pico_frame *f);
+static int filter_compare(void *filterA, void *filterB);
+
+/**************** FILTER TREE ****************/
 
 struct filter_node {
   struct pico_device *fdev;
-  struct filter_node *next_filter;
+  // output address
   uint32_t out_addr;
   uint32_t out_addr_netmask;
+  // input address
   uint32_t in_addr;
   uint32_t in_addr_netmask;
+  // transport
   uint16_t out_port;
   uint16_t in_port;
+  // filter details
   uint8_t proto;
   int8_t priority;
   uint8_t tos;
@@ -39,102 +50,108 @@
   func_pntr function_ptr;
 };
 
-static struct filter_node *head = NULL;
-static struct filter_node *tail = NULL;
+PICO_TREE_DECLARE(filter_tree,&filter_compare);
+
+#define CHECK_AND_RETURN(a,b) do{ \
+									if((a) && ((a)!=(b)))\
+									{ \
+									  if((a)>(b)) return 1; \
+									  else return -1;\
+									}\
+								}while(0) \
+
 
-/*======================== FUNCTION PNTRS ==========================*/
+int filter_compare(void *filterA, void *filterB)
+{
+	struct filter_node * filter = (struct filter_node *)filterA,
+			* temp = (struct filter_node *)filterB;
+
+	// improve the search
+	if(temp->filter_id && filter->filter_id == temp->filter_id)
+		return 0;
 
-static int fp_accept(struct filter_node *filter, struct pico_frame *f) {
-	IGNORE_PARAMETER(filter);
-	IGNORE_PARAMETER(f);
+	ipf_dbg("filter ->> %x %x %x %x %d %d\n",filter->in_addr,filter->in_addr_netmask,filter->out_addr,filter->out_addr_netmask,filter->in_port,filter->out_port);
+
+	CHECK_AND_RETURN(filter->fdev,temp->fdev);
+	CHECK_AND_RETURN((filter->in_addr & filter->in_addr_netmask),(temp->in_addr & filter->in_addr_netmask));
+	CHECK_AND_RETURN((filter->out_addr & filter->out_addr_netmask),(temp->out_addr & filter->in_addr_netmask));
+	CHECK_AND_RETURN(filter->in_port,temp->in_port);
+	CHECK_AND_RETURN(filter->out_port,temp->out_port);
+	CHECK_AND_RETURN(filter->priority,temp->priority);
+	CHECK_AND_RETURN(filter->proto,temp->proto);
+
 	return 0;
 }
 
+/**************** FILTER CALLBACKS ****************/
+
 static int fp_priority(struct filter_node *filter, struct pico_frame *f) {
-
   //TODO do priority-stuff
-	IGNORE_PARAMETER(filter);
-	IGNORE_PARAMETER(f);
+  IGNORE_PARAMETER(filter);
+  IGNORE_PARAMETER(f);
   return 0;
 }
 
 static int fp_reject(struct filter_node *filter, struct pico_frame *f) {
 // TODO check first if sender is pico itself or not
-	IGNORE_PARAMETER(filter);
-  ipf_dbg("ipfilter> #reject\n");
+  IGNORE_PARAMETER(filter);
+  ipf_dbg("ipfilter> reject\n");
   pico_icmp4_packet_filtered(f);
   pico_frame_discard(f);
   return 1;
 }
 
 static int fp_drop(struct filter_node *filter, struct pico_frame *f) {
-	IGNORE_PARAMETER(filter);
-  ipf_dbg("ipfilter> # drop\n");
+  IGNORE_PARAMETER(filter);
+  ipf_dbg("ipfilter> drop\n");
   pico_frame_discard(f);
   return 1;
 }
 
-/*============================ API CALLS ============================*/
+/**************** FILTER API's ****************/
 int pico_ipv4_filter_add(struct pico_device *dev, uint8_t proto, struct pico_ip4 *out_addr, struct pico_ip4 *out_addr_netmask, struct pico_ip4 *in_addr, struct pico_ip4 *in_addr_netmask, uint16_t out_port, uint16_t in_port, int8_t priority, uint8_t tos, enum filter_action action)
 {
   static uint8_t filter_id = 0;
   struct filter_node *new_filter;
 
-  if ( !(dev != NULL || proto != 0 || (out_addr != NULL && out_addr->addr != 0U) || (out_addr_netmask != NULL && out_addr_netmask->addr != 0U)|| (in_addr != NULL && in_addr->addr != 0U) || (in_addr_netmask != NULL && in_addr_netmask->addr != 0U)|| out_port != 0 || in_port !=0 || tos != 0 )) {
+  if (proto != PICO_PROTO_IPV4 || tos != 0 )
+  {
     pico_err = PICO_ERR_EINVAL;
     return -1;
   }
-  if ( priority > 10 || priority < -10) {
-    pico_err = PICO_ERR_EINVAL;
-    return -1;
-  }
-  if (action > 3) {
+
+  if ( priority > MAX_PRIORITY || priority < MIN_PRIORITY) {
     pico_err = PICO_ERR_EINVAL;
     return -1;
   }
-  ipf_dbg("ipfilter> # adding filter\n");
+  if (action > FILTER_COUNT) {
+    pico_err = PICO_ERR_EINVAL;
+    return -1;
+  }
+  ipf_dbg("ipfilter> adding filter\n");
 
   new_filter = pico_zalloc(sizeof(struct filter_node));
-  if (!head) {
-    head = tail = new_filter;
-  } else {
-    tail->next_filter = new_filter;
-    tail = new_filter;
-  }
 
   new_filter->fdev = dev;
   new_filter->proto = proto;
-  if (out_addr != NULL)
-    new_filter->out_addr = out_addr->addr;
-  else
-    new_filter->out_addr = 0U;
 
-  if (out_addr_netmask != NULL)
-    new_filter->out_addr_netmask = out_addr_netmask->addr;
-  else
-    new_filter->out_addr_netmask = 0U;
-
-  if (in_addr != NULL)
-    new_filter->in_addr = in_addr->addr;
-  else
-    new_filter->in_addr = 0U;
- 
-  if (in_addr_netmask != NULL)
-    new_filter->in_addr_netmask = in_addr_netmask->addr;
-  else
-    new_filter->in_addr_netmask = 0U;
+  new_filter->out_addr = (!out_addr)? 0U : out_addr->addr;
+  new_filter->out_addr_netmask = (!out_addr_netmask) ? 0U : out_addr_netmask->addr;
+  new_filter->in_addr = (!in_addr) ? 0U : in_addr->addr;
+  new_filter->in_addr_netmask = (!in_addr_netmask) ? 0U : in_addr_netmask->addr;
 
   new_filter->out_port = out_port;
   new_filter->in_port = in_port;
   new_filter->priority = priority;
   new_filter->tos = tos;
-  new_filter->filter_id = filter_id++;
+
+  if(filter_id == 0)
+	  filter_id = 1;
+
+  new_filter->filter_id = filter_id;
 
   /*Define filterType_functionPointer here instead of in ipfilter-function, to prevent running multiple times through switch*/
   switch (action) {
-    case FILTER_ACCEPT:
-      new_filter->function_ptr = fp_accept;
-      break;
     case FILTER_PRIORITY:
       new_filter->function_ptr = fp_priority;
       break;
@@ -145,68 +162,43 @@
       new_filter->function_ptr = fp_drop;
       break;
     default:
-      ipf_dbg("ipfilter> #unknown filter action\n");
+      ipf_dbg("ipfilter> unknown filter action\n");
       break;
   }
+  if(pico_tree_insert(&filter_tree,new_filter))
+  {
+	  pico_free(new_filter);
+	  ipf_dbg("ipfilter> failed adding filter to tree.\n");
+	  return -1;
+  }
+
   return new_filter->filter_id;
 }
 
 int pico_ipv4_filter_del(uint8_t filter_id)
 {
-  struct filter_node *work;
-  struct filter_node *prev;
-
-  if (!tail || !head) {
-    pico_err = PICO_ERR_EPERM;
-    return -1;
-  }
-
-  work = head;
-  if (work->filter_id == filter_id) {
-      /*delete filter_node from linked list*/
-      head = work->next_filter;
-      pico_free(work);
-      return 0;
-  }
-  prev = work;
-  work = work->next_filter;
+	struct filter_node *node = NULL;
+	struct filter_node dummy={.filter_id=filter_id};
+	if((node = pico_tree_delete(&filter_tree,&dummy))== NULL)
+	{
+		ipf_dbg("ipfilter> failed to delete filter :%d\n",filter_id);
+		return -1;
+	}
 
-  while (1) {
-    if (work->filter_id == filter_id) {
-        if (work != tail) {
-        /*delete filter_node from linked list*/
-        prev->next_filter = work->next_filter;
-        pico_free(work);
-        return 0;
-        } else {
-          prev->next_filter = NULL;
-          pico_free(work);
-          return 0;
-        }
-    } else {
-      /*check next filter_node*/
-      prev = work;
-      work = work->next_filter;
-      if (work == tail) {
-        pico_err = PICO_ERR_EINVAL;
-        return -1;
-      }
-    }
-  }
+	pico_free(node);
+	return 0;
 }
 
-/*================================== CORE FILTER FUNCTIONS ==================================*/
-int match_filter(struct filter_node *filter, struct pico_frame *f)
+int ipfilter(struct pico_frame *f)
 {
   struct filter_node temp;
+  struct filter_node * filter_frame = NULL;
   struct pico_ipv4_hdr *ipv4_hdr = (struct pico_ipv4_hdr *) f->net_hdr;
   struct pico_tcp_hdr *tcp_hdr;
   struct pico_udp_hdr *udp_hdr;
+  struct pico_icmp4_hdr *icmp_hdr;
 
-  if (!filter|| !f) {
-    ipf_dbg("ipfilter> ## nullpointer in match filter \n");
-    return -1;
-  }
+  memset(&temp,0u,sizeof(struct filter_node));
 
   temp.fdev = f->dev;
   temp.out_addr = ipv4_hdr->dst.addr;
@@ -219,56 +211,30 @@
       udp_hdr = (struct pico_udp_hdr *) f->transport_hdr;
       temp.out_port = short_be(udp_hdr->trans.dport);
       temp.in_port = short_be(udp_hdr->trans.sport);
-  } else {
-    temp.out_port = temp.in_port = 0;
   }
+  else
+  {
+	  if(ipv4_hdr->proto == PICO_PROTO_ICMP4)
+	  {
+		  icmp_hdr = (struct pico_icmp4_hdr *) f->transport_hdr;
+		  if(icmp_hdr->type == PICO_ICMP_UNREACH && icmp_hdr->code == PICO_ICMP_UNREACH_FILTER_PROHIB)
+			  return 0;
+	  }
+	  temp.out_port = temp.in_port = 0;
+  }
+
   temp.proto = ipv4_hdr->proto;
   temp.priority = f->priority;
   temp.tos = ipv4_hdr->tos;
 
-
-
-  if ( ((filter->fdev == NULL || filter->fdev == temp.fdev) && \
-        (filter->in_addr == 0 || ((filter->in_addr_netmask == 0) ? (filter->in_addr == temp.in_addr) : 1)) &&\
-        (filter->in_port == 0 || filter->in_port == temp.in_port) &&\
-        (filter->out_addr == 0 || ((filter->out_addr_netmask == 0) ? (filter->out_addr == temp.out_addr) : 1)) && \
-        (filter->out_port == 0 || filter->out_port == temp.out_port)  && \
-        (filter->proto == 0 || filter->proto == temp.proto ) &&\
-        (filter->priority == 0 || filter->priority == temp.priority ) &&\
-        (filter->tos == 0 || filter->tos == temp.tos ) &&\
-        (filter->out_addr_netmask == 0 || ((filter->out_addr & filter->out_addr_netmask) == (temp.out_addr & filter->out_addr_netmask)) ) &&\
-        (filter->in_addr_netmask == 0 || ((filter->in_addr & filter->in_addr_netmask) == (temp.in_addr & filter->in_addr_netmask)) )\
-       ) ) 
-    return 0;
-
-  //No filter match!
-  ipf_dbg("ipfilter> #no match\n");
-  return 1;
-}
-
-int ipfilter(struct pico_frame *f)
-{
-  struct filter_node *work = head;
-
-  /*return 1 if pico_frame is discarded as result of the filtering, 0 for an incomming packet, -1 for faults*/
-  if (!tail || !head)  {
-    return 0;
+  filter_frame = pico_tree_findKey(&filter_tree,&temp);
+  if(filter_frame)
+  {
+	  ipf_dbg("Filtering frame %p with filter %p\n",f,filter_frame);
+	  filter_frame->function_ptr(filter_frame,f);
+	  return 1;
   }
 
-  if ( match_filter(work, f) == 0 ) { 
-    ipf_dbg("ipfilter> # ipfilter match\n");
-    /*filter match, execute filter!*/
-    return work->function_ptr(work, f);
-  } 
-  while (tail != work) {
-    ipf_dbg("ipfilter> next filter..\n");
-    work = work->next_filter;
-    if ( match_filter(work, f) == 0 ) {
-      ipf_dbg("ipfilter> # ipfilter match\n");
-      /*filter match, execute filter!*/
-      return work->function_ptr(work, f);
-    }
-  }
   return 0;
 }
 
--- a/modules/pico_ipfilter.h	Wed Nov 27 10:20:00 2013 +0000
+++ b/modules/pico_ipfilter.h	Thu Nov 28 13:53:18 2013 +0000
@@ -10,14 +10,12 @@
 #include "pico_device.h"
 
 enum filter_action {
-  FILTER_ACCEPT = 0,
   FILTER_PRIORITY,
   FILTER_REJECT,
   FILTER_DROP,
+  FILTER_COUNT
 };
 
-
-
 int pico_ipv4_filter_add(struct pico_device *dev, uint8_t proto,
   struct pico_ip4 *out_addr, struct pico_ip4 *out_addr_netmask, struct pico_ip4 *in_addr,
   struct pico_ip4 *in_addr_netmask, uint16_t out_port, uint16_t in_port,
--- a/stack/pico_socket.c	Wed Nov 27 10:20:00 2013 +0000
+++ b/stack/pico_socket.c	Thu Nov 28 13:53:18 2013 +0000
@@ -713,7 +713,7 @@
 {
   struct pico_frame *cpy = NULL;
   struct pico_sockport *sp = NULL;
-  struct pico_socket *s = NULL, *found = NULL;
+  struct pico_socket *s = NULL;
   struct pico_tree_node *index = NULL;
   struct pico_tree_node *_tmp;
   struct pico_trans *tr = (struct pico_trans *) f->transport_hdr;
@@ -724,6 +724,10 @@
   struct pico_ipv6_hdr *ip6hdr;
   #endif
 
+#ifdef PICO_SUPPORT_TCP
+  struct pico_socket *found = NULL;
+#endif
+
   if (!tr)
     return -1;
 
@@ -1481,12 +1485,17 @@
 
 int pico_socket_listen(struct pico_socket *s, int backlog)
 {
+  IGNORE_PARAMETER(s);
+  IGNORE_PARAMETER(backlog);
   pico_err = PICO_ERR_EINVAL;
   return -1;
 }
 
 struct pico_socket *pico_socket_accept(struct pico_socket *s, void *orig, uint16_t *local_port)
 {
+  IGNORE_PARAMETER(s);
+  IGNORE_PARAMETER(orig);
+  IGNORE_PARAMETER(local_port);
   pico_err = PICO_ERR_EINVAL;
   return NULL;
 }
@@ -2085,7 +2094,7 @@
 
 #define SL_LOOP_MIN 1
 
-
+#ifdef PICO_SUPPORT_TCP
 static int checkSocketSanity(struct pico_socket *s)
 {
 
@@ -2109,10 +2118,17 @@
   }
   return 0;
 }
+#endif
 
 int pico_sockets_loop(int loop_score)
 {
-  static struct pico_tree_node *index_udp, * index_tcp;
+#ifdef PICO_SUPPORT_UDP
+  static struct pico_tree_node *index_udp;
+#endif
+
+#ifdef PICO_SUPPORT_TCP
+  static struct pico_tree_node* index_tcp;
+#endif
 
   struct pico_sockport *start;
   struct pico_socket *s;