Daniele Lacamera / PicoTCP-Experimental_CDC_ECM_Branch

Fork of PicoTCP by Daniele Lacamera

Committer:
daniele
Date:
Thu Jun 06 15:35:29 2013 +0000
Revision:
17:5292cca5c478
Parent:
16:6893f625e337
Reworked some blocking code

Who changed what in which revision?

UserRevisionLine numberNew 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 13:c6662adea07d 30
tass 13:c6662adea07d 31 static PicoCondition globalLock;
tass 13:c6662adea07d 32 static Mutex globalMutex;
tass 13:c6662adea07d 33
tass 5:445d2fc04784 34 /* TODO: Sync blocking from here to blocking from Socket */
tass 5:445d2fc04784 35
tass 5:445d2fc04784 36 static struct socket dummy;
tass 5:445d2fc04784 37 #define MAKE_SOCKET(x) ((struct socket *)x)
tass 5:445d2fc04784 38
tass 5:445d2fc04784 39 static int compareSock(void *ka, void *kb)
tass 5:445d2fc04784 40 {
tass 5:445d2fc04784 41 return MAKE_SOCKET(ka)->socket - MAKE_SOCKET(kb)->socket;
tass 5:445d2fc04784 42 }
tass 5:445d2fc04784 43
tass 5:445d2fc04784 44 PICO_TREE_DECLARE(sockTree,compareSock);
tass 5:445d2fc04784 45
tass 5:445d2fc04784 46 #define VALIDATE_NULL(param) \
tass 5:445d2fc04784 47 if(!param) \
tass 5:445d2fc04784 48 { \
tass 5:445d2fc04784 49 return -1; \
tass 5:445d2fc04784 50 }
tass 5:445d2fc04784 51
tass 5:445d2fc04784 52 #define VALIDATE_ONE(param,value) \
tass 5:445d2fc04784 53 if(param != value) { \
tass 5:445d2fc04784 54 pico_err = PICO_ERR_EINVAL; \
tass 5:445d2fc04784 55 return -1; \
tass 5:445d2fc04784 56 }
tass 5:445d2fc04784 57
tass 5:445d2fc04784 58 #define VALIDATE_TWO(param,value1,value2) \
tass 5:445d2fc04784 59 if(param != value1 && param != value2) { \
tass 5:445d2fc04784 60 pico_err = PICO_ERR_EINVAL; \
tass 5:445d2fc04784 61 return -1; \
tass 5:445d2fc04784 62 }
tass 5:445d2fc04784 63
tass 5:445d2fc04784 64 /* PRIVATE FUNCTIONS */
tass 5:445d2fc04784 65
tass 5:445d2fc04784 66 static inline struct socket * findAfterId(int sock)
tass 5:445d2fc04784 67 {
tass 5:445d2fc04784 68 dummy.socket = sock;
tass 5:445d2fc04784 69 return (struct socket *)pico_tree_findKey(&sockTree,&dummy);
tass 5:445d2fc04784 70 }
tass 5:445d2fc04784 71
tass 5:445d2fc04784 72 static inline struct socket * findAfterSocket(struct pico_socket * sock)
tass 5:445d2fc04784 73 {
tass 5:445d2fc04784 74 struct pico_tree_node * index;
tass 5:445d2fc04784 75
tass 5:445d2fc04784 76 pico_tree_foreach(index,&sockTree)
tass 5:445d2fc04784 77 {
tass 5:445d2fc04784 78 if( MAKE_SOCKET(index->keyValue)->sock == sock )
tass 5:445d2fc04784 79 return (struct socket *)index->keyValue;
tass 5:445d2fc04784 80 }
tass 5:445d2fc04784 81 return NULL;
tass 5:445d2fc04784 82 }
tass 5:445d2fc04784 83
tass 5:445d2fc04784 84 static inline int waitForEvent(struct socket * sock, uint16_t event, uint8_t clear)
tass 5:445d2fc04784 85 {
tass 5:445d2fc04784 86 int retValue = 0;
daniele 17:5292cca5c478 87 printf("Entering wait...\n");
daniele 17:5292cca5c478 88 if ((EVENT_PENDING(sock->revent, event)) == 0) {
daniele 17:5292cca5c478 89 SET_EVENT(sock->event, event);
daniele 17:5292cca5c478 90 while(1) {
daniele 17:5292cca5c478 91 sock->mutex->lock();
daniele 17:5292cca5c478 92 printf("Unlocked! EXP: %x EV: %x\n", event, sock->revent);
daniele 17:5292cca5c478 93 if (EVENT_PENDING(sock->revent, event))
daniele 17:5292cca5c478 94 break;
daniele 17:5292cca5c478 95 if (EVENT_PENDING(sock->revent, PICO_SOCK_EV_ERR | PICO_SOCK_EV_FIN | PICO_SOCK_EV_CLOSE) != 0) {
daniele 17:5292cca5c478 96 retValue = -1;
daniele 17:5292cca5c478 97 break;
daniele 17:5292cca5c478 98 }
daniele 17:5292cca5c478 99 printf("Re-locking.\n");
tass 5:445d2fc04784 100 }
tass 5:445d2fc04784 101 }
daniele 17:5292cca5c478 102 printf("... and returning.\n");
daniele 17:5292cca5c478 103 if(clear)
daniele 17:5292cca5c478 104 RESET_EVENT(sock->revent, event);
tass 5:445d2fc04784 105 return retValue;
tass 5:445d2fc04784 106 }
daniele 17:5292cca5c478 107
tass 5:445d2fc04784 108 static void dispatch_socket(uint16_t ev, struct pico_socket * sock)
tass 5:445d2fc04784 109 {
tass 5:445d2fc04784 110 struct socket * _sock = findAfterSocket(sock);
daniele 17:5292cca5c478 111 printf("Dispatching...\n");
tass 5:445d2fc04784 112
tass 5:445d2fc04784 113 if(!_sock)
tass 13:c6662adea07d 114 {
tass 13:c6662adea07d 115 if( (ev & PICO_SOCK_EV_ERR) || (ev & PICO_SOCK_EV_CLOSE) || (ev & PICO_SOCK_EV_FIN) )
tass 13:c6662adea07d 116 pico_socket_close(sock);
tass 13:c6662adea07d 117 }
tass 5:445d2fc04784 118
tass 5:445d2fc04784 119 SET_EVENT(_sock->revent,ev);
daniele 17:5292cca5c478 120 printf("Dispatcher unlocks event %x\n", ev);
daniele 17:5292cca5c478 121 _sock->mutex->unlock();
daniele 17:5292cca5c478 122 globalLock.lock();
tass 5:445d2fc04784 123 }
tass 5:445d2fc04784 124
tass 5:445d2fc04784 125 /* PUBLIC FUNCTIONS */
tass 5:445d2fc04784 126
tass 5:445d2fc04784 127 int picotcp_socket(uint16_t net, uint16_t proto, uint16_t flags)
tass 5:445d2fc04784 128 {
tass 5:445d2fc04784 129 struct socket * sock = NULL;
tass 5:445d2fc04784 130
tass 5:445d2fc04784 131 net = (net == AF_INET ? PICO_PROTO_IPV4 : (net == AF_INET6 ? PICO_PROTO_IPV6 : -1));
tass 5:445d2fc04784 132 proto = (proto == SOCK_DGRAM ? PICO_PROTO_UDP : (proto == SOCK_STREAM ? PICO_PROTO_TCP : -1));
tass 5:445d2fc04784 133
tass 5:445d2fc04784 134 VALIDATE_TWO(net,PICO_PROTO_IPV4,PICO_PROTO_IPV6);
tass 5:445d2fc04784 135 VALIDATE_TWO(proto,PICO_PROTO_TCP,PICO_PROTO_UDP);
tass 5:445d2fc04784 136 //printf("Parameters are correct...\n");
tass 5:445d2fc04784 137 sock = (struct socket*)pico_zalloc(sizeof(struct socket));
tass 5:445d2fc04784 138 VALIDATE_NULL(sock);
tass 5:445d2fc04784 139
tass 5:445d2fc04784 140 sock->proto = proto;
tass 5:445d2fc04784 141 sock->sock = pico_socket_open(net,proto,&dispatch_socket);
tass 5:445d2fc04784 142
tass 5:445d2fc04784 143 if(!sock->sock)
tass 5:445d2fc04784 144 {
tass 5:445d2fc04784 145 pico_free(sock);
tass 5:445d2fc04784 146 return -1;
tass 5:445d2fc04784 147 }
tass 5:445d2fc04784 148
tass 5:445d2fc04784 149 sock->socket = (int)sock;
tass 5:445d2fc04784 150 sock->mutex = new PicoCondition();
tass 13:c6662adea07d 151
tass 13:c6662adea07d 152
tass 13:c6662adea07d 153
tass 5:445d2fc04784 154 if(!sock->mutex)
tass 5:445d2fc04784 155 {
tass 5:445d2fc04784 156 pico_socket_close(sock->sock);
tass 5:445d2fc04784 157 pico_free(sock);
tass 5:445d2fc04784 158 return -1;
tass 5:445d2fc04784 159 }
tass 13:c6662adea07d 160
tass 13:c6662adea07d 161 globalMutex.lock();
tass 5:445d2fc04784 162 pico_tree_insert(&sockTree,sock);
tass 13:c6662adea07d 163 globalMutex.unlock();
tass 13:c6662adea07d 164
tass 5:445d2fc04784 165 sock->state = SOCK_OPEN;
tass 5:445d2fc04784 166
tass 5:445d2fc04784 167 return sock->socket;
tass 5:445d2fc04784 168 }
tass 5:445d2fc04784 169
tass 5:445d2fc04784 170 int picotcp_bind(int sock, struct sockaddr *local_addr, socklen_t len)
tass 5:445d2fc04784 171 {
tass 5:445d2fc04784 172 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 173 int ret;
tass 5:445d2fc04784 174 struct sockaddr_in *s_in = (struct sockaddr_in *) local_addr;
tass 5:445d2fc04784 175
tass 5:445d2fc04784 176 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 177 VALIDATE_NULL(local_addr);
tass 5:445d2fc04784 178 VALIDATE_NULL(len);
tass 5:445d2fc04784 179
tass 5:445d2fc04784 180 ret = pico_socket_bind(_sock->sock,(void *)&s_in->sin_addr,(uint16_t *)&s_in->sin_port);
tass 5:445d2fc04784 181
tass 5:445d2fc04784 182 if(ret == 0)
tass 5:445d2fc04784 183 _sock->state = SOCK_BOUND;
tass 5:445d2fc04784 184
tass 5:445d2fc04784 185 return ret;
tass 5:445d2fc04784 186 }
tass 5:445d2fc04784 187
tass 5:445d2fc04784 188 int picotcp_state(int sock)
tass 5:445d2fc04784 189 {
tass 5:445d2fc04784 190 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 191 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 192
tass 5:445d2fc04784 193 return _sock->state;
tass 5:445d2fc04784 194 }
tass 5:445d2fc04784 195
tass 5:445d2fc04784 196 int picotcp_listen(int sock, int queue)
tass 5:445d2fc04784 197 {
tass 5:445d2fc04784 198 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 199 int ret;
tass 5:445d2fc04784 200
tass 5:445d2fc04784 201 if(queue <= 0)
tass 5:445d2fc04784 202 queue = DEFAULT_BACKLOG;
tass 5:445d2fc04784 203
tass 5:445d2fc04784 204 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 205 VALIDATE_ONE(_sock->state,SOCK_BOUND);
tass 5:445d2fc04784 206
tass 5:445d2fc04784 207 ret = pico_socket_listen(_sock->sock,queue);
tass 5:445d2fc04784 208
tass 5:445d2fc04784 209 if(!ret)
tass 5:445d2fc04784 210 _sock->state = SOCK_LISTEN;
tass 5:445d2fc04784 211
tass 5:445d2fc04784 212 return ret;
tass 5:445d2fc04784 213 }
tass 5:445d2fc04784 214
tass 5:445d2fc04784 215 int picotcp_connect(int sock, struct sockaddr *srv_addr, socklen_t len)
tass 5:445d2fc04784 216 {
tass 5:445d2fc04784 217 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 218 int ret;
tass 5:445d2fc04784 219 struct sockaddr_in *s_in = (struct sockaddr_in *) srv_addr;
tass 5:445d2fc04784 220
tass 5:445d2fc04784 221 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 222 VALIDATE_NULL(len);
tass 5:445d2fc04784 223
tass 5:445d2fc04784 224 ret = pico_socket_connect(_sock->sock,(void*)&s_in->sin_addr,s_in->sin_port);
tass 5:445d2fc04784 225
tass 5:445d2fc04784 226 if(ret < 0)
tass 5:445d2fc04784 227 {
tass 5:445d2fc04784 228 printf("connect error\n");
tass 5:445d2fc04784 229 return -1;
tass 5:445d2fc04784 230 }
tass 5:445d2fc04784 231
tass 5:445d2fc04784 232 if(_sock->proto == PICO_PROTO_TCP)
tass 5:445d2fc04784 233 {
tass 5:445d2fc04784 234 if(waitForEvent(_sock,PICO_SOCK_EV_CONN,1) < 0)
tass 5:445d2fc04784 235 return -1;
tass 5:445d2fc04784 236 }
tass 5:445d2fc04784 237
tass 5:445d2fc04784 238 _sock->state = SOCK_CONNECTED;
tass 5:445d2fc04784 239
tass 5:445d2fc04784 240 return ret;
tass 5:445d2fc04784 241 }
tass 5:445d2fc04784 242
tass 5:445d2fc04784 243 int picotcp_accept(int sock, struct sockaddr *orig, socklen_t *len)
tass 5:445d2fc04784 244 {
tass 5:445d2fc04784 245 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 246 struct socket * client = NULL;
tass 5:445d2fc04784 247 struct pico_socket * sck = NULL;
tass 5:445d2fc04784 248 struct sockaddr_in *s_in = (struct sockaddr_in *) orig;
tass 5:445d2fc04784 249
tass 5:445d2fc04784 250
tass 5:445d2fc04784 251 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 252 VALIDATE_ONE(_sock->proto, PICO_PROTO_TCP);
tass 5:445d2fc04784 253 VALIDATE_ONE(_sock->state, SOCK_LISTEN);
tass 5:445d2fc04784 254 VALIDATE_NULL(len);
tass 5:445d2fc04784 255
tass 5:445d2fc04784 256 if(waitForEvent(_sock,PICO_SOCK_EV_CONN,1))
tass 5:445d2fc04784 257 {
tass 5:445d2fc04784 258 printf("Wait for event failed\n");
tass 5:445d2fc04784 259 return -1;
tass 5:445d2fc04784 260 }
tass 5:445d2fc04784 261
tass 5:445d2fc04784 262 // create new socket and set it directly to connected
tass 5:445d2fc04784 263 sck = pico_socket_accept(_sock->sock,(void *)&s_in->sin_addr,(uint16_t *)&s_in->sin_port);
tass 5:445d2fc04784 264 *len = sizeof(struct sockaddr_in);
tass 5:445d2fc04784 265
tass 5:445d2fc04784 266 if(!sck)
tass 13:c6662adea07d 267 {
tass 13:c6662adea07d 268 globalLock.unlock();
tass 5:445d2fc04784 269 return -1;
tass 13:c6662adea07d 270 }
tass 5:445d2fc04784 271
tass 5:445d2fc04784 272 client = (struct socket *)pico_zalloc(sizeof(struct socket));
tass 5:445d2fc04784 273
tass 5:445d2fc04784 274 if(!client)
tass 13:c6662adea07d 275 {
tass 13:c6662adea07d 276 globalLock.unlock();
tass 5:445d2fc04784 277 return -1;
tass 13:c6662adea07d 278 }
tass 5:445d2fc04784 279
tass 5:445d2fc04784 280 client->sock = sck;
tass 5:445d2fc04784 281 client->proto = _sock->proto;
tass 5:445d2fc04784 282 client->state = SOCK_CONNECTED;
tass 5:445d2fc04784 283 client->socket = (int)sck;
tass 5:445d2fc04784 284 client->mutex = new PicoCondition();
tass 5:445d2fc04784 285
tass 13:c6662adea07d 286 globalMutex.lock();
tass 5:445d2fc04784 287 pico_tree_insert(&sockTree,client);
tass 13:c6662adea07d 288 globalMutex.unlock();
tass 13:c6662adea07d 289
tass 13:c6662adea07d 290 globalLock.unlock();
tass 5:445d2fc04784 291 return client->socket;
tass 5:445d2fc04784 292 }
tass 5:445d2fc04784 293
tass 5:445d2fc04784 294 int picotcp_close(int sock)
tass 5:445d2fc04784 295 {
tass 5:445d2fc04784 296 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 297 int ret = 0;
tass 5:445d2fc04784 298
tass 5:445d2fc04784 299 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 300 pico_socket_close(_sock->sock);
tass 5:445d2fc04784 301 if(_sock->state == SOCK_CONNECTED && _sock->proto == PICO_PROTO_TCP)
tass 5:445d2fc04784 302 {
tass 5:445d2fc04784 303 ret = waitForEvent(_sock,PICO_SOCK_EV_CLOSE | PICO_SOCK_EV_FIN,1);
tass 5:445d2fc04784 304 }
tass 5:445d2fc04784 305
tass 5:445d2fc04784 306
tass 5:445d2fc04784 307 if(_sock->mutex)
tass 5:445d2fc04784 308 {
tass 5:445d2fc04784 309 delete(_sock->mutex);
tass 5:445d2fc04784 310 }
tass 13:c6662adea07d 311 globalMutex.lock();
tass 5:445d2fc04784 312 pico_tree_delete(&sockTree,_sock);
tass 13:c6662adea07d 313 globalMutex.unlock();
tass 5:445d2fc04784 314 pico_free(_sock);
tass 13:c6662adea07d 315
tass 13:c6662adea07d 316
tass 13:c6662adea07d 317 globalLock.unlock();
tass 5:445d2fc04784 318 return ret;
tass 5:445d2fc04784 319 }
tass 5:445d2fc04784 320
tass 5:445d2fc04784 321 int picotcp_send(int sock,void * buff, int len, int flags)
tass 5:445d2fc04784 322 {
tass 5:445d2fc04784 323 struct socket * _sock = findAfterId(sock);
tass 13:c6662adea07d 324 int ret;
tass 5:445d2fc04784 325
tass 5:445d2fc04784 326 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 327
tass 5:445d2fc04784 328 if(_sock->state != SOCK_BOUND && _sock->state != SOCK_CONNECTED)
tass 5:445d2fc04784 329 {
tass 5:445d2fc04784 330 printf("Bad state\n");
tass 5:445d2fc04784 331 return -1;
tass 5:445d2fc04784 332 }
tass 5:445d2fc04784 333 if(_sock->proto == PICO_PROTO_TCP)
tass 5:445d2fc04784 334 {
daniele 17:5292cca5c478 335 if(waitForEvent(_sock,PICO_SOCK_EV_WR,0))
tass 5:445d2fc04784 336 return -1;
tass 5:445d2fc04784 337 }
tass 13:c6662adea07d 338
tass 13:c6662adea07d 339 ret = pico_socket_send(_sock->sock,buff,len);
daniele 17:5292cca5c478 340 if (ret < len)
daniele 17:5292cca5c478 341 RESET_EVENT(_sock->event, PICO_SOCK_EV_WR);
tass 13:c6662adea07d 342 globalLock.unlock();
tass 13:c6662adea07d 343 return ret;
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 13:c6662adea07d 349 int ret;
tass 13:c6662adea07d 350
tass 5:445d2fc04784 351 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 352
tass 5:445d2fc04784 353 if(_sock->state != SOCK_BOUND && _sock->state != SOCK_CONNECTED)
tass 5:445d2fc04784 354 return -1;
tass 5:445d2fc04784 355
daniele 17:5292cca5c478 356 if(waitForEvent(_sock,PICO_SOCK_EV_RD,0))
tass 5:445d2fc04784 357 return -1;
tass 5:445d2fc04784 358
tass 13:c6662adea07d 359 ret = pico_socket_recv(_sock->sock,buff,len);
daniele 17:5292cca5c478 360 if (ret < len)
daniele 17:5292cca5c478 361 RESET_EVENT(_sock->event, PICO_SOCK_EV_RD);
tass 13:c6662adea07d 362
tass 13:c6662adea07d 363 globalLock.unlock();
tass 13:c6662adea07d 364 return ret;
tass 5:445d2fc04784 365 }
tass 5:445d2fc04784 366
tass 5:445d2fc04784 367 int picotcp_sendto(int sock,void * buff, int len, struct sockaddr *orig, socklen_t socklen)
tass 5:445d2fc04784 368 {
tass 5:445d2fc04784 369 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 370 struct sockaddr_in *s_in = (struct sockaddr_in *) orig;
tass 5:445d2fc04784 371
tass 5:445d2fc04784 372 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 373 VALIDATE_ONE(_sock->proto,PICO_PROTO_UDP);
tass 5:445d2fc04784 374 VALIDATE_NULL(len);
tass 5:445d2fc04784 375 VALIDATE_NULL(socklen);
tass 5:445d2fc04784 376 printf("Sendto : parameters correct !\n");
daniele 17:5292cca5c478 377 if(_sock->proto == PICO_PROTO_TCP)
daniele 17:5292cca5c478 378 {
daniele 17:5292cca5c478 379 return -1;
daniele 17:5292cca5c478 380 }
tass 5:445d2fc04784 381
tass 5:445d2fc04784 382 return pico_socket_sendto(_sock->sock,buff,len,(void *)&s_in->sin_addr,s_in->sin_port);
tass 5:445d2fc04784 383 }
tass 5:445d2fc04784 384
tass 5:445d2fc04784 385 int picotcp_recvfrom(int sock,void * buff, int len, struct sockaddr *orig, socklen_t *socklen)
tass 5:445d2fc04784 386 {
tass 5:445d2fc04784 387 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 388 struct sockaddr_in *s_in = (struct sockaddr_in *) orig;
tass 13:c6662adea07d 389 int ret;
tass 13:c6662adea07d 390
tass 5:445d2fc04784 391 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 392 VALIDATE_ONE(_sock->proto,PICO_PROTO_UDP);
tass 5:445d2fc04784 393 VALIDATE_NULL(socklen);
tass 5:445d2fc04784 394
daniele 17:5292cca5c478 395 if(waitForEvent(_sock,PICO_SOCK_EV_RD,0))
tass 5:445d2fc04784 396 return -1;
tass 13:c6662adea07d 397 ret = pico_socket_recvfrom(_sock->sock,buff,len,(void *)&s_in->sin_addr,(uint16_t *)&s_in->sin_port);
daniele 17:5292cca5c478 398 if (ret < len)
daniele 17:5292cca5c478 399 RESET_EVENT(_sock->event, PICO_SOCK_EV_RD);
tass 13:c6662adea07d 400 globalLock.unlock();
tass 13:c6662adea07d 401 return ret;
tass 5:445d2fc04784 402 }
tass 5:445d2fc04784 403
tass 5:445d2fc04784 404 int picotcp_read(int sock,void *buf, int len)
tass 5:445d2fc04784 405 {
tass 5:445d2fc04784 406 struct socket * _sock = findAfterId(sock);
daniele 11:58acd53df75c 407 int r, tot_len = 0;
tass 5:445d2fc04784 408 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 409 VALIDATE_ONE(_sock->proto,PICO_PROTO_TCP);
tass 5:445d2fc04784 410 VALIDATE_ONE(_sock->state, SOCK_CONNECTED);
daniele 17:5292cca5c478 411 r = pico_socket_read(_sock->sock, (unsigned char *)buf + tot_len, len - tot_len);
daniele 17:5292cca5c478 412 if (r != 0)
daniele 17:5292cca5c478 413 return r;
tass 5:445d2fc04784 414
daniele 17:5292cca5c478 415 if(waitForEvent(_sock,PICO_SOCK_EV_RD,0))
tass 5:445d2fc04784 416 return -1;
daniele 11:58acd53df75c 417 while(tot_len < len) {
daniele 11:58acd53df75c 418 r = pico_socket_read(_sock->sock, (unsigned char *)buf + tot_len, len - tot_len);
daniele 11:58acd53df75c 419 if (r > 0)
daniele 11:58acd53df75c 420 tot_len += r;
tass 16:6893f625e337 421 else
tass 16:6893f625e337 422 {
tass 16:6893f625e337 423 RESET_EVENT(_sock->revent,PICO_SOCK_EV_RD);
tass 16:6893f625e337 424 break;
tass 16:6893f625e337 425 }
daniele 11:58acd53df75c 426 }
tass 13:c6662adea07d 427 globalLock.unlock();
daniele 11:58acd53df75c 428 return tot_len;
tass 5:445d2fc04784 429 }
tass 5:445d2fc04784 430
tass 5:445d2fc04784 431 int picotcp_write(int sock,void *buf, int len)
tass 5:445d2fc04784 432 {
tass 5:445d2fc04784 433 struct socket * _sock = findAfterId(sock);
daniele 11:58acd53df75c 434 int r, tot_len = 0;
tass 5:445d2fc04784 435
tass 5:445d2fc04784 436 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 437 VALIDATE_ONE(_sock->proto,PICO_PROTO_TCP);
tass 5:445d2fc04784 438 VALIDATE_ONE(_sock->state, SOCK_CONNECTED);
daniele 17:5292cca5c478 439 if(waitForEvent(_sock,PICO_SOCK_EV_WR,0))
tass 5:445d2fc04784 440 return -1;
daniele 11:58acd53df75c 441
daniele 11:58acd53df75c 442 while(tot_len < len) {
daniele 11:58acd53df75c 443 r = pico_socket_write(_sock->sock, (unsigned char *)buf + tot_len, len - tot_len);
daniele 11:58acd53df75c 444 if (r > 0)
daniele 11:58acd53df75c 445 tot_len += r;
daniele 11:58acd53df75c 446 else break;
daniele 11:58acd53df75c 447 }
tass 13:c6662adea07d 448
tass 13:c6662adea07d 449 globalLock.unlock();
daniele 11:58acd53df75c 450 return tot_len;
tass 5:445d2fc04784 451 }
tass 5:445d2fc04784 452
tass 5:445d2fc04784 453 int picotcp_setsockopt(int sock, int option, void *value)
tass 5:445d2fc04784 454 {
tass 5:445d2fc04784 455 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 456
tass 5:445d2fc04784 457 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 458
tass 5:445d2fc04784 459 return pico_socket_setoption(_sock->sock,option,value);
tass 5:445d2fc04784 460 }
tass 5:445d2fc04784 461
tass 5:445d2fc04784 462 int picotcp_getsockopt(int sock, int option, void *value)
tass 5:445d2fc04784 463 {
tass 5:445d2fc04784 464 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 465
tass 5:445d2fc04784 466 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 467
tass 5:445d2fc04784 468 return pico_socket_getoption(_sock->sock,option,value);
tass 5:445d2fc04784 469 }
tass 5:445d2fc04784 470
tass 16:6893f625e337 471 void timeoutCb(void const *s)
tass 16:6893f625e337 472 {
tass 16:6893f625e337 473 struct socket * _sock = (struct socket *)s;
tass 16:6893f625e337 474 _sock->mutex->unlock();
tass 16:6893f625e337 475 }
tass 16:6893f625e337 476
tass 16:6893f625e337 477
tass 5:445d2fc04784 478 int picotcp_select(int sock, struct timeval *timeout, int read, int write)
tass 5:445d2fc04784 479 {
tass 5:445d2fc04784 480 uint32_t ms = 1000 * timeout->tv_sec + timeout->tv_usec / 1000;
tass 5:445d2fc04784 481 uint32_t now = PICO_TIME_MS();
tass 16:6893f625e337 482 uint16_t event = 0;
tass 5:445d2fc04784 483 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 484
tass 16:6893f625e337 485 if(!_sock)
tass 16:6893f625e337 486 return -1;
tass 13:c6662adea07d 487
tass 5:445d2fc04784 488
tass 16:6893f625e337 489 while(PICO_TIME_MS() < ms + now)
tass 16:6893f625e337 490 {
tass 16:6893f625e337 491 int events = 0;
daniele 17:5292cca5c478 492 RtosTimer tioTmr(timeoutCb, osTimerOnce, (void*)_sock);
tass 16:6893f625e337 493
tass 16:6893f625e337 494 if(read)
tass 16:6893f625e337 495 event |= PICO_SOCK_EV_RD;
tass 16:6893f625e337 496 if(write)
tass 16:6893f625e337 497 event |= PICO_SOCK_EV_WR;
tass 16:6893f625e337 498
tass 16:6893f625e337 499 waitForEvent(_sock,event,0);
tass 16:6893f625e337 500
tass 16:6893f625e337 501 if(read && EVENT_PENDING(_sock->revent,PICO_SOCK_EV_RD))
tass 16:6893f625e337 502 {
tass 16:6893f625e337 503 events++;
tass 16:6893f625e337 504 }
tass 16:6893f625e337 505
tass 16:6893f625e337 506 if(write && EVENT_PENDING(_sock->revent,PICO_SOCK_EV_WR))
tass 16:6893f625e337 507 {
tass 16:6893f625e337 508 events++;
tass 16:6893f625e337 509 RESET_EVENT(_sock->revent,PICO_SOCK_EV_WR);
tass 16:6893f625e337 510 }
tass 16:6893f625e337 511
tass 16:6893f625e337 512 if(events>0)
tass 16:6893f625e337 513 return events;
tass 16:6893f625e337 514
tass 16:6893f625e337 515 }
tass 16:6893f625e337 516 return 0;
tass 5:445d2fc04784 517 }
tass 5:445d2fc04784 518
tass 5:445d2fc04784 519 int picotcp_setblocking(int sock, int blocking)
tass 5:445d2fc04784 520 {
tass 5:445d2fc04784 521 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 522 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 523
tass 5:445d2fc04784 524 _sock->blocking = blocking;
tass 5:445d2fc04784 525
tass 5:445d2fc04784 526 return 0;
tass 5:445d2fc04784 527 }
tass 5:445d2fc04784 528
tass 5:445d2fc04784 529
tass 5:445d2fc04784 530 int picotcp_join_multicast(int sock,const char* address,const char* local)
tass 5:445d2fc04784 531 {
tass 5:445d2fc04784 532 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 533 struct pico_ip4 inaddr_dst, inaddr_link;
tass 5:445d2fc04784 534 struct pico_ip_mreq mreq = {{0},{0}};
tass 5:445d2fc04784 535 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 536 pico_string_to_ipv4(address, &inaddr_dst.addr);
tass 5:445d2fc04784 537 pico_string_to_ipv4(local, &inaddr_link.addr); // local ip address ?
tass 5:445d2fc04784 538 mreq.mcast_group_addr = inaddr_dst;
tass 5:445d2fc04784 539 mreq.mcast_link_addr = inaddr_link;
tass 5:445d2fc04784 540 return pico_socket_setoption(_sock->sock, PICO_IP_ADD_MEMBERSHIP, &mreq);
tass 5:445d2fc04784 541 }
tass 5:445d2fc04784 542
tass 5:445d2fc04784 543 /************************** PICO BSD DNS LAYER **************************/
tass 5:445d2fc04784 544
tass 5:445d2fc04784 545 struct dnsQuery
tass 5:445d2fc04784 546 {
tass 5:445d2fc04784 547 PicoCondition * mutex;
tass 5:445d2fc04784 548 char * result;
tass 5:445d2fc04784 549 };
tass 5:445d2fc04784 550
tass 5:445d2fc04784 551 static void dispatch_dns(char *ip, void *arg)
tass 5:445d2fc04784 552 {
tass 5:445d2fc04784 553 ((struct dnsQuery *)arg)->result = ip;
tass 5:445d2fc04784 554 printf("Disp : %x\n",((struct dnsQuery *)arg)->mutex);
tass 5:445d2fc04784 555 ((struct dnsQuery *)arg)->mutex->unlock();
tass 5:445d2fc04784 556 printf("Result : %s\n",ip);
tass 5:445d2fc04784 557 }
tass 5:445d2fc04784 558
tass 5:445d2fc04784 559 struct hostent * picotcp_gethostbyname(const char *url)
tass 5:445d2fc04784 560 {
tass 5:445d2fc04784 561 struct dnsQuery * dns;
tass 5:445d2fc04784 562 struct hostent * hresult = NULL;
tass 5:445d2fc04784 563
tass 5:445d2fc04784 564 dns = (struct dnsQuery *)pico_zalloc(sizeof(struct dnsQuery));
tass 5:445d2fc04784 565
tass 5:445d2fc04784 566 if(!dns)
tass 5:445d2fc04784 567 return NULL;
tass 5:445d2fc04784 568
tass 5:445d2fc04784 569 dns->mutex = new PicoCondition();
tass 5:445d2fc04784 570
tass 5:445d2fc04784 571 pico_dns_client_getaddr(url,dispatch_dns,(void *)dns);
tass 5:445d2fc04784 572 dns->mutex->lock();
tass 5:445d2fc04784 573
tass 5:445d2fc04784 574 if(dns->result)
tass 5:445d2fc04784 575 {
tass 5:445d2fc04784 576 hresult = (struct hostent *)pico_zalloc(sizeof(struct hostent));
tass 5:445d2fc04784 577 hresult->h_addrtype = AF_INET; // ipv4
tass 5:445d2fc04784 578 // make a copy of the name
tass 5:445d2fc04784 579 hresult->h_name = new char[strlen(url)+1];
tass 5:445d2fc04784 580 memcpy(hresult->h_name,url,strlen(url)+1);
tass 5:445d2fc04784 581 hresult->h_aliases = NULL;
tass 5:445d2fc04784 582 // address list
tass 5:445d2fc04784 583 hresult->h_addr_list = new char* [2];
tass 5:445d2fc04784 584 hresult->h_addr_list[0] = dns->result;
tass 5:445d2fc04784 585 hresult->h_addr_list[1] = NULL;
tass 5:445d2fc04784 586 }
tass 5:445d2fc04784 587
tass 5:445d2fc04784 588 delete(dns->mutex);
tass 5:445d2fc04784 589 pico_free(dns);
tass 5:445d2fc04784 590 //
tass 5:445d2fc04784 591 return hresult;
tass 5:445d2fc04784 592 }
tass 5:445d2fc04784 593
tass 5:445d2fc04784 594 char * picotcp_gethostbyaddr(const char *ip)
tass 5:445d2fc04784 595 {
tass 5:445d2fc04784 596 struct dnsQuery * dns;
tass 5:445d2fc04784 597 char * result;
tass 5:445d2fc04784 598 dns = (struct dnsQuery *)pico_zalloc(sizeof(struct dnsQuery));
tass 5:445d2fc04784 599 int tries = 5u;
tass 5:445d2fc04784 600
tass 5:445d2fc04784 601 if(!dns)
tass 5:445d2fc04784 602 return NULL;
tass 5:445d2fc04784 603
tass 5:445d2fc04784 604 dns->mutex = new PicoCondition();
tass 5:445d2fc04784 605
tass 5:445d2fc04784 606 pico_dns_client_getname(ip,dispatch_dns,(void *)dns);
tass 5:445d2fc04784 607
tass 5:445d2fc04784 608 while(tries>0)
tass 5:445d2fc04784 609 {
tass 5:445d2fc04784 610 if(dns->mutex->lock() == false)
tass 5:445d2fc04784 611 tries--;
tass 5:445d2fc04784 612 else
tass 5:445d2fc04784 613 break;
tass 5:445d2fc04784 614 }
tass 5:445d2fc04784 615
tass 5:445d2fc04784 616 result = dns->result;
tass 5:445d2fc04784 617 delete(dns->mutex);
tass 5:445d2fc04784 618 pico_free(dns);
tass 5:445d2fc04784 619
tass 5:445d2fc04784 620 return result;
tass 5:445d2fc04784 621 }
tass 5:445d2fc04784 622
tass 5:445d2fc04784 623
tass 5:445d2fc04784 624 static void picotcp_loop(void const *args)
tass 5:445d2fc04784 625 {
tass 5:445d2fc04784 626 while(1) {
tass 5:445d2fc04784 627 pico_stack_tick();
tass 5:445d2fc04784 628 Thread::wait(1);
tass 5:445d2fc04784 629 }
tass 5:445d2fc04784 630 }
tass 5:445d2fc04784 631
tass 5:445d2fc04784 632 static Thread * pico_thread;
tass 5:445d2fc04784 633
tass 5:445d2fc04784 634 void picotcp_init(void)
tass 5:445d2fc04784 635 {
tass 5:445d2fc04784 636 //Thread pico_thread(picotcp_loop);
tass 5:445d2fc04784 637 pico_thread= new Thread(picotcp_loop);
tass 5:445d2fc04784 638 // doesn;t this call the ~Thread
tass 5:445d2fc04784 639 }
tass 5:445d2fc04784 640