Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of PicoTCP by
Socket/pico_bsd_layer.cpp@11:58acd53df75c, 2013-06-06 (annotated)
- Committer:
- daniele
- Date:
- Thu Jun 06 07:08:58 2013 +0000
- Revision:
- 11:58acd53df75c
- Parent:
- 5:445d2fc04784
- Child:
- 13:c6662adea07d
Update from masterbranch;
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| tass | 5:445d2fc04784 | 1 | |
| tass | 5:445d2fc04784 | 2 | /********************************************************************* |
| tass | 5:445d2fc04784 | 3 | PicoTCP. Copyright (c) 2013 TASS Belgium NV. Some rights reserved. |
| tass | 5:445d2fc04784 | 4 | See LICENSE and COPYING for usage. |
| tass | 5:445d2fc04784 | 5 | |
| tass | 5:445d2fc04784 | 6 | Authors: Andrei Carp <andrei.carp@tass.be>, Daniele Lacamera <daniele.lacamera@tass.be> |
| tass | 5:445d2fc04784 | 7 | *********************************************************************/ |
| tass | 5:445d2fc04784 | 8 | #include "pico_bsd_layer.h" |
| tass | 5:445d2fc04784 | 9 | |
| tass | 5:445d2fc04784 | 10 | #include "mbed.h" |
| tass | 5:445d2fc04784 | 11 | #include "rtos.h" |
| tass | 5:445d2fc04784 | 12 | #include "cmsis_os.h" |
| tass | 5:445d2fc04784 | 13 | #include "Queue.h" |
| tass | 5:445d2fc04784 | 14 | #include "Mutex.h" |
| tass | 5:445d2fc04784 | 15 | #include "PicoCondition.h" |
| tass | 5:445d2fc04784 | 16 | /************************** PICO BSD SOCKET LAYER **************************/ |
| tass | 5:445d2fc04784 | 17 | |
| tass | 5:445d2fc04784 | 18 | #define DEFAULT_BACKLOG (5u) |
| tass | 5:445d2fc04784 | 19 | #define DEFAULT_TIMEOUT (10000u) |
| tass | 5:445d2fc04784 | 20 | |
| tass | 5:445d2fc04784 | 21 | // Handle events received from the callback |
| tass | 5:445d2fc04784 | 22 | #define EVENT_PENDING(x,ev) (x & (ev)) |
| tass | 5:445d2fc04784 | 23 | #define CLEAR_EVENTS(x) (x ^= (x)) |
| tass | 5:445d2fc04784 | 24 | #define SET_EVENT(x,ev) (x |= (ev)) |
| tass | 5:445d2fc04784 | 25 | #define RESET_EVENT(x,ev) (x &= (~ev)) |
| tass | 5:445d2fc04784 | 26 | #define CLEAR_ERROR(x) RESET_EVENT(x,PICO_SOCK_EV_ERR) |
| tass | 5:445d2fc04784 | 27 | |
| tass | 5:445d2fc04784 | 28 | #define EVENT_EXPECTED(x) (x->event & x->revent) |
| tass | 5:445d2fc04784 | 29 | |
| tass | 5:445d2fc04784 | 30 | /* TODO: Sync blocking from here to blocking from Socket */ |
| tass | 5:445d2fc04784 | 31 | |
| tass | 5:445d2fc04784 | 32 | static struct socket dummy; |
| tass | 5:445d2fc04784 | 33 | #define MAKE_SOCKET(x) ((struct socket *)x) |
| tass | 5:445d2fc04784 | 34 | |
| tass | 5:445d2fc04784 | 35 | static int compareSock(void *ka, void *kb) |
| tass | 5:445d2fc04784 | 36 | { |
| tass | 5:445d2fc04784 | 37 | return MAKE_SOCKET(ka)->socket - MAKE_SOCKET(kb)->socket; |
| tass | 5:445d2fc04784 | 38 | } |
| tass | 5:445d2fc04784 | 39 | |
| tass | 5:445d2fc04784 | 40 | PICO_TREE_DECLARE(sockTree,compareSock); |
| tass | 5:445d2fc04784 | 41 | |
| tass | 5:445d2fc04784 | 42 | #define VALIDATE_NULL(param) \ |
| tass | 5:445d2fc04784 | 43 | if(!param) \ |
| tass | 5:445d2fc04784 | 44 | { \ |
| tass | 5:445d2fc04784 | 45 | return -1; \ |
| tass | 5:445d2fc04784 | 46 | } |
| tass | 5:445d2fc04784 | 47 | |
| tass | 5:445d2fc04784 | 48 | #define VALIDATE_ONE(param,value) \ |
| tass | 5:445d2fc04784 | 49 | if(param != value) { \ |
| tass | 5:445d2fc04784 | 50 | pico_err = PICO_ERR_EINVAL; \ |
| tass | 5:445d2fc04784 | 51 | return -1; \ |
| tass | 5:445d2fc04784 | 52 | } |
| tass | 5:445d2fc04784 | 53 | |
| tass | 5:445d2fc04784 | 54 | #define VALIDATE_TWO(param,value1,value2) \ |
| tass | 5:445d2fc04784 | 55 | if(param != value1 && param != value2) { \ |
| tass | 5:445d2fc04784 | 56 | pico_err = PICO_ERR_EINVAL; \ |
| tass | 5:445d2fc04784 | 57 | return -1; \ |
| tass | 5:445d2fc04784 | 58 | } |
| tass | 5:445d2fc04784 | 59 | |
| tass | 5:445d2fc04784 | 60 | /* PRIVATE FUNCTIONS */ |
| tass | 5:445d2fc04784 | 61 | |
| tass | 5:445d2fc04784 | 62 | static inline struct socket * findAfterId(int sock) |
| tass | 5:445d2fc04784 | 63 | { |
| tass | 5:445d2fc04784 | 64 | dummy.socket = sock; |
| tass | 5:445d2fc04784 | 65 | return (struct socket *)pico_tree_findKey(&sockTree,&dummy); |
| tass | 5:445d2fc04784 | 66 | } |
| tass | 5:445d2fc04784 | 67 | |
| tass | 5:445d2fc04784 | 68 | static inline struct socket * findAfterSocket(struct pico_socket * sock) |
| tass | 5:445d2fc04784 | 69 | { |
| tass | 5:445d2fc04784 | 70 | struct pico_tree_node * index; |
| tass | 5:445d2fc04784 | 71 | |
| tass | 5:445d2fc04784 | 72 | pico_tree_foreach(index,&sockTree) |
| tass | 5:445d2fc04784 | 73 | { |
| tass | 5:445d2fc04784 | 74 | if( MAKE_SOCKET(index->keyValue)->sock == sock ) |
| tass | 5:445d2fc04784 | 75 | return (struct socket *)index->keyValue; |
| tass | 5:445d2fc04784 | 76 | } |
| tass | 5:445d2fc04784 | 77 | |
| tass | 5:445d2fc04784 | 78 | return NULL; |
| tass | 5:445d2fc04784 | 79 | } |
| tass | 5:445d2fc04784 | 80 | |
| tass | 5:445d2fc04784 | 81 | static inline int waitForEvent(struct socket * sock, uint16_t event, uint8_t clear) |
| tass | 5:445d2fc04784 | 82 | { |
| tass | 5:445d2fc04784 | 83 | int retValue = 0; |
| tass | 5:445d2fc04784 | 84 | |
| tass | 5:445d2fc04784 | 85 | if(sock->blocking) |
| tass | 5:445d2fc04784 | 86 | { |
| tass | 5:445d2fc04784 | 87 | if(EVENT_PENDING(sock->revent,event)) |
| tass | 5:445d2fc04784 | 88 | { |
| tass | 5:445d2fc04784 | 89 | //printf("Already...\n"); |
| tass | 5:445d2fc04784 | 90 | RESET_EVENT(sock->revent, event); |
| tass | 5:445d2fc04784 | 91 | RESET_EVENT(sock->event, event); |
| tass | 5:445d2fc04784 | 92 | } |
| tass | 5:445d2fc04784 | 93 | else |
| tass | 5:445d2fc04784 | 94 | { |
| tass | 5:445d2fc04784 | 95 | SET_EVENT(sock->event, event); |
| tass | 5:445d2fc04784 | 96 | //printf("Locked...\n"); |
| tass | 5:445d2fc04784 | 97 | sock->mutex->lock(); |
| tass | 5:445d2fc04784 | 98 | RESET_EVENT(sock->event,event); |
| tass | 5:445d2fc04784 | 99 | |
| tass | 5:445d2fc04784 | 100 | if(! EVENT_PENDING(sock->revent,event) || EVENT_PENDING(sock->revent, PICO_SOCK_EV_ERR) || |
| tass | 5:445d2fc04784 | 101 | EVENT_PENDING(sock->revent,PICO_SOCK_EV_CLOSE) || EVENT_PENDING(sock->revent,PICO_SOCK_EV_FIN) ) |
| tass | 5:445d2fc04784 | 102 | retValue = -1; |
| tass | 5:445d2fc04784 | 103 | } |
| tass | 5:445d2fc04784 | 104 | if(clear) |
| tass | 5:445d2fc04784 | 105 | RESET_EVENT(sock->revent, event); |
| tass | 5:445d2fc04784 | 106 | } |
| tass | 5:445d2fc04784 | 107 | |
| tass | 5:445d2fc04784 | 108 | return retValue; |
| tass | 5:445d2fc04784 | 109 | } |
| tass | 5:445d2fc04784 | 110 | |
| tass | 5:445d2fc04784 | 111 | |
| tass | 5:445d2fc04784 | 112 | static void dispatch_socket(uint16_t ev, struct pico_socket * sock) |
| tass | 5:445d2fc04784 | 113 | { |
| tass | 5:445d2fc04784 | 114 | struct socket * _sock = findAfterSocket(sock); |
| tass | 5:445d2fc04784 | 115 | |
| tass | 5:445d2fc04784 | 116 | if(!_sock) |
| tass | 5:445d2fc04784 | 117 | return; |
| tass | 5:445d2fc04784 | 118 | |
| tass | 5:445d2fc04784 | 119 | //printf("Received : %d\n",ev); |
| tass | 5:445d2fc04784 | 120 | |
| tass | 5:445d2fc04784 | 121 | SET_EVENT(_sock->revent,ev); |
| tass | 5:445d2fc04784 | 122 | if(EVENT_EXPECTED(_sock)) |
| tass | 5:445d2fc04784 | 123 | { |
| tass | 5:445d2fc04784 | 124 | // if one of the events we're waiting has arrived, unblock this |
| tass | 5:445d2fc04784 | 125 | //printf("Expected event, release the orcs!\n"); |
| tass | 5:445d2fc04784 | 126 | _sock->mutex->unlock(); |
| tass | 5:445d2fc04784 | 127 | } |
| tass | 5:445d2fc04784 | 128 | else |
| tass | 5:445d2fc04784 | 129 | { |
| tass | 5:445d2fc04784 | 130 | //printf("Unexpected event\n"); |
| tass | 5:445d2fc04784 | 131 | // give semaphore back when -1 occurs or close requested |
| tass | 5:445d2fc04784 | 132 | if( (ev & PICO_SOCK_EV_ERR) || (ev & PICO_SOCK_EV_CLOSE) || (ev & PICO_SOCK_EV_FIN) ) |
| tass | 5:445d2fc04784 | 133 | { |
| tass | 5:445d2fc04784 | 134 | //printf("Exception\n"); |
| tass | 5:445d2fc04784 | 135 | |
| tass | 5:445d2fc04784 | 136 | _sock->state = SOCK_CLOSED; |
| tass | 5:445d2fc04784 | 137 | if(_sock->sock) |
| tass | 5:445d2fc04784 | 138 | { |
| tass | 5:445d2fc04784 | 139 | pico_socket_close(_sock->sock); |
| tass | 5:445d2fc04784 | 140 | _sock->sock = NULL; |
| tass | 5:445d2fc04784 | 141 | } |
| tass | 5:445d2fc04784 | 142 | _sock->mutex->unlock(); |
| tass | 5:445d2fc04784 | 143 | } |
| tass | 5:445d2fc04784 | 144 | } |
| tass | 5:445d2fc04784 | 145 | } |
| tass | 5:445d2fc04784 | 146 | |
| tass | 5:445d2fc04784 | 147 | /* PUBLIC FUNCTIONS */ |
| tass | 5:445d2fc04784 | 148 | |
| tass | 5:445d2fc04784 | 149 | int picotcp_socket(uint16_t net, uint16_t proto, uint16_t flags) |
| tass | 5:445d2fc04784 | 150 | { |
| tass | 5:445d2fc04784 | 151 | struct socket * sock = NULL; |
| tass | 5:445d2fc04784 | 152 | |
| tass | 5:445d2fc04784 | 153 | net = (net == AF_INET ? PICO_PROTO_IPV4 : (net == AF_INET6 ? PICO_PROTO_IPV6 : -1)); |
| tass | 5:445d2fc04784 | 154 | proto = (proto == SOCK_DGRAM ? PICO_PROTO_UDP : (proto == SOCK_STREAM ? PICO_PROTO_TCP : -1)); |
| tass | 5:445d2fc04784 | 155 | |
| tass | 5:445d2fc04784 | 156 | VALIDATE_TWO(net,PICO_PROTO_IPV4,PICO_PROTO_IPV6); |
| tass | 5:445d2fc04784 | 157 | VALIDATE_TWO(proto,PICO_PROTO_TCP,PICO_PROTO_UDP); |
| tass | 5:445d2fc04784 | 158 | //printf("Parameters are correct...\n"); |
| tass | 5:445d2fc04784 | 159 | sock = (struct socket*)pico_zalloc(sizeof(struct socket)); |
| tass | 5:445d2fc04784 | 160 | VALIDATE_NULL(sock); |
| tass | 5:445d2fc04784 | 161 | |
| tass | 5:445d2fc04784 | 162 | sock->proto = proto; |
| tass | 5:445d2fc04784 | 163 | sock->sock = pico_socket_open(net,proto,&dispatch_socket); |
| tass | 5:445d2fc04784 | 164 | |
| tass | 5:445d2fc04784 | 165 | if(!sock->sock) |
| tass | 5:445d2fc04784 | 166 | { |
| tass | 5:445d2fc04784 | 167 | pico_free(sock); |
| tass | 5:445d2fc04784 | 168 | return -1; |
| tass | 5:445d2fc04784 | 169 | } |
| tass | 5:445d2fc04784 | 170 | |
| tass | 5:445d2fc04784 | 171 | sock->socket = (int)sock; |
| tass | 5:445d2fc04784 | 172 | sock->mutex = new PicoCondition(); |
| tass | 5:445d2fc04784 | 173 | |
| tass | 5:445d2fc04784 | 174 | if(!sock->mutex) |
| tass | 5:445d2fc04784 | 175 | { |
| tass | 5:445d2fc04784 | 176 | pico_socket_close(sock->sock); |
| tass | 5:445d2fc04784 | 177 | pico_free(sock); |
| tass | 5:445d2fc04784 | 178 | return -1; |
| tass | 5:445d2fc04784 | 179 | } |
| tass | 5:445d2fc04784 | 180 | |
| tass | 5:445d2fc04784 | 181 | pico_tree_insert(&sockTree,sock); |
| tass | 5:445d2fc04784 | 182 | sock->state = SOCK_OPEN; |
| tass | 5:445d2fc04784 | 183 | |
| tass | 5:445d2fc04784 | 184 | return sock->socket; |
| tass | 5:445d2fc04784 | 185 | } |
| tass | 5:445d2fc04784 | 186 | |
| tass | 5:445d2fc04784 | 187 | int picotcp_bind(int sock, struct sockaddr *local_addr, socklen_t len) |
| tass | 5:445d2fc04784 | 188 | { |
| tass | 5:445d2fc04784 | 189 | struct socket * _sock = findAfterId(sock); |
| tass | 5:445d2fc04784 | 190 | int ret; |
| tass | 5:445d2fc04784 | 191 | struct sockaddr_in *s_in = (struct sockaddr_in *) local_addr; |
| tass | 5:445d2fc04784 | 192 | |
| tass | 5:445d2fc04784 | 193 | VALIDATE_NULL(_sock); |
| tass | 5:445d2fc04784 | 194 | VALIDATE_NULL(local_addr); |
| tass | 5:445d2fc04784 | 195 | VALIDATE_NULL(len); |
| tass | 5:445d2fc04784 | 196 | |
| tass | 5:445d2fc04784 | 197 | ret = pico_socket_bind(_sock->sock,(void *)&s_in->sin_addr,(uint16_t *)&s_in->sin_port); |
| tass | 5:445d2fc04784 | 198 | |
| tass | 5:445d2fc04784 | 199 | if(ret == 0) |
| tass | 5:445d2fc04784 | 200 | _sock->state = SOCK_BOUND; |
| tass | 5:445d2fc04784 | 201 | |
| tass | 5:445d2fc04784 | 202 | return ret; |
| tass | 5:445d2fc04784 | 203 | } |
| tass | 5:445d2fc04784 | 204 | |
| tass | 5:445d2fc04784 | 205 | int picotcp_state(int sock) |
| tass | 5:445d2fc04784 | 206 | { |
| tass | 5:445d2fc04784 | 207 | struct socket * _sock = findAfterId(sock); |
| tass | 5:445d2fc04784 | 208 | VALIDATE_NULL(_sock); |
| tass | 5:445d2fc04784 | 209 | |
| tass | 5:445d2fc04784 | 210 | return _sock->state; |
| tass | 5:445d2fc04784 | 211 | } |
| tass | 5:445d2fc04784 | 212 | |
| tass | 5:445d2fc04784 | 213 | int picotcp_listen(int sock, int queue) |
| tass | 5:445d2fc04784 | 214 | { |
| tass | 5:445d2fc04784 | 215 | struct socket * _sock = findAfterId(sock); |
| tass | 5:445d2fc04784 | 216 | int ret; |
| tass | 5:445d2fc04784 | 217 | |
| tass | 5:445d2fc04784 | 218 | if(queue <= 0) |
| tass | 5:445d2fc04784 | 219 | queue = DEFAULT_BACKLOG; |
| tass | 5:445d2fc04784 | 220 | |
| tass | 5:445d2fc04784 | 221 | VALIDATE_NULL(_sock); |
| tass | 5:445d2fc04784 | 222 | VALIDATE_ONE(_sock->state,SOCK_BOUND); |
| tass | 5:445d2fc04784 | 223 | |
| tass | 5:445d2fc04784 | 224 | ret = pico_socket_listen(_sock->sock,queue); |
| tass | 5:445d2fc04784 | 225 | |
| tass | 5:445d2fc04784 | 226 | if(!ret) |
| tass | 5:445d2fc04784 | 227 | _sock->state = SOCK_LISTEN; |
| tass | 5:445d2fc04784 | 228 | |
| tass | 5:445d2fc04784 | 229 | return ret; |
| tass | 5:445d2fc04784 | 230 | } |
| tass | 5:445d2fc04784 | 231 | |
| tass | 5:445d2fc04784 | 232 | int picotcp_connect(int sock, struct sockaddr *srv_addr, socklen_t len) |
| tass | 5:445d2fc04784 | 233 | { |
| tass | 5:445d2fc04784 | 234 | struct socket * _sock = findAfterId(sock); |
| tass | 5:445d2fc04784 | 235 | int ret; |
| tass | 5:445d2fc04784 | 236 | struct sockaddr_in *s_in = (struct sockaddr_in *) srv_addr; |
| tass | 5:445d2fc04784 | 237 | |
| tass | 5:445d2fc04784 | 238 | VALIDATE_NULL(_sock); |
| tass | 5:445d2fc04784 | 239 | VALIDATE_NULL(len); |
| tass | 5:445d2fc04784 | 240 | |
| tass | 5:445d2fc04784 | 241 | ret = pico_socket_connect(_sock->sock,(void*)&s_in->sin_addr,s_in->sin_port); |
| tass | 5:445d2fc04784 | 242 | |
| tass | 5:445d2fc04784 | 243 | if(ret < 0) |
| tass | 5:445d2fc04784 | 244 | { |
| tass | 5:445d2fc04784 | 245 | printf("connect error\n"); |
| tass | 5:445d2fc04784 | 246 | return -1; |
| tass | 5:445d2fc04784 | 247 | } |
| tass | 5:445d2fc04784 | 248 | |
| tass | 5:445d2fc04784 | 249 | if(_sock->proto == PICO_PROTO_TCP) |
| tass | 5:445d2fc04784 | 250 | { |
| tass | 5:445d2fc04784 | 251 | if(waitForEvent(_sock,PICO_SOCK_EV_CONN,1) < 0) |
| tass | 5:445d2fc04784 | 252 | return -1; |
| tass | 5:445d2fc04784 | 253 | } |
| tass | 5:445d2fc04784 | 254 | |
| tass | 5:445d2fc04784 | 255 | _sock->state = SOCK_CONNECTED; |
| tass | 5:445d2fc04784 | 256 | |
| tass | 5:445d2fc04784 | 257 | return ret; |
| tass | 5:445d2fc04784 | 258 | } |
| tass | 5:445d2fc04784 | 259 | |
| tass | 5:445d2fc04784 | 260 | int picotcp_accept(int sock, struct sockaddr *orig, socklen_t *len) |
| tass | 5:445d2fc04784 | 261 | { |
| tass | 5:445d2fc04784 | 262 | struct socket * _sock = findAfterId(sock); |
| tass | 5:445d2fc04784 | 263 | struct socket * client = NULL; |
| tass | 5:445d2fc04784 | 264 | struct pico_socket * sck = NULL; |
| tass | 5:445d2fc04784 | 265 | struct sockaddr_in *s_in = (struct sockaddr_in *) orig; |
| tass | 5:445d2fc04784 | 266 | |
| tass | 5:445d2fc04784 | 267 | |
| tass | 5:445d2fc04784 | 268 | VALIDATE_NULL(_sock); |
| tass | 5:445d2fc04784 | 269 | VALIDATE_ONE(_sock->proto, PICO_PROTO_TCP); |
| tass | 5:445d2fc04784 | 270 | VALIDATE_ONE(_sock->state, SOCK_LISTEN); |
| tass | 5:445d2fc04784 | 271 | VALIDATE_NULL(len); |
| tass | 5:445d2fc04784 | 272 | |
| tass | 5:445d2fc04784 | 273 | if(waitForEvent(_sock,PICO_SOCK_EV_CONN,1)) |
| tass | 5:445d2fc04784 | 274 | { |
| tass | 5:445d2fc04784 | 275 | printf("Wait for event failed\n"); |
| tass | 5:445d2fc04784 | 276 | return -1; |
| tass | 5:445d2fc04784 | 277 | } |
| tass | 5:445d2fc04784 | 278 | |
| tass | 5:445d2fc04784 | 279 | // create new socket and set it directly to connected |
| tass | 5:445d2fc04784 | 280 | sck = pico_socket_accept(_sock->sock,(void *)&s_in->sin_addr,(uint16_t *)&s_in->sin_port); |
| tass | 5:445d2fc04784 | 281 | *len = sizeof(struct sockaddr_in); |
| tass | 5:445d2fc04784 | 282 | |
| tass | 5:445d2fc04784 | 283 | if(!sck) |
| tass | 5:445d2fc04784 | 284 | return -1; |
| tass | 5:445d2fc04784 | 285 | |
| tass | 5:445d2fc04784 | 286 | client = (struct socket *)pico_zalloc(sizeof(struct socket)); |
| tass | 5:445d2fc04784 | 287 | |
| tass | 5:445d2fc04784 | 288 | if(!client) |
| tass | 5:445d2fc04784 | 289 | return -1; |
| tass | 5:445d2fc04784 | 290 | |
| tass | 5:445d2fc04784 | 291 | client->sock = sck; |
| tass | 5:445d2fc04784 | 292 | client->proto = _sock->proto; |
| tass | 5:445d2fc04784 | 293 | client->state = SOCK_CONNECTED; |
| tass | 5:445d2fc04784 | 294 | client->socket = (int)sck; |
| tass | 5:445d2fc04784 | 295 | client->mutex = new PicoCondition(); |
| tass | 5:445d2fc04784 | 296 | |
| tass | 5:445d2fc04784 | 297 | pico_tree_insert(&sockTree,client); |
| tass | 5:445d2fc04784 | 298 | |
| tass | 5:445d2fc04784 | 299 | return client->socket; |
| tass | 5:445d2fc04784 | 300 | } |
| tass | 5:445d2fc04784 | 301 | |
| tass | 5:445d2fc04784 | 302 | int picotcp_close(int sock) |
| tass | 5:445d2fc04784 | 303 | { |
| tass | 5:445d2fc04784 | 304 | struct socket * _sock = findAfterId(sock); |
| tass | 5:445d2fc04784 | 305 | int ret = 0; |
| tass | 5:445d2fc04784 | 306 | |
| tass | 5:445d2fc04784 | 307 | VALIDATE_NULL(_sock); |
| tass | 5:445d2fc04784 | 308 | pico_socket_close(_sock->sock); |
| tass | 5:445d2fc04784 | 309 | if(_sock->state == SOCK_CONNECTED && _sock->proto == PICO_PROTO_TCP) |
| tass | 5:445d2fc04784 | 310 | { |
| tass | 5:445d2fc04784 | 311 | ret = waitForEvent(_sock,PICO_SOCK_EV_CLOSE | PICO_SOCK_EV_FIN,1); |
| tass | 5:445d2fc04784 | 312 | } |
| tass | 5:445d2fc04784 | 313 | |
| tass | 5:445d2fc04784 | 314 | |
| tass | 5:445d2fc04784 | 315 | if(_sock->mutex) |
| tass | 5:445d2fc04784 | 316 | { |
| tass | 5:445d2fc04784 | 317 | delete(_sock->mutex); |
| tass | 5:445d2fc04784 | 318 | } |
| tass | 5:445d2fc04784 | 319 | |
| tass | 5:445d2fc04784 | 320 | pico_tree_delete(&sockTree,_sock); |
| tass | 5:445d2fc04784 | 321 | pico_free(_sock); |
| tass | 5:445d2fc04784 | 322 | |
| tass | 5:445d2fc04784 | 323 | return ret; |
| tass | 5:445d2fc04784 | 324 | } |
| tass | 5:445d2fc04784 | 325 | |
| tass | 5:445d2fc04784 | 326 | int picotcp_send(int sock,void * buff, int len, int flags) |
| tass | 5:445d2fc04784 | 327 | { |
| tass | 5:445d2fc04784 | 328 | struct socket * _sock = findAfterId(sock); |
| tass | 5:445d2fc04784 | 329 | |
| tass | 5:445d2fc04784 | 330 | VALIDATE_NULL(_sock); |
| tass | 5:445d2fc04784 | 331 | |
| tass | 5:445d2fc04784 | 332 | if(_sock->state != SOCK_BOUND && _sock->state != SOCK_CONNECTED) |
| tass | 5:445d2fc04784 | 333 | { |
| tass | 5:445d2fc04784 | 334 | printf("Bad state\n"); |
| tass | 5:445d2fc04784 | 335 | return -1; |
| tass | 5:445d2fc04784 | 336 | } |
| tass | 5:445d2fc04784 | 337 | if(_sock->proto == PICO_PROTO_TCP) |
| tass | 5:445d2fc04784 | 338 | { |
| tass | 5:445d2fc04784 | 339 | if(waitForEvent(_sock,PICO_SOCK_EV_WR,1)) |
| tass | 5:445d2fc04784 | 340 | return -1; |
| tass | 5:445d2fc04784 | 341 | } |
| tass | 5:445d2fc04784 | 342 | //printf("Sending...\n"); |
| tass | 5:445d2fc04784 | 343 | return pico_socket_send(_sock->sock,buff,len); |
| tass | 5:445d2fc04784 | 344 | } |
| tass | 5:445d2fc04784 | 345 | |
| tass | 5:445d2fc04784 | 346 | int picotcp_recv(int sock,void * buff, int len, int flags) |
| tass | 5:445d2fc04784 | 347 | { |
| tass | 5:445d2fc04784 | 348 | struct socket * _sock = findAfterId(sock); |
| tass | 5:445d2fc04784 | 349 | |
| tass | 5:445d2fc04784 | 350 | VALIDATE_NULL(_sock); |
| tass | 5:445d2fc04784 | 351 | |
| tass | 5:445d2fc04784 | 352 | if(_sock->state != SOCK_BOUND && _sock->state != SOCK_CONNECTED) |
| tass | 5:445d2fc04784 | 353 | return -1; |
| tass | 5:445d2fc04784 | 354 | |
| tass | 5:445d2fc04784 | 355 | if(waitForEvent(_sock,PICO_SOCK_EV_RD,1)) |
| tass | 5:445d2fc04784 | 356 | return -1; |
| tass | 5:445d2fc04784 | 357 | |
| tass | 5:445d2fc04784 | 358 | return pico_socket_recv(_sock->sock,buff,len); |
| tass | 5:445d2fc04784 | 359 | } |
| tass | 5:445d2fc04784 | 360 | |
| tass | 5:445d2fc04784 | 361 | int picotcp_sendto(int sock,void * buff, int len, struct sockaddr *orig, socklen_t socklen) |
| tass | 5:445d2fc04784 | 362 | { |
| tass | 5:445d2fc04784 | 363 | struct socket * _sock = findAfterId(sock); |
| tass | 5:445d2fc04784 | 364 | struct sockaddr_in *s_in = (struct sockaddr_in *) orig; |
| tass | 5:445d2fc04784 | 365 | |
| tass | 5:445d2fc04784 | 366 | VALIDATE_NULL(_sock); |
| tass | 5:445d2fc04784 | 367 | VALIDATE_ONE(_sock->proto,PICO_PROTO_UDP); |
| tass | 5:445d2fc04784 | 368 | VALIDATE_NULL(len); |
| tass | 5:445d2fc04784 | 369 | VALIDATE_NULL(socklen); |
| tass | 5:445d2fc04784 | 370 | printf("Sendto : parameters correct !\n"); |
| tass | 5:445d2fc04784 | 371 | |
| tass | 5:445d2fc04784 | 372 | return pico_socket_sendto(_sock->sock,buff,len,(void *)&s_in->sin_addr,s_in->sin_port); |
| tass | 5:445d2fc04784 | 373 | } |
| tass | 5:445d2fc04784 | 374 | |
| tass | 5:445d2fc04784 | 375 | int picotcp_recvfrom(int sock,void * buff, int len, struct sockaddr *orig, socklen_t *socklen) |
| tass | 5:445d2fc04784 | 376 | { |
| tass | 5:445d2fc04784 | 377 | struct socket * _sock = findAfterId(sock); |
| tass | 5:445d2fc04784 | 378 | struct sockaddr_in *s_in = (struct sockaddr_in *) orig; |
| tass | 5:445d2fc04784 | 379 | |
| tass | 5:445d2fc04784 | 380 | VALIDATE_NULL(_sock); |
| tass | 5:445d2fc04784 | 381 | VALIDATE_ONE(_sock->proto,PICO_PROTO_UDP); |
| tass | 5:445d2fc04784 | 382 | VALIDATE_NULL(socklen); |
| tass | 5:445d2fc04784 | 383 | |
| tass | 5:445d2fc04784 | 384 | if(waitForEvent(_sock,PICO_SOCK_EV_RD,1)) |
| tass | 5:445d2fc04784 | 385 | return -1; |
| tass | 5:445d2fc04784 | 386 | return pico_socket_recvfrom(_sock->sock,buff,len,(void *)&s_in->sin_addr,(uint16_t *)&s_in->sin_port); |
| tass | 5:445d2fc04784 | 387 | } |
| tass | 5:445d2fc04784 | 388 | |
| tass | 5:445d2fc04784 | 389 | int picotcp_read(int sock,void *buf, int len) |
| tass | 5:445d2fc04784 | 390 | { |
| tass | 5:445d2fc04784 | 391 | struct socket * _sock = findAfterId(sock); |
| daniele | 11:58acd53df75c | 392 | int r, tot_len = 0; |
| tass | 5:445d2fc04784 | 393 | VALIDATE_NULL(_sock); |
| tass | 5:445d2fc04784 | 394 | VALIDATE_ONE(_sock->proto,PICO_PROTO_TCP); |
| tass | 5:445d2fc04784 | 395 | VALIDATE_ONE(_sock->state, SOCK_CONNECTED); |
| tass | 5:445d2fc04784 | 396 | |
| tass | 5:445d2fc04784 | 397 | if(waitForEvent(_sock,PICO_SOCK_EV_RD,1)) |
| tass | 5:445d2fc04784 | 398 | return -1; |
| daniele | 11:58acd53df75c | 399 | while(tot_len < len) { |
| daniele | 11:58acd53df75c | 400 | r = pico_socket_read(_sock->sock, (unsigned char *)buf + tot_len, len - tot_len); |
| daniele | 11:58acd53df75c | 401 | if (r > 0) |
| daniele | 11:58acd53df75c | 402 | tot_len += r; |
| daniele | 11:58acd53df75c | 403 | else break; |
| daniele | 11:58acd53df75c | 404 | } |
| daniele | 11:58acd53df75c | 405 | return tot_len; |
| tass | 5:445d2fc04784 | 406 | } |
| tass | 5:445d2fc04784 | 407 | |
| tass | 5:445d2fc04784 | 408 | int picotcp_write(int sock,void *buf, int len) |
| tass | 5:445d2fc04784 | 409 | { |
| tass | 5:445d2fc04784 | 410 | struct socket * _sock = findAfterId(sock); |
| daniele | 11:58acd53df75c | 411 | int r, tot_len = 0; |
| tass | 5:445d2fc04784 | 412 | |
| tass | 5:445d2fc04784 | 413 | VALIDATE_NULL(_sock); |
| tass | 5:445d2fc04784 | 414 | VALIDATE_ONE(_sock->proto,PICO_PROTO_TCP); |
| tass | 5:445d2fc04784 | 415 | VALIDATE_ONE(_sock->state, SOCK_CONNECTED); |
| tass | 5:445d2fc04784 | 416 | if(waitForEvent(_sock,PICO_SOCK_EV_WR,1)) |
| tass | 5:445d2fc04784 | 417 | return -1; |
| daniele | 11:58acd53df75c | 418 | |
| daniele | 11:58acd53df75c | 419 | if(waitForEvent(_sock,PICO_SOCK_EV_WR,1)) |
| daniele | 11:58acd53df75c | 420 | return -1; |
| daniele | 11:58acd53df75c | 421 | while(tot_len < len) { |
| daniele | 11:58acd53df75c | 422 | r = pico_socket_write(_sock->sock, (unsigned char *)buf + tot_len, len - tot_len); |
| daniele | 11:58acd53df75c | 423 | if (r > 0) |
| daniele | 11:58acd53df75c | 424 | tot_len += r; |
| daniele | 11:58acd53df75c | 425 | else break; |
| daniele | 11:58acd53df75c | 426 | } |
| daniele | 11:58acd53df75c | 427 | return tot_len; |
| tass | 5:445d2fc04784 | 428 | } |
| tass | 5:445d2fc04784 | 429 | |
| tass | 5:445d2fc04784 | 430 | int picotcp_setsockopt(int sock, int option, void *value) |
| tass | 5:445d2fc04784 | 431 | { |
| tass | 5:445d2fc04784 | 432 | struct socket * _sock = findAfterId(sock); |
| tass | 5:445d2fc04784 | 433 | |
| tass | 5:445d2fc04784 | 434 | VALIDATE_NULL(_sock); |
| tass | 5:445d2fc04784 | 435 | |
| tass | 5:445d2fc04784 | 436 | return pico_socket_setoption(_sock->sock,option,value); |
| tass | 5:445d2fc04784 | 437 | } |
| tass | 5:445d2fc04784 | 438 | |
| tass | 5:445d2fc04784 | 439 | int picotcp_getsockopt(int sock, int option, void *value) |
| tass | 5:445d2fc04784 | 440 | { |
| tass | 5:445d2fc04784 | 441 | struct socket * _sock = findAfterId(sock); |
| tass | 5:445d2fc04784 | 442 | |
| tass | 5:445d2fc04784 | 443 | VALIDATE_NULL(_sock); |
| tass | 5:445d2fc04784 | 444 | |
| tass | 5:445d2fc04784 | 445 | return pico_socket_getoption(_sock->sock,option,value); |
| tass | 5:445d2fc04784 | 446 | } |
| tass | 5:445d2fc04784 | 447 | |
| tass | 5:445d2fc04784 | 448 | int picotcp_select(int sock, struct timeval *timeout, int read, int write) |
| tass | 5:445d2fc04784 | 449 | { |
| tass | 5:445d2fc04784 | 450 | uint32_t ms = 1000 * timeout->tv_sec + timeout->tv_usec / 1000; |
| tass | 5:445d2fc04784 | 451 | uint32_t now = PICO_TIME_MS(); |
| tass | 5:445d2fc04784 | 452 | int ret = 0; |
| tass | 5:445d2fc04784 | 453 | |
| tass | 5:445d2fc04784 | 454 | struct socket * _sock = findAfterId(sock); |
| tass | 5:445d2fc04784 | 455 | VALIDATE_NULL(_sock); |
| tass | 5:445d2fc04784 | 456 | |
| tass | 5:445d2fc04784 | 457 | // tell the dispatcher what events are you waiting for |
| tass | 5:445d2fc04784 | 458 | if(read) |
| tass | 5:445d2fc04784 | 459 | SET_EVENT(_sock->event,PICO_SOCK_EV_RD|PICO_SOCK_EV_CONN); |
| tass | 5:445d2fc04784 | 460 | if(write) |
| tass | 5:445d2fc04784 | 461 | SET_EVENT(_sock->event,PICO_SOCK_EV_WR); |
| tass | 5:445d2fc04784 | 462 | |
| tass | 5:445d2fc04784 | 463 | while (PICO_TIME_MS() < now + ms) { |
| tass | 5:445d2fc04784 | 464 | if (_sock->mutex->lock(1) == false) { |
| daniele | 11:58acd53df75c | 465 | //Thread::wait(1); |
| tass | 5:445d2fc04784 | 466 | continue; |
| tass | 5:445d2fc04784 | 467 | } |
| tass | 5:445d2fc04784 | 468 | |
| tass | 5:445d2fc04784 | 469 | if (read && EVENT_PENDING(_sock->revent,PICO_SOCK_EV_RD|PICO_SOCK_EV_CONN)) |
| tass | 5:445d2fc04784 | 470 | { |
| tass | 5:445d2fc04784 | 471 | RESET_EVENT(_sock->revent,PICO_SOCK_EV_RD|PICO_SOCK_EV_CONN); |
| tass | 5:445d2fc04784 | 472 | ret++; |
| tass | 5:445d2fc04784 | 473 | } |
| tass | 5:445d2fc04784 | 474 | if (write && EVENT_PENDING(_sock->revent, PICO_SOCK_EV_WR)) |
| tass | 5:445d2fc04784 | 475 | { |
| tass | 5:445d2fc04784 | 476 | RESET_EVENT(_sock->revent,PICO_SOCK_EV_WR); |
| tass | 5:445d2fc04784 | 477 | ret++; |
| tass | 5:445d2fc04784 | 478 | } |
| tass | 5:445d2fc04784 | 479 | if (ret > 0) |
| tass | 5:445d2fc04784 | 480 | break; |
| tass | 5:445d2fc04784 | 481 | } |
| tass | 5:445d2fc04784 | 482 | |
| tass | 5:445d2fc04784 | 483 | if(read) |
| tass | 5:445d2fc04784 | 484 | RESET_EVENT(_sock->event,PICO_SOCK_EV_RD|PICO_SOCK_EV_CONN); |
| tass | 5:445d2fc04784 | 485 | if(write) |
| tass | 5:445d2fc04784 | 486 | RESET_EVENT(_sock->event,PICO_SOCK_EV_WR); |
| tass | 5:445d2fc04784 | 487 | |
| tass | 5:445d2fc04784 | 488 | return ret; |
| tass | 5:445d2fc04784 | 489 | } |
| tass | 5:445d2fc04784 | 490 | |
| tass | 5:445d2fc04784 | 491 | int picotcp_setblocking(int sock, int blocking) |
| tass | 5:445d2fc04784 | 492 | { |
| tass | 5:445d2fc04784 | 493 | struct socket * _sock = findAfterId(sock); |
| tass | 5:445d2fc04784 | 494 | VALIDATE_NULL(_sock); |
| tass | 5:445d2fc04784 | 495 | |
| tass | 5:445d2fc04784 | 496 | _sock->blocking = blocking; |
| tass | 5:445d2fc04784 | 497 | |
| tass | 5:445d2fc04784 | 498 | return 0; |
| tass | 5:445d2fc04784 | 499 | } |
| tass | 5:445d2fc04784 | 500 | |
| tass | 5:445d2fc04784 | 501 | |
| tass | 5:445d2fc04784 | 502 | int picotcp_join_multicast(int sock,const char* address,const char* local) |
| tass | 5:445d2fc04784 | 503 | { |
| tass | 5:445d2fc04784 | 504 | struct socket * _sock = findAfterId(sock); |
| tass | 5:445d2fc04784 | 505 | struct pico_ip4 inaddr_dst, inaddr_link; |
| tass | 5:445d2fc04784 | 506 | struct pico_ip_mreq mreq = {{0},{0}}; |
| tass | 5:445d2fc04784 | 507 | VALIDATE_NULL(_sock); |
| tass | 5:445d2fc04784 | 508 | pico_string_to_ipv4(address, &inaddr_dst.addr); |
| tass | 5:445d2fc04784 | 509 | pico_string_to_ipv4(local, &inaddr_link.addr); // local ip address ? |
| tass | 5:445d2fc04784 | 510 | mreq.mcast_group_addr = inaddr_dst; |
| tass | 5:445d2fc04784 | 511 | mreq.mcast_link_addr = inaddr_link; |
| tass | 5:445d2fc04784 | 512 | return pico_socket_setoption(_sock->sock, PICO_IP_ADD_MEMBERSHIP, &mreq); |
| tass | 5:445d2fc04784 | 513 | } |
| tass | 5:445d2fc04784 | 514 | |
| tass | 5:445d2fc04784 | 515 | /************************** PICO BSD DNS LAYER **************************/ |
| tass | 5:445d2fc04784 | 516 | |
| tass | 5:445d2fc04784 | 517 | struct dnsQuery |
| tass | 5:445d2fc04784 | 518 | { |
| tass | 5:445d2fc04784 | 519 | PicoCondition * mutex; |
| tass | 5:445d2fc04784 | 520 | char * result; |
| tass | 5:445d2fc04784 | 521 | }; |
| tass | 5:445d2fc04784 | 522 | |
| tass | 5:445d2fc04784 | 523 | static void dispatch_dns(char *ip, void *arg) |
| tass | 5:445d2fc04784 | 524 | { |
| tass | 5:445d2fc04784 | 525 | ((struct dnsQuery *)arg)->result = ip; |
| tass | 5:445d2fc04784 | 526 | printf("Disp : %x\n",((struct dnsQuery *)arg)->mutex); |
| tass | 5:445d2fc04784 | 527 | ((struct dnsQuery *)arg)->mutex->unlock(); |
| tass | 5:445d2fc04784 | 528 | printf("Result : %s\n",ip); |
| tass | 5:445d2fc04784 | 529 | } |
| tass | 5:445d2fc04784 | 530 | |
| tass | 5:445d2fc04784 | 531 | struct hostent * picotcp_gethostbyname(const char *url) |
| tass | 5:445d2fc04784 | 532 | { |
| tass | 5:445d2fc04784 | 533 | struct dnsQuery * dns; |
| tass | 5:445d2fc04784 | 534 | struct hostent * hresult = NULL; |
| tass | 5:445d2fc04784 | 535 | |
| tass | 5:445d2fc04784 | 536 | dns = (struct dnsQuery *)pico_zalloc(sizeof(struct dnsQuery)); |
| tass | 5:445d2fc04784 | 537 | |
| tass | 5:445d2fc04784 | 538 | if(!dns) |
| tass | 5:445d2fc04784 | 539 | return NULL; |
| tass | 5:445d2fc04784 | 540 | |
| tass | 5:445d2fc04784 | 541 | dns->mutex = new PicoCondition(); |
| tass | 5:445d2fc04784 | 542 | |
| tass | 5:445d2fc04784 | 543 | pico_dns_client_getaddr(url,dispatch_dns,(void *)dns); |
| tass | 5:445d2fc04784 | 544 | dns->mutex->lock(); |
| tass | 5:445d2fc04784 | 545 | |
| tass | 5:445d2fc04784 | 546 | if(dns->result) |
| tass | 5:445d2fc04784 | 547 | { |
| tass | 5:445d2fc04784 | 548 | hresult = (struct hostent *)pico_zalloc(sizeof(struct hostent)); |
| tass | 5:445d2fc04784 | 549 | hresult->h_addrtype = AF_INET; // ipv4 |
| tass | 5:445d2fc04784 | 550 | // make a copy of the name |
| tass | 5:445d2fc04784 | 551 | hresult->h_name = new char[strlen(url)+1]; |
| tass | 5:445d2fc04784 | 552 | memcpy(hresult->h_name,url,strlen(url)+1); |
| tass | 5:445d2fc04784 | 553 | hresult->h_aliases = NULL; |
| tass | 5:445d2fc04784 | 554 | // address list |
| tass | 5:445d2fc04784 | 555 | hresult->h_addr_list = new char* [2]; |
| tass | 5:445d2fc04784 | 556 | hresult->h_addr_list[0] = dns->result; |
| tass | 5:445d2fc04784 | 557 | hresult->h_addr_list[1] = NULL; |
| tass | 5:445d2fc04784 | 558 | } |
| tass | 5:445d2fc04784 | 559 | |
| tass | 5:445d2fc04784 | 560 | delete(dns->mutex); |
| tass | 5:445d2fc04784 | 561 | pico_free(dns); |
| tass | 5:445d2fc04784 | 562 | // |
| tass | 5:445d2fc04784 | 563 | return hresult; |
| tass | 5:445d2fc04784 | 564 | } |
| tass | 5:445d2fc04784 | 565 | |
| tass | 5:445d2fc04784 | 566 | char * picotcp_gethostbyaddr(const char *ip) |
| tass | 5:445d2fc04784 | 567 | { |
| tass | 5:445d2fc04784 | 568 | struct dnsQuery * dns; |
| tass | 5:445d2fc04784 | 569 | char * result; |
| tass | 5:445d2fc04784 | 570 | dns = (struct dnsQuery *)pico_zalloc(sizeof(struct dnsQuery)); |
| tass | 5:445d2fc04784 | 571 | int tries = 5u; |
| tass | 5:445d2fc04784 | 572 | |
| tass | 5:445d2fc04784 | 573 | if(!dns) |
| tass | 5:445d2fc04784 | 574 | return NULL; |
| tass | 5:445d2fc04784 | 575 | |
| tass | 5:445d2fc04784 | 576 | dns->mutex = new PicoCondition(); |
| tass | 5:445d2fc04784 | 577 | |
| tass | 5:445d2fc04784 | 578 | pico_dns_client_getname(ip,dispatch_dns,(void *)dns); |
| tass | 5:445d2fc04784 | 579 | |
| tass | 5:445d2fc04784 | 580 | while(tries>0) |
| tass | 5:445d2fc04784 | 581 | { |
| tass | 5:445d2fc04784 | 582 | if(dns->mutex->lock() == false) |
| tass | 5:445d2fc04784 | 583 | tries--; |
| tass | 5:445d2fc04784 | 584 | else |
| tass | 5:445d2fc04784 | 585 | break; |
| tass | 5:445d2fc04784 | 586 | } |
| tass | 5:445d2fc04784 | 587 | |
| tass | 5:445d2fc04784 | 588 | result = dns->result; |
| tass | 5:445d2fc04784 | 589 | delete(dns->mutex); |
| tass | 5:445d2fc04784 | 590 | pico_free(dns); |
| tass | 5:445d2fc04784 | 591 | |
| tass | 5:445d2fc04784 | 592 | return result; |
| tass | 5:445d2fc04784 | 593 | } |
| tass | 5:445d2fc04784 | 594 | |
| tass | 5:445d2fc04784 | 595 | |
| tass | 5:445d2fc04784 | 596 | static void picotcp_loop(void const *args) |
| tass | 5:445d2fc04784 | 597 | { |
| tass | 5:445d2fc04784 | 598 | while(1) { |
| tass | 5:445d2fc04784 | 599 | pico_stack_tick(); |
| tass | 5:445d2fc04784 | 600 | Thread::wait(1); |
| tass | 5:445d2fc04784 | 601 | } |
| tass | 5:445d2fc04784 | 602 | } |
| tass | 5:445d2fc04784 | 603 | |
| tass | 5:445d2fc04784 | 604 | static Thread * pico_thread; |
| tass | 5:445d2fc04784 | 605 | |
| tass | 5:445d2fc04784 | 606 | void picotcp_init(void) |
| tass | 5:445d2fc04784 | 607 | { |
| tass | 5:445d2fc04784 | 608 | //Thread pico_thread(picotcp_loop); |
| tass | 5:445d2fc04784 | 609 | pico_thread= new Thread(picotcp_loop); |
| tass | 5:445d2fc04784 | 610 | // doesn;t this call the ~Thread |
| tass | 5:445d2fc04784 | 611 | } |
| tass | 5:445d2fc04784 | 612 |
