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.

Committer:
tass
Date:
Thu Jan 28 15:12:00 2016 +0100
Revision:
155:a70f34550c34
Parent:
142:35da43068894
Adding TCP flag for FIN.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
daniele 29:1a47b7151851 1 /*
daniele 29:1a47b7151851 2 *
daniele 29:1a47b7151851 3 * PicoTCP Socket interface for mbed.
daniele 29:1a47b7151851 4 * Copyright (C) 2013 TASS Belgium NV
daniele 29:1a47b7151851 5 *
daniele 29:1a47b7151851 6 * Released under GPL v2
daniele 29:1a47b7151851 7 *
daniele 29:1a47b7151851 8 * Other licensing models might apply at the sole discretion of the copyright holders.
daniele 29:1a47b7151851 9 *
daniele 29:1a47b7151851 10 *
daniele 29:1a47b7151851 11 * This software is based on the mbed.org EthernetInterface implementation:
daniele 29:1a47b7151851 12 * Copyright (C) 2012 mbed.org, MIT License
daniele 29:1a47b7151851 13 *
daniele 29:1a47b7151851 14 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
daniele 29:1a47b7151851 15 * and associated documentation files (the "Software"), to deal in the Software without restriction,
daniele 29:1a47b7151851 16 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
daniele 29:1a47b7151851 17 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
daniele 29:1a47b7151851 18 * furnished to do so, subject to the following conditions:
daniele 29:1a47b7151851 19 *
daniele 29:1a47b7151851 20 * The above copyright notice and this permission notice shall be included in all copies or
daniele 29:1a47b7151851 21 * substantial portions of the Software.
daniele 29:1a47b7151851 22 *
daniele 29:1a47b7151851 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
daniele 29:1a47b7151851 24 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
daniele 29:1a47b7151851 25 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
daniele 29:1a47b7151851 26 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
daniele 29:1a47b7151851 27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
daniele 29:1a47b7151851 28 */
daniele 29:1a47b7151851 29
daniele 29:1a47b7151851 30 #include "EthernetInterface.h"
daniele 29:1a47b7151851 31 #include "Queue.h"
daniele 29:1a47b7151851 32 #include "wrapper.h"
daniele 29:1a47b7151851 33 #include "proxy_endpoint.h"
daniele 29:1a47b7151851 34 #include "pico_dev_mbed_emac.h"
daniele 29:1a47b7151851 35 #include "mbed.h"
daniele 29:1a47b7151851 36 #include "PicoCondition.h"
daniele 29:1a47b7151851 37 extern "C"{
daniele 29:1a47b7151851 38 #include "pico_stack.h"
daniele 29:1a47b7151851 39 #include "pico_config.h"
daniele 29:1a47b7151851 40 #include "cmsis_os.h"
daniele 29:1a47b7151851 41 #include "pico_dhcp_client.h"
daniele 29:1a47b7151851 42 #include "pico_dns_client.h"
tass 125:96003ae6f1d8 43 #include "pico_ipfilter.h"
tass 129:dbf9eddc9109 44 #include "pico_slaacv4.h"
tass 44:ffd9a11d4f95 45 //#define eth_dbg mbed_dbg
tass 42:13e557b44f68 46 #define eth_dbg(...)
tass 42:13e557b44f68 47
daniele 29:1a47b7151851 48 void (*linkCb)(uint32_t link) = NULL;
daniele 29:1a47b7151851 49 }
daniele 29:1a47b7151851 50
daniele 29:1a47b7151851 51 //DigitalOutput led(LED3);
daniele 29:1a47b7151851 52 /* TCP/IP and Network Interface Initialisation */
daniele 29:1a47b7151851 53 static struct pico_device *lpc_eth;
daniele 29:1a47b7151851 54
daniele 29:1a47b7151851 55 static uint32_t dhcp_xid = 0;
daniele 29:1a47b7151851 56 static PicoCondition dhcp_mx;
daniele 29:1a47b7151851 57 static int dhcp_retval = -1;
daniele 29:1a47b7151851 58
daniele 29:1a47b7151851 59 static char mac_addr[19];
daniele 29:1a47b7151851 60 static char ip_addr[17] = "\0";
daniele 29:1a47b7151851 61 static char gw_addr[17] = "\0";
tass 127:476fed453d4d 62 static char nm_addr[17] = "\0";
daniele 29:1a47b7151851 63 static bool use_dhcp = false;
daniele 29:1a47b7151851 64 static bool is_initialized = false;
daniele 29:1a47b7151851 65
tass 129:dbf9eddc9109 66 void slaacv4_cb(struct pico_ip4 *ip, uint8_t code)
tass 129:dbf9eddc9109 67 {
tass 129:dbf9eddc9109 68 struct pico_ip4 nm_ip4;
tass 129:dbf9eddc9109 69 if(code == 0 && ip)
tass 129:dbf9eddc9109 70 {
tass 129:dbf9eddc9109 71 dhcp_retval = 0;
tass 129:dbf9eddc9109 72
tass 129:dbf9eddc9109 73 pico_ipv4_to_string(ip_addr, ip->addr);
tass 129:dbf9eddc9109 74 nm_ip4.addr = long_be(0xFFFF0000);
tass 129:dbf9eddc9109 75 pico_ipv4_to_string(nm_addr,nm_ip4.addr);
tass 129:dbf9eddc9109 76 }
tass 129:dbf9eddc9109 77 else
tass 129:dbf9eddc9109 78 dhcp_retval = -1;
tass 129:dbf9eddc9109 79
tass 129:dbf9eddc9109 80 dhcp_mx.unlock();
tass 129:dbf9eddc9109 81 }
tass 129:dbf9eddc9109 82
daniele 29:1a47b7151851 83 static void dhcp_cb(void *cli, int code)
daniele 29:1a47b7151851 84 {
daniele 29:1a47b7151851 85 void *id = NULL;
tass 127:476fed453d4d 86 struct pico_ip4 address, gateway, netmask, zero = {};
tass 41:4c18c62b31b9 87
tass 42:13e557b44f68 88 if (PICO_DHCP_ERROR == code)
daniele 29:1a47b7151851 89 goto fail;
tass 99:1c92cc810ecb 90
tass 99:1c92cc810ecb 91 if (PICO_DHCP_RESET == code)
tass 99:1c92cc810ecb 92 goto reset;
tass 99:1c92cc810ecb 93
daniele 29:1a47b7151851 94 id = pico_dhcp_get_identifier(dhcp_xid);
daniele 29:1a47b7151851 95 if (!id)
daniele 29:1a47b7151851 96 goto fail;
daniele 29:1a47b7151851 97 address = pico_dhcp_get_address(id);
daniele 29:1a47b7151851 98 gateway = pico_dhcp_get_gateway(id);
tass 127:476fed453d4d 99 netmask = pico_dhcp_get_netmask(id);
daniele 29:1a47b7151851 100 //if (address) ? // still needed
tass 127:476fed453d4d 101
daniele 29:1a47b7151851 102 pico_ipv4_to_string(ip_addr, address.addr);
tass 127:476fed453d4d 103 pico_ipv4_to_string(gw_addr,gateway.addr);
tass 127:476fed453d4d 104 pico_ipv4_to_string(nm_addr,netmask.addr);
tass 127:476fed453d4d 105
tass 53:f3ea2e39a7b2 106 eth_dbg("IP assigned : %s\n",ip_addr);
daniele 29:1a47b7151851 107
daniele 29:1a47b7151851 108 if (gateway.addr != 0) {
daniele 29:1a47b7151851 109 pico_ipv4_to_string(gw_addr, gateway.addr);
tass 53:f3ea2e39a7b2 110 eth_dbg("Default gateway assigned : %s\n",gw_addr);
daniele 29:1a47b7151851 111 pico_ipv4_route_add(zero, zero, gateway, 1, NULL);
daniele 29:1a47b7151851 112 }
tass 43:5f2146814b83 113
tass 43:5f2146814b83 114 dhcp_retval = 0;
daniele 29:1a47b7151851 115 dhcp_mx.unlock();
tass 41:4c18c62b31b9 116
daniele 29:1a47b7151851 117 return;
daniele 29:1a47b7151851 118
daniele 29:1a47b7151851 119 fail:
tass 129:dbf9eddc9109 120 pico_slaacv4_claimip(lpc_eth,slaacv4_cb);
tass 99:1c92cc810ecb 121
tass 99:1c92cc810ecb 122 reset:
tass 99:1c92cc810ecb 123 eth_dbg("DHCP reset!\n");
daniele 29:1a47b7151851 124 }
daniele 29:1a47b7151851 125
daniele 29:1a47b7151851 126 static void init_eth(void)
daniele 29:1a47b7151851 127 {
daniele 29:1a47b7151851 128 if (!is_initialized) {
daniele 29:1a47b7151851 129 pico_stack_init();
daniele 29:1a47b7151851 130 picotcp_init();
daniele 29:1a47b7151851 131 lpc_eth = pico_emac_create("mbed0");
daniele 29:1a47b7151851 132 is_initialized = true;
daniele 29:1a47b7151851 133 pico_dns_client_init();
daniele 29:1a47b7151851 134 }
daniele 29:1a47b7151851 135 if (lpc_eth) {
daniele 29:1a47b7151851 136 snprintf(mac_addr, 19, "%02X:%02X:%02X:%02X:%02X:%02X", lpc_eth->eth->mac.addr[0], lpc_eth->eth->mac.addr[1],
daniele 29:1a47b7151851 137 lpc_eth->eth->mac.addr[2], lpc_eth->eth->mac.addr[3], lpc_eth->eth->mac.addr[4], lpc_eth->eth->mac.addr[5]);
daniele 29:1a47b7151851 138 }
tass 41:4c18c62b31b9 139
tass 41:4c18c62b31b9 140 if(lpc_eth)
tass 42:13e557b44f68 141 eth_dbg("Ethernet initialized...\n");
tass 41:4c18c62b31b9 142 else
tass 42:13e557b44f68 143 eth_dbg("Failed to start Ethernet...\n");
tass 41:4c18c62b31b9 144
daniele 29:1a47b7151851 145 }
daniele 29:1a47b7151851 146
daniele 29:1a47b7151851 147 int EthernetInterface::init()
daniele 29:1a47b7151851 148 {
daniele 29:1a47b7151851 149 init_eth();
daniele 29:1a47b7151851 150 /* use dhcp to retrieve address and gateway. */
daniele 29:1a47b7151851 151 use_dhcp = true;
daniele 29:1a47b7151851 152 return 0;
daniele 29:1a47b7151851 153 }
daniele 29:1a47b7151851 154
daniele 29:1a47b7151851 155 int EthernetInterface::init(const char* ip, const char* mask, const char* gateway) {
daniele 29:1a47b7151851 156 pico_ip4 pico_addr, pico_netmask, pico_gw = {0}, zero = {0};
daniele 29:1a47b7151851 157
tass 94:7bdeb5f4d111 158 if(strcmp(ip,gateway) == 0)
tass 94:7bdeb5f4d111 159 return -1;
tass 94:7bdeb5f4d111 160
daniele 29:1a47b7151851 161 init_eth();
daniele 29:1a47b7151851 162
daniele 29:1a47b7151851 163 use_dhcp = false;
daniele 29:1a47b7151851 164 strcpy(ip_addr, ip);
tass 127:476fed453d4d 165 strcpy(nm_addr, mask);
tass 127:476fed453d4d 166 strcpy(gw_addr,gateway);
daniele 29:1a47b7151851 167
daniele 29:1a47b7151851 168 pico_string_to_ipv4(ip, &pico_addr.addr);
daniele 29:1a47b7151851 169 pico_string_to_ipv4(mask, &pico_netmask.addr);
daniele 29:1a47b7151851 170 if (gateway) {
tass 94:7bdeb5f4d111 171 pico_string_to_ipv4(gateway, &pico_gw.addr);
daniele 29:1a47b7151851 172 }
daniele 29:1a47b7151851 173 pico_ipv4_link_add(lpc_eth, pico_addr, pico_netmask);
daniele 29:1a47b7151851 174
daniele 29:1a47b7151851 175 if (pico_gw.addr)
daniele 29:1a47b7151851 176 pico_ipv4_route_add(zero, zero, pico_gw, 1, NULL);
daniele 29:1a47b7151851 177
daniele 29:1a47b7151851 178 return 0;
daniele 29:1a47b7151851 179 }
daniele 29:1a47b7151851 180
daniele 29:1a47b7151851 181 int EthernetInterface::connect(unsigned int timeout_ms) {
tass 99:1c92cc810ecb 182 IGNORE_PARAMETER(timeout_ms);
daniele 29:1a47b7151851 183 //dhcp_mx.lock(); do we still need this ?
daniele 29:1a47b7151851 184 if (use_dhcp) {
daniele 29:1a47b7151851 185 if (pico_dhcp_initiate_negotiation(lpc_eth, &dhcp_cb, &dhcp_xid) < 0)
daniele 29:1a47b7151851 186 return -1;
daniele 29:1a47b7151851 187
tass 99:1c92cc810ecb 188 dhcp_mx.lock(); // wait for a sign
tass 99:1c92cc810ecb 189 //timeout_ms removed because rtos limit lock timeout to approximate 65 seconds.
tass 41:4c18c62b31b9 190
daniele 29:1a47b7151851 191 return dhcp_retval;
daniele 29:1a47b7151851 192
daniele 29:1a47b7151851 193 } else {
daniele 29:1a47b7151851 194 return 0;
daniele 29:1a47b7151851 195 }
daniele 29:1a47b7151851 196 }
daniele 29:1a47b7151851 197
daniele 29:1a47b7151851 198 int EthernetInterface::disconnect() {
daniele 29:1a47b7151851 199 if (use_dhcp) {
daniele 29:1a47b7151851 200 }
daniele 29:1a47b7151851 201 pico_device_destroy(lpc_eth);
daniele 29:1a47b7151851 202 lpc_eth = NULL;
daniele 29:1a47b7151851 203 return 0;
daniele 29:1a47b7151851 204 }
daniele 29:1a47b7151851 205
daniele 29:1a47b7151851 206 char* EthernetInterface::getMACAddress() {
daniele 29:1a47b7151851 207 return mac_addr;
daniele 29:1a47b7151851 208 }
daniele 29:1a47b7151851 209
daniele 29:1a47b7151851 210 char* EthernetInterface::getIPAddress() {
daniele 29:1a47b7151851 211 return ip_addr;
daniele 29:1a47b7151851 212 }
daniele 29:1a47b7151851 213
tass 127:476fed453d4d 214 char* EthernetInterface::getIPGateway() {
tass 127:476fed453d4d 215 return gw_addr;
tass 127:476fed453d4d 216 }
tass 127:476fed453d4d 217
tass 127:476fed453d4d 218 char* EthernetInterface::getIPNetmask() {
tass 127:476fed453d4d 219 return nm_addr;
tass 127:476fed453d4d 220 }
tass 127:476fed453d4d 221
daniele 29:1a47b7151851 222 int EthernetInterface::registerLinkStatus(void (*cb)(uint32_t linkStatus))
daniele 29:1a47b7151851 223 {
daniele 29:1a47b7151851 224 ::linkCb = cb;
daniele 29:1a47b7151851 225 return 0;
daniele 29:1a47b7151851 226 }
daniele 29:1a47b7151851 227
tass picotcp@tass.be 142:35da43068894 228 int EthernetInterface::setDnsServer(const char * ip)
daniele 29:1a47b7151851 229 {
tass picotcp@tass.be 142:35da43068894 230 return picotcp_dns_client_nameserver(ip, PICO_DNS_NS_ADD);
daniele 29:1a47b7151851 231 }
tass 125:96003ae6f1d8 232
tass 125:96003ae6f1d8 233 int EthernetInterface::createIpFilter(char *ipAddress, char * netmask, int port, filter_type filter)
tass 125:96003ae6f1d8 234 {
tass 125:96003ae6f1d8 235 struct pico_ip4 addr, nm, local;
tass 125:96003ae6f1d8 236 if(!ipAddress) addr.addr = 0;
tass 125:96003ae6f1d8 237 else pico_string_to_ipv4(ipAddress,&addr.addr);
tass 125:96003ae6f1d8 238
tass 125:96003ae6f1d8 239 if(!netmask) nm.addr = 0;
tass 125:96003ae6f1d8 240 else pico_string_to_ipv4(netmask,&nm.addr);
tass 125:96003ae6f1d8 241
tass 125:96003ae6f1d8 242 pico_string_to_ipv4(ip_addr,&local.addr);
tass 125:96003ae6f1d8 243
tass 125:96003ae6f1d8 244 if(filter == INPUT_FILTER)
tass 125:96003ae6f1d8 245 {
tass 125:96003ae6f1d8 246 return pico_ipv4_filter_add(NULL,PICO_PROTO_IPV4,&local,&nm,&addr,&nm,0,port,0,0,FILTER_REJECT);
tass 125:96003ae6f1d8 247 }
tass 125:96003ae6f1d8 248 else if(filter == OUTPUT_FILTER)
tass 125:96003ae6f1d8 249 {
tass 125:96003ae6f1d8 250 return pico_ipv4_filter_add(NULL,PICO_PROTO_IPV4,&addr,&nm,&local,&nm,port,0,0,0,FILTER_DROP);
tass 125:96003ae6f1d8 251 }
tass 125:96003ae6f1d8 252 else
tass 125:96003ae6f1d8 253 return -1;
tass 125:96003ae6f1d8 254 }
tass 125:96003ae6f1d8 255
tass 125:96003ae6f1d8 256 int EthernetInterface::createIpFilter(char *src, char * src_netmask, int src_port, char *dst, char * dst_netmask, int dst_port)
tass 125:96003ae6f1d8 257 {
tass 125:96003ae6f1d8 258 struct pico_ip4 src4,src_nm4,dst4,dst_nm4;
tass 125:96003ae6f1d8 259
tass 125:96003ae6f1d8 260 if(!src)
tass 125:96003ae6f1d8 261 src4.addr=0;
tass 125:96003ae6f1d8 262 else
tass 125:96003ae6f1d8 263 pico_string_to_ipv4(src,&src4.addr);
tass 125:96003ae6f1d8 264
tass 125:96003ae6f1d8 265 if(!src_netmask)
tass 125:96003ae6f1d8 266 src_nm4.addr=0;
tass 125:96003ae6f1d8 267 else
tass 125:96003ae6f1d8 268 pico_string_to_ipv4(src,&src_nm4.addr);
tass 125:96003ae6f1d8 269
tass 125:96003ae6f1d8 270 if(!dst)
tass 125:96003ae6f1d8 271 dst4.addr=0;
tass 125:96003ae6f1d8 272 else
tass 125:96003ae6f1d8 273 pico_string_to_ipv4(src,&dst4.addr);
tass 125:96003ae6f1d8 274
tass 125:96003ae6f1d8 275 if(!dst_netmask)
tass 125:96003ae6f1d8 276 dst_nm4.addr=0;
tass 125:96003ae6f1d8 277 else
tass 125:96003ae6f1d8 278 pico_string_to_ipv4(src,&dst_nm4.addr);
tass 125:96003ae6f1d8 279
tass 125:96003ae6f1d8 280 return pico_ipv4_filter_add(NULL,PICO_PROTO_IPV4,&dst4,&dst_nm4,&src4,&src_nm4,dst_port,src_port,0,0,FILTER_DROP);
tass 125:96003ae6f1d8 281 }
tass 125:96003ae6f1d8 282
tass 125:96003ae6f1d8 283 int EthernetInterface::destroyIpFilter(int filter_id)
tass 125:96003ae6f1d8 284 {
tass 125:96003ae6f1d8 285 return pico_ipv4_filter_del(filter_id);
tass picotcp@tass.be 142:35da43068894 286 }