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:
daniele
Date:
Sat Jun 15 18:38:26 2013 +0000
Revision:
26:dc3e7f96338f
Parent:
25:d63125298eb3
Child:
27:26c168f5aa97
Socket interface rewritten again

Who changed what in which revision?

UserRevisionLine numberNew contents of line
daniele 19:c7debad9a20a 1 /*********************************************************************
daniele 19:c7debad9a20a 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
daniele 19:c7debad9a20a 3 See LICENSE and COPYING for usage.
daniele 19:c7debad9a20a 4
daniele 19:c7debad9a20a 5 Authors: Daniele Lacamera
daniele 19:c7debad9a20a 6 *********************************************************************/
daniele 19:c7debad9a20a 7
daniele 19:c7debad9a20a 8 #include "wrapper.h"
daniele 19:c7debad9a20a 9 #include "rtos.h"
daniele 19:c7debad9a20a 10 #include "cmsis_os.h"
daniele 19:c7debad9a20a 11 #include "mbed.h"
daniele 19:c7debad9a20a 12 #include "Socket.h"
daniele 26:dc3e7f96338f 13 #include "Mutex.h"
daniele 19:c7debad9a20a 14
daniele 19:c7debad9a20a 15 //#define ptsock_dbg printf
daniele 19:c7debad9a20a 16 #define ptsock_dbg(...)
daniele 19:c7debad9a20a 17
daniele 19:c7debad9a20a 18 int in_the_stack = 0;
daniele 26:dc3e7f96338f 19 Mutex *PicoTcpLock;
daniele 26:dc3e7f96338f 20 Queue<void,10> *PicoTcpEvents;
daniele 19:c7debad9a20a 21
daniele 19:c7debad9a20a 22
daniele 19:c7debad9a20a 23 static Thread * serverThread = NULL;
daniele 26:dc3e7f96338f 24
daniele 26:dc3e7f96338f 25 #define pt_proxy_dbg(...)
daniele 26:dc3e7f96338f 26
daniele 26:dc3e7f96338f 27 /* Testing ng blocking mechanism */
daniele 19:c7debad9a20a 28
daniele 26:dc3e7f96338f 29 /*
daniele 26:dc3e7f96338f 30 * backend of select function, used in blocking (like picotcp_read()...)
daniele 26:dc3e7f96338f 31 * calls. Sleeps on the message queue
daniele 26:dc3e7f96338f 32 *
daniele 26:dc3e7f96338f 33 *
daniele 26:dc3e7f96338f 34 * WARNING: PicoTcpLock (big stack lock) must be acquired before entering this.
daniele 26:dc3e7f96338f 35 */
daniele 19:c7debad9a20a 36
daniele 26:dc3e7f96338f 37 static inline int __critical_select(struct stack_endpoint *ep, uint32_t time)
daniele 19:c7debad9a20a 38 {
daniele 26:dc3e7f96338f 39 int retval = 0;
daniele 26:dc3e7f96338f 40 uint16_t ev = ep->revents;
daniele 26:dc3e7f96338f 41 uint32_t in_time = PICO_TIME_MS();
daniele 26:dc3e7f96338f 42
daniele 26:dc3e7f96338f 43 PicoTcpLock->unlock();
daniele 26:dc3e7f96338f 44 while ((ep->events & ep->revents) == 0) {
daniele 26:dc3e7f96338f 45 ep->queue->get(time);
daniele 26:dc3e7f96338f 46 if ((time != osWaitForever) && (PICO_TIME_MS() > in_time + time)) {
daniele 26:dc3e7f96338f 47 printf("TIMEOUT in critical select... (ev:%04x rev:%04x \n", ep->events, ep->revents);
daniele 26:dc3e7f96338f 48 PicoTcpLock->lock();
daniele 26:dc3e7f96338f 49 return 0;
daniele 26:dc3e7f96338f 50 }
daniele 26:dc3e7f96338f 51 }
daniele 26:dc3e7f96338f 52 PicoTcpLock->lock();
daniele 26:dc3e7f96338f 53 return 1;
daniele 19:c7debad9a20a 54 }
daniele 19:c7debad9a20a 55
daniele 26:dc3e7f96338f 56 static void wakeup(uint16_t ev, struct pico_socket *s)
daniele 19:c7debad9a20a 57 {
daniele 26:dc3e7f96338f 58 struct stack_endpoint *ep = (struct stack_endpoint *)s->priv;
daniele 26:dc3e7f96338f 59 if (!ep) {
daniele 26:dc3e7f96338f 60 printf("WAKEUP: no socket :(\n");
daniele 26:dc3e7f96338f 61 return;
daniele 26:dc3e7f96338f 62 }
daniele 26:dc3e7f96338f 63 ep->revents |= ev;
daniele 19:c7debad9a20a 64
daniele 26:dc3e7f96338f 65 if ((ev & PICO_SOCK_EV_CLOSE) || (ev & PICO_SOCK_EV_FIN)) {
daniele 26:dc3e7f96338f 66 ep->connected = 0;
daniele 26:dc3e7f96338f 67 }
daniele 26:dc3e7f96338f 68 if ((ev & PICO_SOCK_EV_CONN) || (ev & PICO_SOCK_EV_RD)) {
daniele 26:dc3e7f96338f 69 ep->connected = 1;
daniele 26:dc3e7f96338f 70 }
daniele 26:dc3e7f96338f 71 ep->queue->put((void *)0);
daniele 19:c7debad9a20a 72 }
daniele 19:c7debad9a20a 73
daniele 19:c7debad9a20a 74
daniele 26:dc3e7f96338f 75 struct stack_endpoint *picotcp_socket(uint16_t net, uint16_t proto, uint16_t timeout)
daniele 19:c7debad9a20a 76 {
daniele 26:dc3e7f96338f 77 struct stack_endpoint *ep = (struct stack_endpoint *)pico_zalloc(sizeof(struct stack_endpoint));
daniele 26:dc3e7f96338f 78 uint16_t p_net = ((net == AF_INET6)?PICO_PROTO_IPV6:PICO_PROTO_IPV4);
daniele 26:dc3e7f96338f 79 uint16_t p_proto = ((proto == SOCK_DGRAM)?PICO_PROTO_UDP:PICO_PROTO_TCP);
daniele 26:dc3e7f96338f 80 PicoTcpLock->lock();
daniele 26:dc3e7f96338f 81 ep->s = pico_socket_open( p_net, p_proto, &wakeup );
daniele 26:dc3e7f96338f 82 if (ep->s == NULL) {
daniele 26:dc3e7f96338f 83 delete(ep->queue);
daniele 26:dc3e7f96338f 84 pico_free(ep);
daniele 26:dc3e7f96338f 85 ep = NULL;
daniele 26:dc3e7f96338f 86 printf("Error opening socket!\n");
daniele 26:dc3e7f96338f 87 } else {
daniele 26:dc3e7f96338f 88 ep->s->priv = ep;
daniele 26:dc3e7f96338f 89 ep->queue = new Queue<void,1>();
daniele 26:dc3e7f96338f 90 }
daniele 26:dc3e7f96338f 91 PicoTcpLock->unlock();
daniele 26:dc3e7f96338f 92 return ep;
daniele 19:c7debad9a20a 93 }
daniele 19:c7debad9a20a 94
daniele 19:c7debad9a20a 95
daniele 26:dc3e7f96338f 96 int picotcp_state(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 97 {
daniele 26:dc3e7f96338f 98 /* TODO: return one of:
daniele 26:dc3e7f96338f 99 SOCK_OPEN,
daniele 26:dc3e7f96338f 100 SOCK_BOUND,
daniele 26:dc3e7f96338f 101 SOCK_LISTEN,
daniele 26:dc3e7f96338f 102 SOCK_CONNECTED,
daniele 26:dc3e7f96338f 103 SOCK_CLOSED
daniele 26:dc3e7f96338f 104 */
daniele 26:dc3e7f96338f 105 return ep->state;
daniele 26:dc3e7f96338f 106 }
daniele 26:dc3e7f96338f 107
daniele 26:dc3e7f96338f 108 int picotcp_bind(struct stack_endpoint *ep, struct sockaddr *_local_addr, socklen_t len)
daniele 26:dc3e7f96338f 109 {
daniele 26:dc3e7f96338f 110 int ret;
daniele 26:dc3e7f96338f 111 struct sockaddr_in *local_addr;
daniele 26:dc3e7f96338f 112 local_addr = (struct sockaddr_in *)_local_addr;
daniele 26:dc3e7f96338f 113
daniele 26:dc3e7f96338f 114 PicoTcpLock->lock();
daniele 26:dc3e7f96338f 115 ret = pico_socket_bind(ep->s, (struct pico_ip4 *)(&local_addr->sin_addr.s_addr), &local_addr->sin_port);
daniele 26:dc3e7f96338f 116 PicoTcpLock->unlock();
daniele 19:c7debad9a20a 117 return ret;
daniele 19:c7debad9a20a 118 }
daniele 19:c7debad9a20a 119
daniele 26:dc3e7f96338f 120 int picotcp_listen(struct stack_endpoint *ep, int queue)
daniele 19:c7debad9a20a 121 {
daniele 26:dc3e7f96338f 122 int ret;
daniele 26:dc3e7f96338f 123 PicoTcpLock->lock();
daniele 26:dc3e7f96338f 124 ret = pico_socket_listen(ep->s, queue);
daniele 26:dc3e7f96338f 125 PicoTcpLock->unlock();
daniele 26:dc3e7f96338f 126 return ret;
daniele 19:c7debad9a20a 127 }
daniele 19:c7debad9a20a 128
daniele 26:dc3e7f96338f 129 int picotcp_connect(struct stack_endpoint *ep, struct sockaddr *_srv_addr, socklen_t len)
daniele 19:c7debad9a20a 130 {
daniele 26:dc3e7f96338f 131 int retval;
daniele 26:dc3e7f96338f 132 struct sockaddr_in *srv_addr;
daniele 26:dc3e7f96338f 133 srv_addr = (struct sockaddr_in *)_srv_addr;
daniele 26:dc3e7f96338f 134 PicoTcpLock->lock();
daniele 26:dc3e7f96338f 135 pico_socket_connect(ep->s, (struct pico_ip4 *)(&srv_addr->sin_addr.s_addr), srv_addr->sin_port);
daniele 26:dc3e7f96338f 136 ep->events = PICO_SOCK_EV_CONN | PICO_SOCK_EV_ERR;
daniele 26:dc3e7f96338f 137 __critical_select(ep, osWaitForever);
daniele 19:c7debad9a20a 138 if ((ep->revents & PICO_SOCK_EV_CONN) && ep->connected) {
daniele 19:c7debad9a20a 139 ep->revents &= (~PICO_SOCK_EV_CONN);
daniele 19:c7debad9a20a 140 ep->revents |= PICO_SOCK_EV_WR;
daniele 19:c7debad9a20a 141 ptsock_dbg("Established. sock state: %x\n", ep->s->state);
daniele 26:dc3e7f96338f 142 retval = 0;
daniele 26:dc3e7f96338f 143 } else {
daniele 26:dc3e7f96338f 144 retval = -1;
daniele 19:c7debad9a20a 145 }
daniele 26:dc3e7f96338f 146 PicoTcpLock->unlock();
daniele 26:dc3e7f96338f 147 return retval;
daniele 19:c7debad9a20a 148 }
daniele 19:c7debad9a20a 149
daniele 26:dc3e7f96338f 150 struct stack_endpoint *picotcp_accept(struct stack_endpoint *ep, struct sockaddr *_cli_addr, socklen_t *len)
daniele 19:c7debad9a20a 151 {
daniele 26:dc3e7f96338f 152 int retval;
daniele 26:dc3e7f96338f 153 struct stack_endpoint *aep = (struct stack_endpoint *) pico_zalloc(sizeof(struct stack_endpoint));
daniele 26:dc3e7f96338f 154 struct sockaddr_in *cli_addr = (struct sockaddr_in *)_cli_addr;
daniele 26:dc3e7f96338f 155 if (!aep)
daniele 26:dc3e7f96338f 156 return aep;
daniele 26:dc3e7f96338f 157 PicoTcpLock->lock();
daniele 26:dc3e7f96338f 158 ep->events = PICO_SOCK_EV_CONN | PICO_SOCK_EV_ERR;
daniele 26:dc3e7f96338f 159 __critical_select(ep, osWaitForever);
daniele 19:c7debad9a20a 160 if (ep->revents & PICO_SOCK_EV_CONN) {
daniele 26:dc3e7f96338f 161 aep->s = pico_socket_accept(ep->s, (struct pico_ip4 *)(&cli_addr->sin_addr.s_addr), &cli_addr->sin_port);
daniele 26:dc3e7f96338f 162 ep->revents &= (~PICO_SOCK_EV_CONN);
daniele 26:dc3e7f96338f 163 aep->revents |= PICO_SOCK_EV_WR;
daniele 26:dc3e7f96338f 164 aep->s->priv = aep;
daniele 26:dc3e7f96338f 165 aep->queue = new Queue<void,1>();
daniele 26:dc3e7f96338f 166 *len = sizeof(struct sockaddr_in);
daniele 26:dc3e7f96338f 167 ptsock_dbg("Established. sock state: %x\n", aep->s->state);
daniele 26:dc3e7f96338f 168 } else {
daniele 26:dc3e7f96338f 169 pico_free(aep);
daniele 26:dc3e7f96338f 170 aep = NULL;
daniele 19:c7debad9a20a 171 }
daniele 26:dc3e7f96338f 172 PicoTcpLock->unlock();
daniele 26:dc3e7f96338f 173 return aep;
daniele 19:c7debad9a20a 174 }
daniele 19:c7debad9a20a 175
daniele 26:dc3e7f96338f 176 int picotcp_select(struct stack_endpoint *ep, struct timeval *timeout, int read, int write)
daniele 19:c7debad9a20a 177 {
daniele 26:dc3e7f96338f 178 int ret;
daniele 26:dc3e7f96338f 179 ep->timeout |= timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
daniele 26:dc3e7f96338f 180 ep->events = PICO_SOCK_EV_ERR;
daniele 26:dc3e7f96338f 181 ep->events |= PICO_SOCK_EV_FIN;
daniele 26:dc3e7f96338f 182 ep->events |= PICO_SOCK_EV_CLOSE;
daniele 26:dc3e7f96338f 183 ep->events |= PICO_SOCK_EV_CONN;
daniele 26:dc3e7f96338f 184 if (read) {
daniele 26:dc3e7f96338f 185 ep->events |= PICO_SOCK_EV_RD;
daniele 19:c7debad9a20a 186 }
daniele 26:dc3e7f96338f 187 if (write)
daniele 19:c7debad9a20a 188 ep->events |= PICO_SOCK_EV_WR;
daniele 26:dc3e7f96338f 189 ret = __critical_select(ep, ep->timeout);
daniele 26:dc3e7f96338f 190 return ret;
daniele 19:c7debad9a20a 191 }
daniele 19:c7debad9a20a 192
daniele 26:dc3e7f96338f 193 int picotcp_send(struct stack_endpoint *ep,void * buff, int len, int flags)
daniele 19:c7debad9a20a 194 {
daniele 26:dc3e7f96338f 195 /* TODO */
daniele 26:dc3e7f96338f 196 return -1;
daniele 19:c7debad9a20a 197 }
daniele 19:c7debad9a20a 198
daniele 26:dc3e7f96338f 199 int picotcp_recv(struct stack_endpoint *ep,void * buff, int len, int flags)
daniele 19:c7debad9a20a 200 {
daniele 26:dc3e7f96338f 201 /* TODO */
daniele 26:dc3e7f96338f 202 return -1;
daniele 26:dc3e7f96338f 203 }
daniele 19:c7debad9a20a 204
daniele 26:dc3e7f96338f 205 int picotcp_sendto(struct stack_endpoint *ep,void * buff, int len, struct sockaddr *a, socklen_t l)
daniele 26:dc3e7f96338f 206 {
daniele 26:dc3e7f96338f 207 /* TODO */
daniele 26:dc3e7f96338f 208 return -1;
daniele 19:c7debad9a20a 209 }
daniele 19:c7debad9a20a 210
daniele 26:dc3e7f96338f 211 int picotcp_recvfrom(struct stack_endpoint *ep,void * buff, int len, struct sockaddr *a, socklen_t *l)
daniele 19:c7debad9a20a 212 {
daniele 26:dc3e7f96338f 213 /* TODO */
daniele 26:dc3e7f96338f 214 return -1;
daniele 19:c7debad9a20a 215 }
daniele 19:c7debad9a20a 216
daniele 26:dc3e7f96338f 217 int picotcp_read(struct stack_endpoint *ep,void *buf, int len)
daniele 19:c7debad9a20a 218 {
daniele 26:dc3e7f96338f 219 int retval = 0;
daniele 26:dc3e7f96338f 220 int tot_len = 0;
daniele 26:dc3e7f96338f 221 if (!buf || (len <= 0))
daniele 26:dc3e7f96338f 222 return 0;
daniele 26:dc3e7f96338f 223 PicoTcpLock->lock();
daniele 26:dc3e7f96338f 224 while (tot_len < len) {
daniele 26:dc3e7f96338f 225 retval = pico_socket_read(ep->s, ((uint8_t *)buf) + tot_len , len - tot_len);
daniele 26:dc3e7f96338f 226 if (retval <= 0) {
daniele 26:dc3e7f96338f 227 ep->revents &= ~PICO_SOCK_EV_RD;
daniele 26:dc3e7f96338f 228 break;
daniele 26:dc3e7f96338f 229 }
daniele 26:dc3e7f96338f 230 tot_len += retval;
daniele 19:c7debad9a20a 231 }
daniele 26:dc3e7f96338f 232 PicoTcpLock->unlock();
daniele 26:dc3e7f96338f 233 return tot_len;
daniele 19:c7debad9a20a 234 }
daniele 19:c7debad9a20a 235
daniele 26:dc3e7f96338f 236 int picotcp_write(struct stack_endpoint *ep,void *buf, int len)
daniele 19:c7debad9a20a 237 {
daniele 26:dc3e7f96338f 238 int retval = 0;
daniele 26:dc3e7f96338f 239 int tot_len = 0;
daniele 26:dc3e7f96338f 240 if (!buf || (len <= 0))
daniele 26:dc3e7f96338f 241 return 0;
daniele 26:dc3e7f96338f 242 PicoTcpLock->lock();
daniele 26:dc3e7f96338f 243 while (tot_len < len) {
daniele 26:dc3e7f96338f 244 retval = pico_socket_write(ep->s, ((uint8_t *)buf) + tot_len , len - tot_len);
daniele 26:dc3e7f96338f 245 if (retval <= 0) {
daniele 26:dc3e7f96338f 246 ep->revents &= ~PICO_SOCK_EV_WR;
daniele 26:dc3e7f96338f 247 break;
daniele 26:dc3e7f96338f 248 }
daniele 26:dc3e7f96338f 249 tot_len += retval;
daniele 26:dc3e7f96338f 250 picotcp_async_interrupt();
daniele 26:dc3e7f96338f 251 }
daniele 26:dc3e7f96338f 252 PicoTcpLock->unlock();
daniele 26:dc3e7f96338f 253 return tot_len;
daniele 26:dc3e7f96338f 254 }
daniele 19:c7debad9a20a 255
daniele 19:c7debad9a20a 256
daniele 26:dc3e7f96338f 257 int picotcp_setsockopt(struct stack_endpoint *ep, int option, void *value)
daniele 26:dc3e7f96338f 258 {
daniele 26:dc3e7f96338f 259 /* TODO */
daniele 26:dc3e7f96338f 260 return -1;
daniele 26:dc3e7f96338f 261 }
daniele 26:dc3e7f96338f 262
daniele 26:dc3e7f96338f 263 int picotcp_getsockopt(struct stack_endpoint *ep, int option, void *value)
daniele 26:dc3e7f96338f 264 {
daniele 26:dc3e7f96338f 265 /* TODO */
daniele 26:dc3e7f96338f 266 return -1;
daniele 26:dc3e7f96338f 267 }
daniele 19:c7debad9a20a 268
daniele 26:dc3e7f96338f 269 int picotcp_close(struct stack_endpoint *ep)
daniele 26:dc3e7f96338f 270 {
daniele 26:dc3e7f96338f 271 PicoTcpLock->lock();
daniele 26:dc3e7f96338f 272 pico_socket_close(ep->s);
daniele 26:dc3e7f96338f 273 ep->s->priv = NULL;
daniele 26:dc3e7f96338f 274 printf("Socket closed!\n");
daniele 26:dc3e7f96338f 275 delete(ep->queue);
daniele 26:dc3e7f96338f 276 pico_free(ep);
daniele 26:dc3e7f96338f 277 PicoTcpLock->unlock();
daniele 19:c7debad9a20a 278 }
daniele 19:c7debad9a20a 279
daniele 26:dc3e7f96338f 280 int picotcp_join_multicast(struct stack_endpoint *ep,const char* address,const char* local)
daniele 26:dc3e7f96338f 281 {
daniele 26:dc3e7f96338f 282 /* TODO */
daniele 26:dc3e7f96338f 283 return -1;
daniele 26:dc3e7f96338f 284 }
daniele 26:dc3e7f96338f 285
daniele 26:dc3e7f96338f 286
daniele 26:dc3e7f96338f 287
daniele 19:c7debad9a20a 288 void pico_wrapper_loop(const void * arg)
daniele 19:c7debad9a20a 289 {
daniele 19:c7debad9a20a 290 (void)arg;
daniele 19:c7debad9a20a 291 int ret = 0;
daniele 19:c7debad9a20a 292 while(1) {
daniele 26:dc3e7f96338f 293 PicoTcpEvents->get(2);
daniele 26:dc3e7f96338f 294 if (PicoTcpLock->trylock()) {
daniele 26:dc3e7f96338f 295 pico_stack_tick();
daniele 26:dc3e7f96338f 296 PicoTcpLock->unlock();
daniele 26:dc3e7f96338f 297 }
daniele 19:c7debad9a20a 298 }
daniele 19:c7debad9a20a 299 }
daniele 19:c7debad9a20a 300
daniele 19:c7debad9a20a 301 void picotcp_start(void)
daniele 19:c7debad9a20a 302 {
daniele 19:c7debad9a20a 303 if (serverThread == NULL) {
daniele 26:dc3e7f96338f 304 PicoTcpLock = new Mutex();
daniele 26:dc3e7f96338f 305 PicoTcpEvents = new Queue<void,10>();
daniele 19:c7debad9a20a 306 printf (" *** PicoTCP initialized *** \n");
daniele 19:c7debad9a20a 307 serverThread = new Thread(pico_wrapper_loop);
daniele 19:c7debad9a20a 308 serverThread->set_priority(osPriorityIdle);
daniele 19:c7debad9a20a 309 }
daniele 19:c7debad9a20a 310 }
daniele 26:dc3e7f96338f 311
daniele 26:dc3e7f96338f 312 void picotcp_init(void)
daniele 26:dc3e7f96338f 313 {
daniele 26:dc3e7f96338f 314 picotcp_start();
daniele 26:dc3e7f96338f 315 }
daniele 26:dc3e7f96338f 316
daniele 26:dc3e7f96338f 317 int picotcp_async_interrupt(void)
daniele 26:dc3e7f96338f 318 {
daniele 26:dc3e7f96338f 319 PicoTcpEvents->put((void *)0);
daniele 26:dc3e7f96338f 320 }