Rewrite from scratch a TCP/IP stack for mbed. So far the following parts are usable: Drivers: - EMAC driver (from CMSIS 2.0) Protocols: - Ethernet protocol - ARP over ethernet for IPv4 - IPv4 over Ethernet - ICMPv4 over IPv4 - UDPv4 over IPv4 APIs: - Sockets for UDPv4 The structure of this stack is designed to be very modular. Each protocol can register one or more protocol to handle its payload, and in each protocol, an API can be hooked (like Sockets for example). This is an early release.

Revision:
6:7f7f29fde21c
Parent:
5:3cd83fcb1467
--- a/Sockets.cpp	Mon Jun 13 13:13:59 2011 +0000
+++ b/Sockets.cpp	Mon Jun 13 15:40:56 2011 +0000
@@ -48,15 +48,14 @@
 
 struct Socket_Entry
 {
-    //Bool_t                inUse;
-    Socket_Family_t        family;
-    Socket_Protocol_t    protocol;
-    int32_t                options;
-    State_t                state;
-    Socket_Addr_t        *localAddr,
-                        *remoteAddr;
-    CQueue_t                *dataQueue;
-    int32_t                index;
+    Socket_Family_t		family;
+    Socket_Protocol_t	protocol;
+    int32_t				options;
+    State_t				state;
+    Socket_Addr_t		*localAddr,
+						*remoteAddr;
+    CQueue_t			*dataQueue;
+    int32_t				index;
 };
 typedef struct Socket_Entry Socket_Entry_t;
 
@@ -65,13 +64,13 @@
 static Bool_t            socketAPIInitialized = False;
 
 
-static void             Init(void);
-static int32_t             Hook(NetIF_t *netIF, Protocol_ID_t protocolID, NetPacket_t *packet);
-static void             Hook_UDPv4(NetIF_t *netIF, NetPacket_t *packet, Socket_Entry_t *entry);
-static Socket_Entry_t    *GetSocketEntry(Socket_t socket);
-static int32_t            BindUDPv4(Socket_Entry_t    *entry, Socket_AddrIn_t *addrIn);
-static int32_t            Recv_Data(Socket_Entry_t *entry, uint8_t *data, int32_t length);
-static int32_t            SendToUDPv4(Socket_Entry_t *entry, uint8_t *data, int32_t length, Socket_AddrIn_t *remoteAddr);
+static void				Init(void);
+static int32_t			Hook(NetIF_t *netIF, Protocol_ID_t protocolID, NetPacket_t *packet);
+static void				Hook_UDPv4(NetIF_t *netIF, NetPacket_t *packet, Socket_Entry_t *entry);
+static Socket_Entry_t	*GetSocketEntry(Socket_t socket);
+static int32_t			BindUDPv4(Socket_Entry_t    *entry, Socket_AddrIn_t *addrIn);
+static int32_t			Recv_Data(Socket_Entry_t *entry, uint8_t *data, int32_t length);
+static int32_t			SendToUDPv4(Socket_Entry_t *entry, uint8_t *data, int32_t length, Socket_AddrIn_t *remoteAddr);
 
 
 Net_API_t    sockets = 
@@ -127,12 +126,11 @@
 
 static void Hook_UDPv4(NetIF_t *netIF, NetPacket_t *packet, Socket_Entry_t *entry)
 {
-    IPv4_Header_t        *ipv4Header;
-    UDPv4_Header_t        *udpv4Header;
-    Socket_AddrIn_t        *localAddrIn, *remoteAddrIn;
-    int32_t                depth;
-    DataBlock_t            *dataBlock;
-
+    IPv4_Header_t		*ipv4Header;
+    UDPv4_Header_t		*udpv4Header;
+    Socket_AddrIn_t		*localAddrIn, *remoteAddrIn;
+    int32_t				depth;
+    DataBlock_t			*dataBlock;
 
     depth = packet->depth;
     ipv4Header = (IPv4_Header_t *)packet->headerPtrTable[depth];
@@ -184,33 +182,39 @@
     return;
 }
 
-static int32_t BindUDPv4(Socket_Entry_t    *entry, Socket_AddrIn_t *addrIn)
+static int32_t BindUDPv4(Socket_Entry_t *entry, Socket_AddrIn_t *addrIn)
 {
-    int32_t                result = -1;
-    Socket_AddrIn_t        *localAddrIn, 
-                        *remoteAddrIn;
+    int32_t					result = -1;
+    Socket_AddrIn_t			*localAddrIn,
+							*remoteAddrIn;
 
+	/* Allocate local internet v4 addr */
     entry->localAddr = (Socket_Addr_t *)malloc(sizeof(Socket_AddrIn_t));
     if (entry->localAddr == NULL)
     {
         mbedNet_LastError = mbedNetResult_NotEnoughMemory;
         goto Exit;
     }
+
+	/* Allocate remote internet v4 addr */
     entry->remoteAddr = (Socket_Addr_t *)malloc(sizeof(Socket_AddrIn_t));
     if (entry->remoteAddr == NULL)
     {
-        free(entry->localAddr);
+		free(entry->localAddr);
         mbedNet_LastError = mbedNetResult_NotEnoughMemory;
         goto Exit;
     }
+	
+	/* Setup local socket address */
     localAddrIn = (Socket_AddrIn_t *)entry->localAddr;
-    remoteAddrIn = (Socket_AddrIn_t *)entry->remoteAddr;
     memcpy(localAddrIn, addrIn, sizeof(Socket_AddrIn_t));
-    memset(remoteAddrIn, 0, sizeof(Socket_AddrIn_t));
-    remoteAddrIn->family = addrIn->family;
-    remoteAddrIn->len = addrIn->len;
-    localAddrIn->port = addrIn->port;
-    
+
+	/* Setup remote socket adress, copy from local address, set port & address to zero */
+	remoteAddrIn = (Socket_AddrIn_t *)entry->remoteAddr;
+	*remoteAddrIn = *localAddrIn;
+	remoteAddrIn->port = 0;
+	remoteAddrIn->address.addr = 0;
+        
     DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Binding socket %d to %d.%d.%d.%d:%d", 
         entry->index, 
         addrIn->address.IP0, 
@@ -250,17 +254,15 @@
 }
 
 
-static int32_t SendToUDPv4(Socket_Entry_t *entry, uint8_t *data, int32_t length, Socket_AddrIn_t *remoteAddr)
+static int32_t SendToUDPv4(Socket_Entry_t *entry, uint8_t *data, int32_t length, Socket_AddrIn_t *remoteAddrIn)
 {
     int32_t                count = -1,
                         totalLength;
     IPv4_Header_t        *ipv4Header;
     UDPv4_Header_t        *udpv4Header;
-    Socket_AddrIn_t        *localAddrIn,
-                        *remoteAddrIn;
+    Socket_AddrIn_t        *localAddrIn;
     
     localAddrIn = (Socket_AddrIn_t *)entry->localAddr;
-    remoteAddrIn = (Socket_AddrIn_t *)entry->remoteAddr;
     totalLength = length + sizeof(UDPv4_Header_t) + sizeof(IPv4_Header_t);
     ipv4Header = (IPv4_Header_t *)malloc(totalLength);
     if (ipv4Header == NULL)
@@ -274,12 +276,11 @@
     
     DEBUG_SOURCE(DEBUG_LEVEL_VERBOSE0, ("UDPv4 sending %d bytes to %d.%d.%d.%d:%d",
         length,
-        remoteAddr->address.IP0,
-        remoteAddr->address.IP1,
-        remoteAddr->address.IP2,
-        remoteAddr->address.IP3,
-        ntohs(remoteAddr->port)
-
+        remoteAddrIn->address.IP0,
+        remoteAddrIn->address.IP1,
+        remoteAddrIn->address.IP2,
+        remoteAddrIn->address.IP3,
+        ntohs(remoteAddrIn->port)
     ));
     
     udpv4Header = (UDPv4_Header_t *)(ipv4Header + 1);
@@ -292,7 +293,7 @@
     ipv4Header->fragmentFlags = 0;
     ipv4Header->ttl = NET_DEFAULT_TTL;
     ipv4Header->protocol = IPV4_PROTO_UDPV4;
-    ipv4Header->dest = remoteAddr->address;
+    ipv4Header->dest = remoteAddrIn->address;
     
     udpv4Header->sourcePort = localAddrIn->port;
     udpv4Header->destPort = remoteAddrIn->port;
@@ -418,8 +419,8 @@
     
     if (entry == NULL)
     {
-        free(entry->localAddr);
-        free(entry->remoteAddr);
+        if (entry->localAddr) free(entry->localAddr);
+        if (entry->remoteAddr) free(entry->remoteAddr);
         DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("Not enough memory to allocate data queue"));
         mbedNet_LastError = mbedNetResult_NotEnoughMemory;
         result = -1;
@@ -510,6 +511,12 @@
     entry = GetSocketEntry(socket);
     if (entry == NULL) goto Exit;
 
+    if (entry->protocol == SOCK_DGRAM)
+    {
+        mbedNet_LastError = mbedNetResult_DestinationAddressRequired;
+        goto Exit;
+    }
+
     if (CQueue_IsEmpty(entry->dataQueue))
     {
         mbedNet_LastError = mbedNetResult_WouldBlock;
@@ -563,9 +570,9 @@
     if ((entry = GetSocketEntry(socket)) == NULL) goto Exit;
     
     entry->state = State_Close;
-    free(entry->localAddr);
+    if (entry->localAddr) free(entry->localAddr);
     entry->localAddr = NULL;
-    free(entry->remoteAddr);
+    if (entry->remoteAddr) free(entry->remoteAddr);
     entry->remoteAddr = NULL;
     /* Free pending data blocks */
     while(CQueue_Peek(entry->dataQueue, &ptr) != -1)