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:
Wed Jul 03 08:56:01 2013 +0000
Revision:
37:bdf736327c71
Parent:
35:6078073547bb
Child:
38:b71e5dd1806a
Added DNS calls to stack interface.; Integrated the DNS feature in Endpoint.; Fixed incomplete data receiving.;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
daniele 29:1a47b7151851 1 /*********************************************************************
daniele 29:1a47b7151851 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
daniele 29:1a47b7151851 3 See LICENSE and COPYING for usage.
daniele 29:1a47b7151851 4
daniele 29:1a47b7151851 5 Authors: Daniele Lacamera
daniele 29:1a47b7151851 6 *********************************************************************/
daniele 29:1a47b7151851 7
daniele 29:1a47b7151851 8 #include "wrapper.h"
daniele 29:1a47b7151851 9 #include "rtos.h"
daniele 29:1a47b7151851 10 #include "cmsis_os.h"
daniele 29:1a47b7151851 11 #include "mbed.h"
daniele 29:1a47b7151851 12 #include "Socket.h"
daniele 29:1a47b7151851 13 #include "Mutex.h"
daniele 29:1a47b7151851 14
tass 37:bdf736327c71 15 extern "C"
tass 37:bdf736327c71 16 {
tass 37:bdf736327c71 17 #include "pico_dns_client.h"
tass 37:bdf736327c71 18 }
tass 37:bdf736327c71 19
daniele 29:1a47b7151851 20 //#define ptsock_dbg printf
daniele 29:1a47b7151851 21 #define ptsock_dbg(...)
daniele 29:1a47b7151851 22
daniele 29:1a47b7151851 23 int in_the_stack = 0;
daniele 29:1a47b7151851 24 Mutex *PicoTcpLock;
tass 37:bdf736327c71 25 Queue<void,32> *PicoTcpEvents;
daniele 29:1a47b7151851 26
daniele 29:1a47b7151851 27 static struct stack_endpoint *ep_accepting;
daniele 29:1a47b7151851 28 static Thread * serverThread = NULL;
daniele 29:1a47b7151851 29
daniele 29:1a47b7151851 30 #define pt_proxy_dbg(...)
daniele 29:1a47b7151851 31
daniele 29:1a47b7151851 32 /* Testing ng blocking mechanism */
daniele 29:1a47b7151851 33
daniele 29:1a47b7151851 34 /*
daniele 29:1a47b7151851 35 * backend of select function, used in blocking (like picotcp_read()...)
daniele 29:1a47b7151851 36 * calls. Sleeps on the message queue
daniele 29:1a47b7151851 37 *
daniele 29:1a47b7151851 38 *
daniele 29:1a47b7151851 39 * WARNING: PicoTcpLock (big stack lock) must be acquired before entering this.
daniele 29:1a47b7151851 40 */
daniele 29:1a47b7151851 41
tass 32:865c101e0874 42 static inline int __critical_select(struct stack_endpoint *ep, uint32_t time, uint8_t lock)
daniele 29:1a47b7151851 43 {
daniele 29:1a47b7151851 44 int retval = 0;
daniele 29:1a47b7151851 45 uint16_t ev = ep->revents;
daniele 29:1a47b7151851 46 uint32_t in_time = PICO_TIME_MS();
daniele 29:1a47b7151851 47
tass 32:865c101e0874 48 if(lock) PicoTcpLock->unlock();
daniele 29:1a47b7151851 49 while ((ep->events & ep->revents) == 0) {
daniele 29:1a47b7151851 50 ep->queue->get(time);
daniele 29:1a47b7151851 51 if ((time != osWaitForever) && (PICO_TIME_MS() > in_time + time)) {
daniele 29:1a47b7151851 52 printf("TIMEOUT in critical select... (ev:%04x rev:%04x \n", ep->events, ep->revents);
tass 32:865c101e0874 53 if(lock) PicoTcpLock->lock();
daniele 29:1a47b7151851 54 return 0;
daniele 29:1a47b7151851 55 }
daniele 29:1a47b7151851 56 }
tass 32:865c101e0874 57 if(lock) PicoTcpLock->lock();
daniele 29:1a47b7151851 58 return 1;
daniele 29:1a47b7151851 59 }
daniele 29:1a47b7151851 60
daniele 29:1a47b7151851 61 static void wakeup(uint16_t ev, struct pico_socket *s)
daniele 29:1a47b7151851 62 {
daniele 29:1a47b7151851 63 struct stack_endpoint *ep = (struct stack_endpoint *)s->priv;
daniele 29:1a47b7151851 64 if (!ep) {
daniele 29:1a47b7151851 65 if (ep_accepting != NULL) {
daniele 34:d868bb69114e 66 //printf("Delivering %02x to accepting socket...\n", ev);
daniele 29:1a47b7151851 67 ep = ep_accepting;
daniele 29:1a47b7151851 68 } else {
daniele 29:1a47b7151851 69 printf("WAKEUP: socket not found! ev=%04x\n", ev);
daniele 29:1a47b7151851 70 return;
daniele 29:1a47b7151851 71 }
daniele 29:1a47b7151851 72 }
daniele 29:1a47b7151851 73 //if (((ep->revents & PICO_SOCK_EV_RD) == 0) && (ev & PICO_SOCK_EV_RD))
daniele 29:1a47b7151851 74 // printf("Activating RD\n");
daniele 29:1a47b7151851 75 ep->revents |= ev;
daniele 29:1a47b7151851 76
tass 32:865c101e0874 77 if(ev & PICO_SOCK_EV_ERR)
tass 32:865c101e0874 78 {
tass 32:865c101e0874 79 if(pico_err == PICO_ERR_ECONNRESET)
tass 32:865c101e0874 80 {
tass 32:865c101e0874 81 printf("Connection reset by peer...\n");
tass 32:865c101e0874 82 ep->state = SOCK_RESET_BY_PEER;
tass 32:865c101e0874 83 pico_socket_close(ep->s);
tass 32:865c101e0874 84 ep->s->priv = NULL;
tass 32:865c101e0874 85 }
tass 32:865c101e0874 86 }
daniele 29:1a47b7151851 87 if ((ev & PICO_SOCK_EV_CLOSE) || (ev & PICO_SOCK_EV_FIN)) {
daniele 29:1a47b7151851 88 ep->connected = 0;
tass 37:bdf736327c71 89 pico_socket_close(ep->s);
tass 35:6078073547bb 90 ep->state = SOCK_CLOSED;
daniele 29:1a47b7151851 91 }
daniele 29:1a47b7151851 92 if ((ev & PICO_SOCK_EV_CONN) || (ev & PICO_SOCK_EV_RD)) {
daniele 29:1a47b7151851 93 ep->connected = 1;
tass 35:6078073547bb 94 ep->state = SOCK_CONNECTED;
daniele 29:1a47b7151851 95 }
daniele 29:1a47b7151851 96 ep->queue->put((void *)0);
daniele 29:1a47b7151851 97 }
daniele 29:1a47b7151851 98
daniele 29:1a47b7151851 99
daniele 29:1a47b7151851 100 struct stack_endpoint *picotcp_socket(uint16_t net, uint16_t proto, uint16_t timeout)
daniele 29:1a47b7151851 101 {
daniele 29:1a47b7151851 102 struct stack_endpoint *ep = (struct stack_endpoint *)pico_zalloc(sizeof(struct stack_endpoint));
daniele 29:1a47b7151851 103 uint16_t p_net = ((net == AF_INET6)?PICO_PROTO_IPV6:PICO_PROTO_IPV4);
daniele 29:1a47b7151851 104 uint16_t p_proto = ((proto == SOCK_DGRAM)?PICO_PROTO_UDP:PICO_PROTO_TCP);
daniele 29:1a47b7151851 105 PicoTcpLock->lock();
daniele 29:1a47b7151851 106 ep->s = pico_socket_open( p_net, p_proto, &wakeup );
daniele 29:1a47b7151851 107 if (ep->s == NULL) {
daniele 29:1a47b7151851 108 delete(ep->queue);
daniele 29:1a47b7151851 109 pico_free(ep);
daniele 29:1a47b7151851 110 ep = NULL;
daniele 29:1a47b7151851 111 printf("Error opening socket!\n");
daniele 29:1a47b7151851 112 } else {
daniele 29:1a47b7151851 113 ep->s->priv = ep;
daniele 29:1a47b7151851 114 printf("Added socket (open)\n");
tass 35:6078073547bb 115 ep->state = SOCK_OPEN;
daniele 29:1a47b7151851 116 ep->queue = new Queue<void,1>();
daniele 29:1a47b7151851 117 }
daniele 29:1a47b7151851 118 PicoTcpLock->unlock();
daniele 29:1a47b7151851 119 return ep;
daniele 29:1a47b7151851 120 }
daniele 29:1a47b7151851 121
daniele 29:1a47b7151851 122
daniele 29:1a47b7151851 123 int picotcp_state(struct stack_endpoint *ep)
daniele 29:1a47b7151851 124 {
daniele 29:1a47b7151851 125 return ep->state;
daniele 29:1a47b7151851 126 }
daniele 29:1a47b7151851 127
daniele 29:1a47b7151851 128 int picotcp_bind(struct stack_endpoint *ep, struct sockaddr *_local_addr, socklen_t len)
daniele 29:1a47b7151851 129 {
daniele 29:1a47b7151851 130 int ret;
daniele 29:1a47b7151851 131 struct sockaddr_in *local_addr;
daniele 29:1a47b7151851 132 local_addr = (struct sockaddr_in *)_local_addr;
daniele 29:1a47b7151851 133
daniele 29:1a47b7151851 134 PicoTcpLock->lock();
daniele 29:1a47b7151851 135 ret = pico_socket_bind(ep->s, (struct pico_ip4 *)(&local_addr->sin_addr.s_addr), &local_addr->sin_port);
tass 35:6078073547bb 136 if(ret == 0)
tass 35:6078073547bb 137 ep->state = SOCK_BOUND;
daniele 29:1a47b7151851 138 PicoTcpLock->unlock();
daniele 29:1a47b7151851 139 return ret;
daniele 29:1a47b7151851 140 }
daniele 29:1a47b7151851 141
daniele 29:1a47b7151851 142 int picotcp_listen(struct stack_endpoint *ep, int queue)
daniele 29:1a47b7151851 143 {
daniele 29:1a47b7151851 144 int ret;
daniele 29:1a47b7151851 145 PicoTcpLock->lock();
daniele 29:1a47b7151851 146 ret = pico_socket_listen(ep->s, queue);
daniele 29:1a47b7151851 147 ep_accepting = (struct stack_endpoint *) pico_zalloc(sizeof(struct stack_endpoint));
daniele 29:1a47b7151851 148 ep_accepting->queue = new Queue<void,1>();
daniele 29:1a47b7151851 149 if (!ep_accepting)
daniele 29:1a47b7151851 150 ret = -1;
tass 35:6078073547bb 151 if(ret == 0)
tass 35:6078073547bb 152 ep->state = SOCK_LISTEN;
daniele 29:1a47b7151851 153 PicoTcpLock->unlock();
daniele 29:1a47b7151851 154 return ret;
daniele 29:1a47b7151851 155 }
daniele 29:1a47b7151851 156
daniele 29:1a47b7151851 157 int picotcp_connect(struct stack_endpoint *ep, struct sockaddr *_srv_addr, socklen_t len)
daniele 29:1a47b7151851 158 {
daniele 29:1a47b7151851 159 int retval;
daniele 29:1a47b7151851 160 struct sockaddr_in *srv_addr;
daniele 29:1a47b7151851 161 srv_addr = (struct sockaddr_in *)_srv_addr;
daniele 29:1a47b7151851 162 PicoTcpLock->lock();
daniele 29:1a47b7151851 163 pico_socket_connect(ep->s, (struct pico_ip4 *)(&srv_addr->sin_addr.s_addr), srv_addr->sin_port);
daniele 29:1a47b7151851 164 ep->events = PICO_SOCK_EV_CONN | PICO_SOCK_EV_ERR;
daniele 33:d8af3f85a484 165 __critical_select(ep, osWaitForever, 1);
daniele 29:1a47b7151851 166 if ((ep->revents & PICO_SOCK_EV_CONN) && ep->connected) {
daniele 29:1a47b7151851 167 ep->revents &= (~PICO_SOCK_EV_CONN);
daniele 29:1a47b7151851 168 ep->revents |= PICO_SOCK_EV_WR;
daniele 29:1a47b7151851 169 ptsock_dbg("Established. sock state: %x\n", ep->s->state);
tass 35:6078073547bb 170 ep->state = SOCK_CONNECTED;
daniele 29:1a47b7151851 171 retval = 0;
daniele 29:1a47b7151851 172 } else {
daniele 29:1a47b7151851 173 retval = -1;
daniele 29:1a47b7151851 174 }
daniele 29:1a47b7151851 175 PicoTcpLock->unlock();
daniele 29:1a47b7151851 176 return retval;
daniele 29:1a47b7151851 177 }
daniele 29:1a47b7151851 178
daniele 29:1a47b7151851 179 struct stack_endpoint *picotcp_accept(struct stack_endpoint *ep, struct sockaddr *_cli_addr, socklen_t *len)
daniele 29:1a47b7151851 180 {
daniele 29:1a47b7151851 181 int retval;
daniele 29:1a47b7151851 182 struct stack_endpoint *aep = ep_accepting;
daniele 29:1a47b7151851 183 struct sockaddr_in *cli_addr = (struct sockaddr_in *)_cli_addr;
daniele 29:1a47b7151851 184 ep_accepting = (struct stack_endpoint *) pico_zalloc(sizeof(struct stack_endpoint));
daniele 29:1a47b7151851 185 if (ep_accepting)
daniele 29:1a47b7151851 186 ep_accepting->queue = new Queue<void,1>();
daniele 29:1a47b7151851 187
daniele 29:1a47b7151851 188
daniele 29:1a47b7151851 189 if (!aep)
daniele 29:1a47b7151851 190 return aep;
daniele 29:1a47b7151851 191
daniele 29:1a47b7151851 192 PicoTcpLock->lock();
daniele 29:1a47b7151851 193 ep->events = PICO_SOCK_EV_CONN | PICO_SOCK_EV_ERR;
daniele 33:d8af3f85a484 194 __critical_select(ep, osWaitForever, 1);
daniele 29:1a47b7151851 195 if (ep->revents & PICO_SOCK_EV_CONN) {
daniele 29:1a47b7151851 196 printf("Calling Accept\n");
daniele 29:1a47b7151851 197 aep->s = pico_socket_accept(ep->s, (struct pico_ip4 *)(&cli_addr->sin_addr.s_addr), &cli_addr->sin_port);
daniele 29:1a47b7151851 198 printf("Accept returned\n");
daniele 29:1a47b7151851 199 aep->s->priv = aep;
daniele 29:1a47b7151851 200 ep->revents &= (~PICO_SOCK_EV_CONN);
tass 32:865c101e0874 201 aep->revents = 0; // set this to 0 to allow seq connections
daniele 29:1a47b7151851 202 aep->revents |= PICO_SOCK_EV_WR;
tass 35:6078073547bb 203 aep->state = SOCK_CONNECTED;
daniele 29:1a47b7151851 204 printf("Added socket (accept)\n");
daniele 29:1a47b7151851 205
daniele 29:1a47b7151851 206 *len = sizeof(struct sockaddr_in);
daniele 29:1a47b7151851 207 ptsock_dbg("Established. sock state: %x\n", aep->s->state);
daniele 29:1a47b7151851 208 } else {
daniele 29:1a47b7151851 209 pico_free(aep);
daniele 29:1a47b7151851 210 aep = NULL;
daniele 29:1a47b7151851 211 }
daniele 29:1a47b7151851 212 PicoTcpLock->unlock();
daniele 29:1a47b7151851 213 return aep;
daniele 29:1a47b7151851 214 }
daniele 29:1a47b7151851 215
daniele 29:1a47b7151851 216 int picotcp_select(struct stack_endpoint *ep, struct timeval *timeout, int read, int write)
daniele 29:1a47b7151851 217 {
daniele 29:1a47b7151851 218 int ret;
daniele 29:1a47b7151851 219 ep->timeout |= timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
daniele 29:1a47b7151851 220 ep->events = PICO_SOCK_EV_ERR;
daniele 29:1a47b7151851 221 ep->events |= PICO_SOCK_EV_FIN;
daniele 29:1a47b7151851 222 ep->events |= PICO_SOCK_EV_CLOSE;
daniele 29:1a47b7151851 223 ep->events |= PICO_SOCK_EV_CONN;
daniele 29:1a47b7151851 224 if (read) {
daniele 29:1a47b7151851 225 ep->events |= PICO_SOCK_EV_RD;
daniele 29:1a47b7151851 226 }
daniele 29:1a47b7151851 227 if (write)
daniele 29:1a47b7151851 228 ep->events |= PICO_SOCK_EV_WR;
daniele 33:d8af3f85a484 229 ret = __critical_select(ep, ep->timeout, 0);
daniele 29:1a47b7151851 230 return ret;
daniele 29:1a47b7151851 231 }
daniele 29:1a47b7151851 232
tass 35:6078073547bb 233 int picotcp_send(struct stack_endpoint *ep,void * buf, int len, int flags)
daniele 29:1a47b7151851 234 {
tass 35:6078073547bb 235 int retval = 0;
tass 35:6078073547bb 236 int tot_len = 0;
tass 35:6078073547bb 237 if (!buf || (len <= 0))
tass 35:6078073547bb 238 return 0;
tass 35:6078073547bb 239 PicoTcpLock->lock();
tass 35:6078073547bb 240 while (tot_len < len) {
tass 35:6078073547bb 241 retval = pico_socket_send(ep->s, ((uint8_t *)buf) + tot_len , len - tot_len);
tass 35:6078073547bb 242 if (retval == 0) {
tass 35:6078073547bb 243 if (tot_len < len)
tass 35:6078073547bb 244 ep->revents &= ~PICO_SOCK_EV_WR;
tass 35:6078073547bb 245 break;
tass 35:6078073547bb 246 }
tass 35:6078073547bb 247 if (retval < 0) {
tass 35:6078073547bb 248 tot_len = -1;
tass 35:6078073547bb 249 break;
tass 35:6078073547bb 250 }
tass 35:6078073547bb 251 tot_len += retval;
tass 35:6078073547bb 252 }
tass 35:6078073547bb 253 PicoTcpLock->unlock();
tass 35:6078073547bb 254 picotcp_async_interrupt(NULL);
tass 35:6078073547bb 255 return tot_len;
tass 35:6078073547bb 256 }
tass 35:6078073547bb 257
tass 35:6078073547bb 258 int picotcp_recv(struct stack_endpoint *ep,void * buf, int len, int flags)
tass 35:6078073547bb 259 {
tass 35:6078073547bb 260 int retval = 0;
tass 35:6078073547bb 261 int tot_len = 0;
tass 35:6078073547bb 262 if (!buf || (len <= 0))
tass 35:6078073547bb 263 return 0;
tass 35:6078073547bb 264 PicoTcpLock->lock();
tass 35:6078073547bb 265 while (tot_len < len) {
tass 35:6078073547bb 266 retval = pico_socket_recv(ep->s, ((uint8_t *)buf) + tot_len , len - tot_len);
tass 35:6078073547bb 267 if (retval == 0) {
tass 35:6078073547bb 268 if (tot_len < len)
tass 35:6078073547bb 269 ep->revents &= ~PICO_SOCK_EV_RD;
tass 35:6078073547bb 270 break;
tass 35:6078073547bb 271 }
tass 35:6078073547bb 272 if (retval < 0) {
tass 37:bdf736327c71 273 if(tot_len == 0) tot_len = -1;
tass 35:6078073547bb 274 break;
tass 35:6078073547bb 275 }
tass 35:6078073547bb 276 tot_len += retval;
tass 35:6078073547bb 277 }
tass 35:6078073547bb 278 PicoTcpLock->unlock();
tass 35:6078073547bb 279 picotcp_async_interrupt(NULL);
tass 35:6078073547bb 280 return tot_len;
daniele 29:1a47b7151851 281 }
daniele 29:1a47b7151851 282
tass 35:6078073547bb 283 int picotcp_sendto(struct stack_endpoint * ep,void * buf, int len, struct sockaddr* a,socklen_t size)
daniele 29:1a47b7151851 284 {
tass 35:6078073547bb 285 int retval = 0;
tass 35:6078073547bb 286 int tot_len = 0;
tass 35:6078073547bb 287 struct sockaddr_in * in = (struct sockaddr_in *)a;
tass 35:6078073547bb 288 if (!buf || (len <= 0))
tass 35:6078073547bb 289 return 0;
tass 35:6078073547bb 290 if(!ep->broadcast && pico_ipv4_is_broadcast(in->sin_addr.s_addr))
tass 35:6078073547bb 291 return -1;
tass 35:6078073547bb 292
tass 35:6078073547bb 293 PicoTcpLock->lock();
tass 35:6078073547bb 294 while (tot_len < len) {
tass 35:6078073547bb 295 retval = pico_socket_sendto(ep->s, ((uint8_t *)buf) + tot_len , len - tot_len,(struct pico_ip4 *)&in->sin_addr.s_addr, in->sin_port);
tass 35:6078073547bb 296
tass 35:6078073547bb 297 if (retval == 0)
tass 35:6078073547bb 298 break;
tass 35:6078073547bb 299
tass 35:6078073547bb 300 if (retval < 0) {
tass 35:6078073547bb 301 tot_len = -1;
tass 35:6078073547bb 302 break;
tass 35:6078073547bb 303 }
tass 35:6078073547bb 304 tot_len += retval;
tass 35:6078073547bb 305 }
tass 35:6078073547bb 306 PicoTcpLock->unlock();
tass 35:6078073547bb 307 picotcp_async_interrupt(NULL);
tass 35:6078073547bb 308 return tot_len;
daniele 29:1a47b7151851 309 }
daniele 29:1a47b7151851 310
tass 35:6078073547bb 311 int picotcp_recvfrom(struct stack_endpoint *ep,void * buf, int len, struct sockaddr *a, socklen_t * size)
daniele 29:1a47b7151851 312 {
tass 35:6078073547bb 313 (void)len;
tass 35:6078073547bb 314 int retval = 0;
tass 35:6078073547bb 315 int tot_len = 0;
tass 35:6078073547bb 316 struct sockaddr_in * in = (struct sockaddr_in *)a;
tass 35:6078073547bb 317 if (!buf || (len <= 0))
tass 35:6078073547bb 318 return 0;
tass 35:6078073547bb 319 PicoTcpLock->lock();
tass 35:6078073547bb 320 while (tot_len < len) {
tass 35:6078073547bb 321 retval = pico_socket_recvfrom(ep->s, ((uint8_t *)buf) + tot_len , len - tot_len,(struct pico_ip4 *)&(in->sin_addr.s_addr),&in->sin_port);
tass 35:6078073547bb 322 if (retval == 0) {
tass 35:6078073547bb 323 if (tot_len < len)
tass 35:6078073547bb 324 ep->revents &= ~PICO_SOCK_EV_RD;
tass 35:6078073547bb 325 break;
tass 35:6078073547bb 326 }
tass 35:6078073547bb 327 if (retval < 0) {
tass 37:bdf736327c71 328 if(tot_len == 0) tot_len = -1;
tass 35:6078073547bb 329 break;
tass 35:6078073547bb 330 }
tass 35:6078073547bb 331 tot_len += retval;
tass 35:6078073547bb 332 }
tass 35:6078073547bb 333 PicoTcpLock->unlock();
tass 35:6078073547bb 334 picotcp_async_interrupt(NULL);
tass 35:6078073547bb 335 return tot_len;
daniele 29:1a47b7151851 336 }
daniele 29:1a47b7151851 337
daniele 29:1a47b7151851 338 int picotcp_read(struct stack_endpoint *ep,void *buf, int len)
daniele 29:1a47b7151851 339 {
daniele 29:1a47b7151851 340 int retval = 0;
daniele 29:1a47b7151851 341 int tot_len = 0;
daniele 29:1a47b7151851 342 if (!buf || (len <= 0))
daniele 29:1a47b7151851 343 return 0;
daniele 29:1a47b7151851 344 PicoTcpLock->lock();
daniele 29:1a47b7151851 345 while (tot_len < len) {
daniele 29:1a47b7151851 346 retval = pico_socket_read(ep->s, ((uint8_t *)buf) + tot_len , len - tot_len);
daniele 29:1a47b7151851 347 if (retval == 0) {
daniele 29:1a47b7151851 348 if (tot_len < len)
daniele 29:1a47b7151851 349 ep->revents &= ~PICO_SOCK_EV_RD;
daniele 29:1a47b7151851 350 break;
daniele 29:1a47b7151851 351 }
daniele 29:1a47b7151851 352 if (retval < 0) {
tass 37:bdf736327c71 353 if(tot_len == 0) tot_len = -1;
daniele 29:1a47b7151851 354 break;
daniele 29:1a47b7151851 355 }
daniele 29:1a47b7151851 356 tot_len += retval;
daniele 29:1a47b7151851 357 }
daniele 29:1a47b7151851 358 PicoTcpLock->unlock();
daniele 29:1a47b7151851 359 picotcp_async_interrupt(NULL);
daniele 29:1a47b7151851 360 return tot_len;
daniele 29:1a47b7151851 361 }
daniele 29:1a47b7151851 362
daniele 29:1a47b7151851 363 int picotcp_write(struct stack_endpoint *ep,void *buf, int len)
daniele 29:1a47b7151851 364 {
daniele 29:1a47b7151851 365 int retval = 0;
daniele 29:1a47b7151851 366 int tot_len = 0;
daniele 29:1a47b7151851 367 if (!buf || (len <= 0))
daniele 29:1a47b7151851 368 return 0;
daniele 29:1a47b7151851 369 PicoTcpLock->lock();
daniele 29:1a47b7151851 370 while (tot_len < len) {
daniele 29:1a47b7151851 371 retval = pico_socket_write(ep->s, ((uint8_t *)buf) + tot_len , len - tot_len);
tass 35:6078073547bb 372 //retval = pico_socket_read(ep->s, ((uint8_t *)buf) + tot_len , len - tot_len);
daniele 29:1a47b7151851 373 if (retval == 0) {
daniele 29:1a47b7151851 374 if (tot_len < len)
tass 35:6078073547bb 375 ep->revents &= ~PICO_SOCK_EV_WR;
daniele 29:1a47b7151851 376 break;
daniele 29:1a47b7151851 377 }
daniele 29:1a47b7151851 378 if (retval < 0) {
daniele 29:1a47b7151851 379 tot_len = -1;
daniele 29:1a47b7151851 380 break;
daniele 29:1a47b7151851 381 }
daniele 29:1a47b7151851 382 tot_len += retval;
daniele 29:1a47b7151851 383 }
daniele 29:1a47b7151851 384 PicoTcpLock->unlock();
daniele 29:1a47b7151851 385 picotcp_async_interrupt(NULL);
daniele 29:1a47b7151851 386 return tot_len;
daniele 29:1a47b7151851 387 }
daniele 29:1a47b7151851 388
daniele 29:1a47b7151851 389
daniele 29:1a47b7151851 390 int picotcp_setsockopt(struct stack_endpoint *ep, int option, void *value)
daniele 29:1a47b7151851 391 {
tass 35:6078073547bb 392 int ret;
tass 35:6078073547bb 393
tass 35:6078073547bb 394 PicoTcpLock->lock();
tass 35:6078073547bb 395 if(option == SO_BROADCAST)
tass 35:6078073547bb 396 {
tass 35:6078073547bb 397 ep->broadcast = *(int *)value;
tass 35:6078073547bb 398 ret = 0;
tass 35:6078073547bb 399 }
tass 35:6078073547bb 400 else
tass 35:6078073547bb 401 ret = pico_socket_setoption(ep->s,option,value);
tass 35:6078073547bb 402 PicoTcpLock->unlock();
tass 35:6078073547bb 403
tass 35:6078073547bb 404 return ret;
daniele 29:1a47b7151851 405 }
daniele 29:1a47b7151851 406
daniele 29:1a47b7151851 407 int picotcp_getsockopt(struct stack_endpoint *ep, int option, void *value)
daniele 29:1a47b7151851 408 {
tass 35:6078073547bb 409 int ret;
tass 35:6078073547bb 410
tass 35:6078073547bb 411 PicoTcpLock->lock();
tass 35:6078073547bb 412 ret = pico_socket_getoption(ep->s,option,value);
tass 35:6078073547bb 413 PicoTcpLock->unlock();
tass 35:6078073547bb 414
tass 35:6078073547bb 415 return ret;
daniele 29:1a47b7151851 416 }
daniele 29:1a47b7151851 417
daniele 29:1a47b7151851 418 int picotcp_close(struct stack_endpoint *ep)
daniele 29:1a47b7151851 419 {
daniele 29:1a47b7151851 420 PicoTcpLock->lock();
tass 32:865c101e0874 421 if(ep->state != SOCK_RESET_BY_PEER)
tass 32:865c101e0874 422 {
tass 32:865c101e0874 423 pico_socket_close(ep->s);
tass 32:865c101e0874 424 ep->s->priv = NULL;
tass 32:865c101e0874 425 }
daniele 29:1a47b7151851 426 printf("Socket closed!\n");
daniele 29:1a47b7151851 427 delete(ep->queue);
daniele 29:1a47b7151851 428 pico_free(ep);
daniele 29:1a47b7151851 429 PicoTcpLock->unlock();
daniele 29:1a47b7151851 430 }
daniele 29:1a47b7151851 431
daniele 29:1a47b7151851 432 int picotcp_join_multicast(struct stack_endpoint *ep,const char* address,const char* local)
daniele 29:1a47b7151851 433 {
tass 35:6078073547bb 434 int ret;
tass 35:6078073547bb 435 struct pico_ip_mreq mreq={};
tass 35:6078073547bb 436
tass 35:6078073547bb 437 PicoTcpLock->lock();
tass 35:6078073547bb 438 pico_string_to_ipv4(address,&mreq.mcast_group_addr.addr);
tass 35:6078073547bb 439 pico_string_to_ipv4(local,&mreq.mcast_link_addr.addr);
tass 35:6078073547bb 440 ret = pico_socket_setoption(ep->s, PICO_IP_ADD_MEMBERSHIP, &mreq);
tass 35:6078073547bb 441 PicoTcpLock->unlock();
tass 35:6078073547bb 442
tass 35:6078073547bb 443 return ret;
daniele 29:1a47b7151851 444 }
daniele 29:1a47b7151851 445
daniele 29:1a47b7151851 446
daniele 29:1a47b7151851 447
daniele 29:1a47b7151851 448 void pico_wrapper_loop(const void * arg)
daniele 29:1a47b7151851 449 {
daniele 29:1a47b7151851 450 (void)arg;
daniele 29:1a47b7151851 451 int ret = 0;
daniele 29:1a47b7151851 452 struct pico_device *dev;
daniele 29:1a47b7151851 453 while(1) {
daniele 29:1a47b7151851 454
daniele 29:1a47b7151851 455 osEvent evt = PicoTcpEvents->get(5);
daniele 29:1a47b7151851 456
daniele 29:1a47b7151851 457 if (evt.status == osEventMessage) {
daniele 29:1a47b7151851 458 dev = (struct pico_device *)evt.value.p;
daniele 29:1a47b7151851 459 } else {
daniele 29:1a47b7151851 460 dev = NULL;
daniele 29:1a47b7151851 461 }
daniele 29:1a47b7151851 462 PicoTcpLock->lock();
daniele 29:1a47b7151851 463 if (dev && dev->dsr)
daniele 29:1a47b7151851 464 dev->dsr(dev, 5);
daniele 29:1a47b7151851 465 pico_stack_tick();
daniele 29:1a47b7151851 466 pico_stack_tick();
daniele 29:1a47b7151851 467 PicoTcpLock->unlock();
daniele 29:1a47b7151851 468 }
daniele 29:1a47b7151851 469 }
daniele 29:1a47b7151851 470
daniele 29:1a47b7151851 471 void picotcp_start(void)
daniele 29:1a47b7151851 472 {
daniele 29:1a47b7151851 473 if (serverThread == NULL) {
daniele 29:1a47b7151851 474 PicoTcpLock = new Mutex();
tass 37:bdf736327c71 475 PicoTcpEvents = new Queue<void,32>();
daniele 29:1a47b7151851 476 printf (" *** PicoTCP initialized *** \n");
daniele 29:1a47b7151851 477 serverThread = new Thread(pico_wrapper_loop);
daniele 29:1a47b7151851 478 serverThread->set_priority(osPriorityIdle);
daniele 29:1a47b7151851 479 }
daniele 29:1a47b7151851 480 }
daniele 29:1a47b7151851 481
daniele 29:1a47b7151851 482 void picotcp_init(void)
daniele 29:1a47b7151851 483 {
daniele 29:1a47b7151851 484 picotcp_start();
daniele 29:1a47b7151851 485 }
daniele 29:1a47b7151851 486
daniele 29:1a47b7151851 487 int picotcp_async_interrupt(void *arg)
daniele 29:1a47b7151851 488 {
daniele 29:1a47b7151851 489 PicoTcpEvents->put(arg);
daniele 29:1a47b7151851 490 }
tass 37:bdf736327c71 491
tass 37:bdf736327c71 492 // *************** DNS part ***************
tass 37:bdf736327c71 493 void dns_cb(char *ip,void *arg)
tass 37:bdf736327c71 494 {
tass 37:bdf736327c71 495 if(!arg)
tass 37:bdf736327c71 496 goto fail;
tass 37:bdf736327c71 497 // send the result back
tass 37:bdf736327c71 498 ((Queue<void,1> *)arg)->put((void *)ip);
tass 37:bdf736327c71 499 fail:
tass 37:bdf736327c71 500 if(ip) free(ip);
tass 37:bdf736327c71 501 }
tass 37:bdf736327c71 502
tass 37:bdf736327c71 503 // dns get host
tass 37:bdf736327c71 504 struct hostent *picotcp_gethostbyname(const char *name)
tass 37:bdf736327c71 505 {
tass 37:bdf736327c71 506 Queue<void,1> *dnsResult = new Queue<void,1>();
tass 37:bdf736327c71 507 struct hostent * hostdata = NULL;
tass 37:bdf736327c71 508 char *ip;
tass 37:bdf736327c71 509
tass 37:bdf736327c71 510 if(!dnsResult)
tass 37:bdf736327c71 511 return NULL;
tass 37:bdf736327c71 512
tass 37:bdf736327c71 513 pico_dns_client_getaddr(name,dns_cb,dnsResult);
tass 37:bdf736327c71 514
tass 37:bdf736327c71 515 osEvent evt = dnsResult->get(7000);// 7 seconds timeout
tass 37:bdf736327c71 516 if (evt.status == osEventMessage){
tass 37:bdf736327c71 517 ip = (char *)evt.value.p;
tass 37:bdf736327c71 518 hostdata = new struct hostent;
tass 37:bdf736327c71 519 hostdata->h_name = new char[strlen(name)+1];
tass 37:bdf736327c71 520 strcpy(hostdata->h_name,name);
tass 37:bdf736327c71 521 hostdata->h_aliases=NULL;
tass 37:bdf736327c71 522 hostdata->h_addrtype = AF_INET;
tass 37:bdf736327c71 523 hostdata->h_length = strlen(ip);
tass 37:bdf736327c71 524 hostdata->h_addr_list = new char*[2];
tass 37:bdf736327c71 525 hostdata->h_addr_list[0] = ip;
tass 37:bdf736327c71 526 hostdata->h_addr_list[1] = NULL;
tass 37:bdf736327c71 527 }
tass 37:bdf736327c71 528
tass 37:bdf736327c71 529 free(dnsResult);
tass 37:bdf736327c71 530 return hostdata;
tass 37:bdf736327c71 531 }