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 RTOSgeneric mbed Ethernet driverhigh performance NXP LPC1768 specific Ethernet driverMulti-threading support for mbed RTOSBerkeley sockets and integration with the New Socket APIFork of the apps running on top of the New Socket APIScheduling 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.
Socket/bsd/stack_endpoint.cpp@31:d3b2dfcc358f, 2013-06-12 (annotated)
- 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?
User | Revision | Line number | New 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 | } |