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 Jun 12 13:35:01 2013 +0000
Revision:
31:d3b2dfcc358f
Parent:
25:d63125298eb3
updated pico_tcp and pico_socket after the mainline.

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 19:c7debad9a20a 13
daniele 19:c7debad9a20a 14 //#define ptsock_dbg printf
daniele 19:c7debad9a20a 15 #define ptsock_dbg(...)
daniele 19:c7debad9a20a 16
daniele 19:c7debad9a20a 17 int in_the_stack = 0;
daniele 19:c7debad9a20a 18
daniele 19:c7debad9a20a 19
daniele 19:c7debad9a20a 20 static Thread * serverThread = NULL;
daniele 19:c7debad9a20a 21 // global queue for open requests
daniele 19:c7debad9a20a 22 Queue<struct picotcp_socketcall,10> picotcp_socketcall_queue;
daniele 19:c7debad9a20a 23 Queue<struct stack_endpoint,10> picotcp_socketcall_response_queue;
daniele 19:c7debad9a20a 24
daniele 19:c7debad9a20a 25 static inline void sendOpenResponse(struct stack_endpoint * arg)
daniele 19:c7debad9a20a 26 {
daniele 19:c7debad9a20a 27 picotcp_socketcall_response_queue.put(arg);
daniele 19:c7debad9a20a 28 }
daniele 19:c7debad9a20a 29
daniele 19:c7debad9a20a 30 static inline uint16_t readSocketCommand(struct stack_endpoint * endp)
daniele 19:c7debad9a20a 31 {
daniele 19:c7debad9a20a 32 osEvent event = endp->CallActivateQueue->get(0); // Tx for Client, Rx for Me, non blocking
daniele 19:c7debad9a20a 33 if(event.status == osEventMessage)
daniele 19:c7debad9a20a 34 return *((uint16_t *)event.value.p);
daniele 19:c7debad9a20a 35 return NO_COMMAND;
daniele 19:c7debad9a20a 36 }
daniele 19:c7debad9a20a 37
daniele 19:c7debad9a20a 38 static inline void sendSocketResponse(struct stack_endpoint *endp)
daniele 19:c7debad9a20a 39 {
daniele 19:c7debad9a20a 40 endp->CallResponseQueue->put(endp);
daniele 19:c7debad9a20a 41 }
daniele 19:c7debad9a20a 42
daniele 19:c7debad9a20a 43 static int stack_compare(void *ka, void *kb)
daniele 19:c7debad9a20a 44 {
daniele 19:c7debad9a20a 45 struct stack_endpoint *a = (struct stack_endpoint *)ka, *b = (struct stack_endpoint *)kb;
daniele 19:c7debad9a20a 46 if (a->s < b->s)
daniele 19:c7debad9a20a 47 return -1;
daniele 19:c7debad9a20a 48 if (a->s > b->s)
daniele 19:c7debad9a20a 49 return 1;
daniele 19:c7debad9a20a 50 return 0;
daniele 19:c7debad9a20a 51 }
daniele 19:c7debad9a20a 52
daniele 19:c7debad9a20a 53 PICO_TREE_DECLARE(stack_ep_tree, stack_compare);
daniele 19:c7debad9a20a 54
daniele 19:c7debad9a20a 55 static struct stack_endpoint *GET_SOCK_BY_PICOSOCK(struct pico_socket *s)
daniele 19:c7debad9a20a 56 {
daniele 19:c7debad9a20a 57 struct stack_endpoint test;
daniele 19:c7debad9a20a 58 test.s = s;
daniele 19:c7debad9a20a 59 return (struct stack_endpoint *)pico_tree_findKey(&stack_ep_tree, &test);
daniele 19:c7debad9a20a 60 }
daniele 19:c7debad9a20a 61
daniele 19:c7debad9a20a 62 static void stack_Add(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 63 {
daniele 19:c7debad9a20a 64 pico_tree_insert(&stack_ep_tree, ep);
daniele 19:c7debad9a20a 65 }
daniele 19:c7debad9a20a 66
daniele 19:c7debad9a20a 67 static void stack_Del(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 68 {
daniele 19:c7debad9a20a 69 pico_tree_delete(&stack_ep_tree, ep);
daniele 19:c7debad9a20a 70 }
daniele 19:c7debad9a20a 71
daniele 19:c7debad9a20a 72 static void status_pending_off(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 73 {
daniele 19:c7debad9a20a 74 //ep->pending = NO_COMMAND; //no event
daniele 19:c7debad9a20a 75 }
daniele 19:c7debad9a20a 76
daniele 19:c7debad9a20a 77
daniele 24:8bff2b51ea3b 78
daniele 19:c7debad9a20a 79
daniele 19:c7debad9a20a 80 static int send_wakeup(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 81 {
daniele 19:c7debad9a20a 82 int ret = 0;
daniele 19:c7debad9a20a 83 if (ep->pending == NO_COMMAND)
daniele 19:c7debad9a20a 84 return -1;
daniele 19:c7debad9a20a 85 ep->retval = 1;
daniele 19:c7debad9a20a 86 // send response
daniele 19:c7debad9a20a 87 sendSocketResponse(ep);
daniele 19:c7debad9a20a 88 return ret;
daniele 19:c7debad9a20a 89 }
daniele 19:c7debad9a20a 90
daniele 19:c7debad9a20a 91
daniele 19:c7debad9a20a 92
daniele 19:c7debad9a20a 93 static int send_retval(struct stack_endpoint *ep, int retval)
daniele 19:c7debad9a20a 94 {
daniele 19:c7debad9a20a 95 int ret = 0;
daniele 19:c7debad9a20a 96 if (ep->pending == NO_COMMAND)
daniele 19:c7debad9a20a 97 return -1;
daniele 19:c7debad9a20a 98 ep->retval = retval;
daniele 19:c7debad9a20a 99 // send queue
daniele 19:c7debad9a20a 100 sendSocketResponse(ep);
daniele 19:c7debad9a20a 101 status_pending_off(ep);
daniele 19:c7debad9a20a 102 return ret;
daniele 19:c7debad9a20a 103 }
daniele 19:c7debad9a20a 104
daniele 19:c7debad9a20a 105 static int send_error(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 106 {
daniele 19:c7debad9a20a 107 ep->code = pico_err;
daniele 19:c7debad9a20a 108 return send_retval(ep, -1);
daniele 19:c7debad9a20a 109 }
daniele 19:c7debad9a20a 110 static void set_timer(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 111 {
daniele 19:c7debad9a20a 112 if (ep->timeout == osWaitForever)
daniele 19:c7debad9a20a 113 return;
daniele 19:c7debad9a20a 114
daniele 19:c7debad9a20a 115 if (ep->t_call == 0) {
daniele 19:c7debad9a20a 116 ep->t_call = PICO_TIME_MS();
daniele 19:c7debad9a20a 117 ep->t_expire = ep->t_call + ep->timeout;
daniele 19:c7debad9a20a 118 }
daniele 19:c7debad9a20a 119 }
daniele 19:c7debad9a20a 120
daniele 19:c7debad9a20a 121 static void check_timer_expired(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 122 {
daniele 19:c7debad9a20a 123 if (ep->timeout == osWaitForever)
daniele 19:c7debad9a20a 124 return; /* never */
daniele 19:c7debad9a20a 125
daniele 19:c7debad9a20a 126 if (ep->t_expire < PICO_TIME_MS()) {
daniele 19:c7debad9a20a 127 ep->retval = 0;
daniele 19:c7debad9a20a 128 sendSocketResponse(ep);
daniele 19:c7debad9a20a 129 }
daniele 19:c7debad9a20a 130 }
daniele 19:c7debad9a20a 131
daniele 19:c7debad9a20a 132
daniele 19:c7debad9a20a 133 static void retry_connect(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 134 {
daniele 19:c7debad9a20a 135 if ((ep->revents & PICO_SOCK_EV_CONN) && ep->connected) {
daniele 19:c7debad9a20a 136 ep->revents &= (~PICO_SOCK_EV_CONN);
daniele 19:c7debad9a20a 137 ep->revents |= PICO_SOCK_EV_WR;
daniele 19:c7debad9a20a 138 ptsock_dbg("Established. sock state: %x\n", ep->s->state);
daniele 19:c7debad9a20a 139 send_retval(ep, 0);
daniele 19:c7debad9a20a 140 }else {
daniele 19:c7debad9a20a 141 pico_socket_connect(ep->s, &ep->addr, ep->port);
daniele 19:c7debad9a20a 142 ep->events |= PICO_SOCK_EV_CONN;
daniele 19:c7debad9a20a 143 }
daniele 19:c7debad9a20a 144 }
daniele 19:c7debad9a20a 145
daniele 19:c7debad9a20a 146 static void retry_accept(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 147 {
daniele 19:c7debad9a20a 148 struct pico_ip4 peer ={};
daniele 19:c7debad9a20a 149 uint16_t port = 0;
daniele 19:c7debad9a20a 150
daniele 19:c7debad9a20a 151 struct stack_endpoint *aep;
daniele 19:c7debad9a20a 152 struct pico_socket *sa;
daniele 19:c7debad9a20a 153 set_timer(ep);
daniele 19:c7debad9a20a 154 if (ep->revents & PICO_SOCK_EV_CONN) {
daniele 19:c7debad9a20a 155 ptsock_dbg("Incoming connection...\n");
daniele 19:c7debad9a20a 156 sa = pico_socket_accept(ep->s, &peer.addr, &port);
daniele 19:c7debad9a20a 157 if (sa) {
daniele 19:c7debad9a20a 158 ptsock_dbg("Accepted!\n");
daniele 19:c7debad9a20a 159 aep = (struct stack_endpoint *)pico_zalloc(sizeof(struct stack_endpoint));
daniele 19:c7debad9a20a 160 if (!aep) {
daniele 19:c7debad9a20a 161 send_error(ep);
daniele 19:c7debad9a20a 162 return;
daniele 19:c7debad9a20a 163 }
daniele 19:c7debad9a20a 164
daniele 19:c7debad9a20a 165 aep->sock_fd = (uint16_t)pico_rand();
daniele 19:c7debad9a20a 166 aep->s = sa;
daniele 19:c7debad9a20a 167 aep->connected = 1;
daniele 19:c7debad9a20a 168 aep->peer = peer;
daniele 19:c7debad9a20a 169 aep->peer_port = port;
daniele 19:c7debad9a20a 170 aep->addr = ep->addr;//copy parent's address
daniele 19:c7debad9a20a 171 aep->port = ep->port;
daniele 19:c7debad9a20a 172 aep->pending = NO_COMMAND;
daniele 19:c7debad9a20a 173 aep->revents |= PICO_SOCK_EV_WR;
daniele 19:c7debad9a20a 174 ep->revents &= (~PICO_SOCK_EV_CONN);
daniele 19:c7debad9a20a 175 aep->CallResponseQueue = new Queue<struct stack_endpoint,2>();
daniele 19:c7debad9a20a 176 aep->CallActivateQueue = new Queue<struct stack_endpoint,2>();
daniele 19:c7debad9a20a 177 aep->state = SOCK_CONNECTED;
daniele 19:c7debad9a20a 178 stack_Add(aep);
daniele 19:c7debad9a20a 179 ep->retval = 0;
daniele 19:c7debad9a20a 180 ep->CallResponseQueue->put(aep);
daniele 19:c7debad9a20a 181 } else {
daniele 19:c7debad9a20a 182 send_error(ep);
daniele 19:c7debad9a20a 183 }
daniele 19:c7debad9a20a 184 return;
daniele 19:c7debad9a20a 185 }
daniele 19:c7debad9a20a 186 ep->events |= PICO_SOCK_EV_CONN;
daniele 19:c7debad9a20a 187 check_timer_expired(ep);
daniele 19:c7debad9a20a 188 }
daniele 19:c7debad9a20a 189
daniele 19:c7debad9a20a 190 static void retry_close(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 191 {
daniele 25:d63125298eb3 192 if (ep) {
daniele 25:d63125298eb3 193 pico_socket_close(ep->s);
daniele 25:d63125298eb3 194 send_retval(ep, 0);
daniele 25:d63125298eb3 195 stack_Del(ep);
daniele 25:d63125298eb3 196 }
daniele 19:c7debad9a20a 197 }
daniele 19:c7debad9a20a 198
daniele 19:c7debad9a20a 199 static void retry_write(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 200 {
daniele 19:c7debad9a20a 201 if (ep->pending == NO_COMMAND)
daniele 19:c7debad9a20a 202 return;
daniele 19:c7debad9a20a 203
daniele 19:c7debad9a20a 204 if (!ep->buffer) {
daniele 19:c7debad9a20a 205 send_error(ep);
daniele 19:c7debad9a20a 206 return;
daniele 19:c7debad9a20a 207 }
daniele 19:c7debad9a20a 208
daniele 19:c7debad9a20a 209 if (ep->pending == TOK_SENDTO) {
daniele 19:c7debad9a20a 210 ep->size = pico_socket_sendto(ep->s, ep->buffer, ep->size, &ep->addr, ep->port);
daniele 19:c7debad9a20a 211 } else {
daniele 19:c7debad9a20a 212 ep->size = pico_socket_write(ep->s, ep->buffer, ep->size);
daniele 19:c7debad9a20a 213 }
daniele 19:c7debad9a20a 214 ep->revents &= (~PICO_SOCK_EV_WR);
daniele 19:c7debad9a20a 215 if (ep->size < 0)
daniele 19:c7debad9a20a 216 send_error(ep);
daniele 19:c7debad9a20a 217 else if (ep->size > 0)
daniele 19:c7debad9a20a 218 send_retval(ep, ep->size);
daniele 19:c7debad9a20a 219 else {
daniele 19:c7debad9a20a 220 ep->events |= PICO_SOCK_EV_WR;
daniele 19:c7debad9a20a 221 return;
daniele 19:c7debad9a20a 222 }
daniele 19:c7debad9a20a 223 }
daniele 19:c7debad9a20a 224
daniele 19:c7debad9a20a 225 static void retry_read(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 226 {
daniele 19:c7debad9a20a 227 int len;
daniele 19:c7debad9a20a 228 if (ep->pending == NO_COMMAND)
daniele 19:c7debad9a20a 229 return;
daniele 19:c7debad9a20a 230
daniele 19:c7debad9a20a 231 ptsock_dbg("in retry-read, len: %d \n", len);
daniele 19:c7debad9a20a 232
daniele 19:c7debad9a20a 233
daniele 19:c7debad9a20a 234
daniele 19:c7debad9a20a 235 if (!ep->buffer) {
daniele 19:c7debad9a20a 236 send_error(ep);
daniele 19:c7debad9a20a 237 return;
daniele 19:c7debad9a20a 238 } else {
daniele 19:c7debad9a20a 239 if (ep->pending == TOK_RECVFROM)
daniele 19:c7debad9a20a 240 len = pico_socket_recvfrom(ep->s, ep->buffer, ep->size, &ep->addr, &ep->port);
daniele 19:c7debad9a20a 241 else {
daniele 19:c7debad9a20a 242 len = pico_socket_read(ep->s, ep->buffer, ep->size);
daniele 19:c7debad9a20a 243 }
daniele 19:c7debad9a20a 244 }
daniele 19:c7debad9a20a 245
daniele 19:c7debad9a20a 246 if (ep->size > len)
daniele 19:c7debad9a20a 247 ep->revents &= (~PICO_SOCK_EV_RD);
daniele 19:c7debad9a20a 248
daniele 19:c7debad9a20a 249 if (len == 0) {
daniele 19:c7debad9a20a 250 ptsock_dbg("Read returned 0.");
daniele 19:c7debad9a20a 251 ep->events |= PICO_SOCK_EV_RD;
daniele 19:c7debad9a20a 252 return;
daniele 19:c7debad9a20a 253 }
daniele 19:c7debad9a20a 254 send_retval(ep, len);
daniele 19:c7debad9a20a 255 }
daniele 19:c7debad9a20a 256
daniele 19:c7debad9a20a 257 void retry_poll(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 258 {
daniele 19:c7debad9a20a 259 if (ep->pending == NO_COMMAND)
daniele 19:c7debad9a20a 260 return;
daniele 19:c7debad9a20a 261
daniele 19:c7debad9a20a 262 set_timer(ep);
daniele 19:c7debad9a20a 263
daniele 19:c7debad9a20a 264 if ((ep->events & ep->revents) != 0) {
daniele 19:c7debad9a20a 265 send_retval(ep, 1);
daniele 19:c7debad9a20a 266 return;
daniele 19:c7debad9a20a 267 }
daniele 19:c7debad9a20a 268
daniele 19:c7debad9a20a 269 check_timer_expired(ep);
daniele 19:c7debad9a20a 270 }
daniele 19:c7debad9a20a 271
daniele 19:c7debad9a20a 272 static void retry_token(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 273 {
daniele 19:c7debad9a20a 274 if (ep->pending == NO_COMMAND)
daniele 19:c7debad9a20a 275 return;
daniele 19:c7debad9a20a 276 ptsock_dbg("in retry-token, cmd: %04x\n", ep->pending);
daniele 19:c7debad9a20a 277 switch(ep->pending) {
daniele 19:c7debad9a20a 278 case TOK_POLL:
daniele 19:c7debad9a20a 279 retry_poll(ep);
daniele 19:c7debad9a20a 280 break;
daniele 19:c7debad9a20a 281 case TOK_CONNECT:
daniele 19:c7debad9a20a 282 retry_connect(ep);
daniele 19:c7debad9a20a 283 break;
daniele 19:c7debad9a20a 284 case TOK_ACCEPT:
daniele 19:c7debad9a20a 285 retry_accept(ep);
daniele 19:c7debad9a20a 286 break;
daniele 19:c7debad9a20a 287
daniele 19:c7debad9a20a 288 case TOK_READ:
daniele 19:c7debad9a20a 289 case TOK_RECV:
daniele 19:c7debad9a20a 290 case TOK_RECVFROM:
daniele 19:c7debad9a20a 291 retry_read(ep);
daniele 19:c7debad9a20a 292 break;
daniele 19:c7debad9a20a 293
daniele 19:c7debad9a20a 294 case TOK_WRITE:
daniele 19:c7debad9a20a 295 case TOK_SEND:
daniele 19:c7debad9a20a 296 case TOK_SENDTO:
daniele 19:c7debad9a20a 297 retry_write(ep);
daniele 19:c7debad9a20a 298 break;
daniele 19:c7debad9a20a 299
daniele 19:c7debad9a20a 300 case TOK_CLOSE:
daniele 19:c7debad9a20a 301 retry_close(ep);
daniele 19:c7debad9a20a 302 break;
daniele 19:c7debad9a20a 303 default:
daniele 19:c7debad9a20a 304 break;
daniele 19:c7debad9a20a 305 }
daniele 19:c7debad9a20a 306 }
daniele 19:c7debad9a20a 307
daniele 19:c7debad9a20a 308 static void wakeup(uint16_t ev, struct pico_socket *s)
daniele 19:c7debad9a20a 309 {
daniele 19:c7debad9a20a 310 int t;
daniele 19:c7debad9a20a 311 struct stack_endpoint *ep = GET_SOCK_BY_PICOSOCK(s);
daniele 19:c7debad9a20a 312
daniele 19:c7debad9a20a 313 if (!ep) {
daniele 19:c7debad9a20a 314 ptsock_dbg("WAKEUP: no socket :(\n");
daniele 19:c7debad9a20a 315 return;
daniele 19:c7debad9a20a 316 }
daniele 19:c7debad9a20a 317 t = ep->pending;
daniele 19:c7debad9a20a 318 ptsock_dbg("Wake up event: %04x\n", ev);
daniele 19:c7debad9a20a 319 ep->revents |= ev;
daniele 19:c7debad9a20a 320
daniele 24:8bff2b51ea3b 321
daniele 24:8bff2b51ea3b 322
daniele 25:d63125298eb3 323 if (ev & (PICO_SOCK_EV_CLOSE | PICO_SOCK_EV_FIN)){
daniele 24:8bff2b51ea3b 324 printf("** CLOSE\n");
daniele 24:8bff2b51ea3b 325 ep->connected = 0;
daniele 24:8bff2b51ea3b 326 }
daniele 24:8bff2b51ea3b 327
daniele 19:c7debad9a20a 328 if (ev & PICO_SOCK_EV_ERR) {
daniele 19:c7debad9a20a 329 ep->revents = PICO_SOCK_EV_ERR;
daniele 19:c7debad9a20a 330 send_error(ep);
daniele 19:c7debad9a20a 331 return;
daniele 19:c7debad9a20a 332 }
daniele 19:c7debad9a20a 333
daniele 19:c7debad9a20a 334 if ((ev & PICO_SOCK_EV_CONN) || (ev & PICO_SOCK_EV_RD)) {
daniele 24:8bff2b51ea3b 335 if ((ev & PICO_SOCK_EV_CONN) && ((ep->pending == TOK_CONNECT) || (ep->pending == TOK_ACCEPT))) {
daniele 24:8bff2b51ea3b 336 printf("** Connected\n");
daniele 19:c7debad9a20a 337 ep->connected = 1;
daniele 19:c7debad9a20a 338 }
daniele 19:c7debad9a20a 339 }
daniele 24:8bff2b51ea3b 340 ep->revents = ev;
daniele 19:c7debad9a20a 341 if ( (ep->pending != 0) && ((ep->events & ep->revents)!=0) )
daniele 19:c7debad9a20a 342 retry_token(ep);
daniele 19:c7debad9a20a 343 }
daniele 19:c7debad9a20a 344
daniele 19:c7debad9a20a 345 static int stack_parse_requests(void)
daniele 19:c7debad9a20a 346 {
daniele 19:c7debad9a20a 347 struct stack_endpoint *ep = NULL;
daniele 19:c7debad9a20a 348 struct picotcp_socketcall *skc;
daniele 19:c7debad9a20a 349 osEvent event; // used to see the status of queue get
daniele 19:c7debad9a20a 350 struct pico_tree_node * index = NULL;
daniele 19:c7debad9a20a 351 uint16_t proto,net;
daniele 19:c7debad9a20a 352 int ret = 0;
daniele 19:c7debad9a20a 353 int yes = 1;
daniele 19:c7debad9a20a 354 // first check if the global queue has something in it
daniele 19:c7debad9a20a 355 // and open a new socket if so
daniele 19:c7debad9a20a 356 do
daniele 19:c7debad9a20a 357 {
daniele 19:c7debad9a20a 358 stack_endpoint *stack_ep = NULL;
daniele 19:c7debad9a20a 359
daniele 19:c7debad9a20a 360 event = picotcp_socketcall_queue.get(0); // non blocking get
daniele 19:c7debad9a20a 361 if(event.status == osEventMessage) {
daniele 19:c7debad9a20a 362 ret = 1;
daniele 19:c7debad9a20a 363 // Get the arguments
daniele 19:c7debad9a20a 364 skc = (struct picotcp_socketcall *)event.value.p;
daniele 19:c7debad9a20a 365
daniele 19:c7debad9a20a 366 // open new socket and send the response
daniele 19:c7debad9a20a 367 stack_ep = (struct stack_endpoint *)pico_zalloc(sizeof(struct stack_endpoint));
daniele 19:c7debad9a20a 368 if(!stack_ep)
daniele 19:c7debad9a20a 369 {
daniele 19:c7debad9a20a 370 ptsock_dbg("Out of memory\n");
daniele 19:c7debad9a20a 371 return -1;
daniele 19:c7debad9a20a 372 }
daniele 19:c7debad9a20a 373 stack_ep->CallActivateQueue = new Queue<struct stack_endpoint,2>();
daniele 19:c7debad9a20a 374 stack_ep->CallResponseQueue = new Queue<struct stack_endpoint,2>();
daniele 19:c7debad9a20a 375
daniele 19:c7debad9a20a 376 net = ((skc->family == AF_INET6)?PICO_PROTO_IPV6:PICO_PROTO_IPV4);
daniele 19:c7debad9a20a 377 proto = ((skc->proto == SOCK_DGRAM)?PICO_PROTO_UDP:PICO_PROTO_TCP);
daniele 19:c7debad9a20a 378 stack_ep->s = pico_socket_open( net, proto, &wakeup );
daniele 19:c7debad9a20a 379
daniele 19:c7debad9a20a 380 if (!stack_ep->s)
daniele 19:c7debad9a20a 381 stack_ep->retval = -1;
daniele 19:c7debad9a20a 382 //pico_socket_setoption(stack_ep->s, PICO_SOCKET_OPT_TCPNODELAY, &yes);
daniele 19:c7debad9a20a 383
daniele 19:c7debad9a20a 384 //stack_ep->pending = NO_COMMAND;
daniele 19:c7debad9a20a 385 stack_Add(stack_ep);
daniele 19:c7debad9a20a 386 // send the response back to the client
daniele 19:c7debad9a20a 387 sendOpenResponse(stack_ep);
daniele 19:c7debad9a20a 388 ptsock_dbg("New socket added: %p\n", stack_ep->s);
daniele 19:c7debad9a20a 389 }
daniele 19:c7debad9a20a 390 }while(event.status == osEventMessage);
daniele 19:c7debad9a20a 391
daniele 19:c7debad9a20a 392 // go through all the sockets and check if there is a request from someone
daniele 19:c7debad9a20a 393 // call to the get function has timeout 0, must be non blocking
daniele 19:c7debad9a20a 394 // if a request has come from someone parse it
daniele 19:c7debad9a20a 395 pico_tree_foreach(index,&stack_ep_tree)
daniele 19:c7debad9a20a 396 {
daniele 19:c7debad9a20a 397 ep = (struct stack_endpoint *)index->keyValue;
daniele 19:c7debad9a20a 398 // check if data has arrived
daniele 19:c7debad9a20a 399 event = ep->CallActivateQueue->get(0); // again non blocking
daniele 19:c7debad9a20a 400 if(event.status == osEventMessage)
daniele 19:c7debad9a20a 401 {
daniele 19:c7debad9a20a 402 ret = 1;
daniele 19:c7debad9a20a 403 //printf("Socket contacted. CMD: %X\n", ep->pending);
daniele 19:c7debad9a20a 404 // check command sent
daniele 19:c7debad9a20a 405 switch(ep->pending)
daniele 19:c7debad9a20a 406 {
daniele 19:c7debad9a20a 407 case TOK_BIND:
daniele 19:c7debad9a20a 408 if(pico_socket_bind(ep->s, &ep->addr, &ep->port) == 0) {
daniele 19:c7debad9a20a 409 ptsock_dbg("stack: bind success (addr: %08x, port %d)!\n", ep->addr.addr, ep->port);
daniele 19:c7debad9a20a 410 send_retval(ep, 0);
daniele 19:c7debad9a20a 411 } else {
daniele 19:c7debad9a20a 412 ptsock_dbg("stack: bind error (pico_s: %p, addr: %08x, port %d err: %d)!\n", ep->s, ep->addr.addr, ep->port, pico_err);
daniele 19:c7debad9a20a 413 send_error(ep);
daniele 19:c7debad9a20a 414 }
daniele 19:c7debad9a20a 415 break;
daniele 19:c7debad9a20a 416 case TOK_LISTEN:
daniele 19:c7debad9a20a 417 if(pico_socket_listen(ep->s, ep->size) == 0)
daniele 19:c7debad9a20a 418 send_retval(ep, 0);
daniele 19:c7debad9a20a 419 else
daniele 19:c7debad9a20a 420 send_error(ep);
daniele 19:c7debad9a20a 421 break;
daniele 19:c7debad9a20a 422 default:
daniele 19:c7debad9a20a 423 retry_token(ep);
daniele 19:c7debad9a20a 424 }
daniele 19:c7debad9a20a 425 break;
daniele 19:c7debad9a20a 426 }
daniele 19:c7debad9a20a 427 }
daniele 19:c7debad9a20a 428 return ret;
daniele 19:c7debad9a20a 429 }
daniele 19:c7debad9a20a 430
daniele 19:c7debad9a20a 431 void pico_wrapper_loop(const void * arg)
daniele 19:c7debad9a20a 432 {
daniele 19:c7debad9a20a 433 (void)arg;
daniele 19:c7debad9a20a 434 int ret = 0;
daniele 19:c7debad9a20a 435 while(1) {
daniele 23:884f327c3647 436 ret = stack_parse_requests();
daniele 19:c7debad9a20a 437 pico_stack_tick();
daniele 25:d63125298eb3 438 //Thread::wait(1);
daniele 24:8bff2b51ea3b 439 Thread::wait(1);
daniele 19:c7debad9a20a 440 }
daniele 19:c7debad9a20a 441 }
daniele 19:c7debad9a20a 442
daniele 19:c7debad9a20a 443 void picotcp_start(void)
daniele 19:c7debad9a20a 444 {
daniele 23:884f327c3647 445 Ticker *picotcpTicker = new Ticker();
daniele 19:c7debad9a20a 446 if (serverThread == NULL) {
daniele 19:c7debad9a20a 447 printf (" *** PicoTCP initialized *** \n");
tass 31:d3b2dfcc358f 448 serverThread = new Thread(pico_wrapper_loop,NULL,osPriorityNormal,4096);
daniele 19:c7debad9a20a 449 serverThread->set_priority(osPriorityIdle);
daniele 23:884f327c3647 450 //picotcpTicker->attach(&pico_stack_tick, 0.001);
daniele 19:c7debad9a20a 451 }
daniele 19:c7debad9a20a 452 }