Daniele Lacamera / PicoTCP-Experimental_CDC_ECM_Branch

Fork of PicoTCP by Daniele Lacamera

Committer:
tass
Date:
Fri May 31 11:34:03 2013 +0000
Revision:
5:445d2fc04784
Child:
11:58acd53df75c
Integrated mbed friendly sockets

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 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);
tass 5:445d2fc04784 392
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;
tass 5:445d2fc04784 399
tass 5:445d2fc04784 400 return pico_socket_read(_sock->sock,buf,len);
tass 5:445d2fc04784 401 }
tass 5:445d2fc04784 402
tass 5:445d2fc04784 403 int picotcp_write(int sock,void *buf, int len)
tass 5:445d2fc04784 404 {
tass 5:445d2fc04784 405 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 406
tass 5:445d2fc04784 407 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 408 VALIDATE_ONE(_sock->proto,PICO_PROTO_TCP);
tass 5:445d2fc04784 409 VALIDATE_ONE(_sock->state, SOCK_CONNECTED);
tass 5:445d2fc04784 410 if(waitForEvent(_sock,PICO_SOCK_EV_WR,1))
tass 5:445d2fc04784 411 return -1;
tass 5:445d2fc04784 412 return pico_socket_write(_sock->sock,buf,len);
tass 5:445d2fc04784 413 }
tass 5:445d2fc04784 414
tass 5:445d2fc04784 415 int picotcp_setsockopt(int sock, int option, void *value)
tass 5:445d2fc04784 416 {
tass 5:445d2fc04784 417 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 418
tass 5:445d2fc04784 419 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 420
tass 5:445d2fc04784 421 return pico_socket_setoption(_sock->sock,option,value);
tass 5:445d2fc04784 422 }
tass 5:445d2fc04784 423
tass 5:445d2fc04784 424 int picotcp_getsockopt(int sock, int option, void *value)
tass 5:445d2fc04784 425 {
tass 5:445d2fc04784 426 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 427
tass 5:445d2fc04784 428 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 429
tass 5:445d2fc04784 430 return pico_socket_getoption(_sock->sock,option,value);
tass 5:445d2fc04784 431 }
tass 5:445d2fc04784 432
tass 5:445d2fc04784 433 int picotcp_select(int sock, struct timeval *timeout, int read, int write)
tass 5:445d2fc04784 434 {
tass 5:445d2fc04784 435 uint32_t ms = 1000 * timeout->tv_sec + timeout->tv_usec / 1000;
tass 5:445d2fc04784 436 uint32_t now = PICO_TIME_MS();
tass 5:445d2fc04784 437 int ret = 0;
tass 5:445d2fc04784 438
tass 5:445d2fc04784 439 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 440 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 441
tass 5:445d2fc04784 442 // tell the dispatcher what events are you waiting for
tass 5:445d2fc04784 443 if(read)
tass 5:445d2fc04784 444 SET_EVENT(_sock->event,PICO_SOCK_EV_RD|PICO_SOCK_EV_CONN);
tass 5:445d2fc04784 445 if(write)
tass 5:445d2fc04784 446 SET_EVENT(_sock->event,PICO_SOCK_EV_WR);
tass 5:445d2fc04784 447
tass 5:445d2fc04784 448 while (PICO_TIME_MS() < now + ms) {
tass 5:445d2fc04784 449 if (_sock->mutex->lock(1) == false) {
tass 5:445d2fc04784 450 Thread::wait(1);
tass 5:445d2fc04784 451 continue;
tass 5:445d2fc04784 452 }
tass 5:445d2fc04784 453
tass 5:445d2fc04784 454 if (read && EVENT_PENDING(_sock->revent,PICO_SOCK_EV_RD|PICO_SOCK_EV_CONN))
tass 5:445d2fc04784 455 {
tass 5:445d2fc04784 456 RESET_EVENT(_sock->revent,PICO_SOCK_EV_RD|PICO_SOCK_EV_CONN);
tass 5:445d2fc04784 457 ret++;
tass 5:445d2fc04784 458 }
tass 5:445d2fc04784 459 if (write && EVENT_PENDING(_sock->revent, PICO_SOCK_EV_WR))
tass 5:445d2fc04784 460 {
tass 5:445d2fc04784 461 RESET_EVENT(_sock->revent,PICO_SOCK_EV_WR);
tass 5:445d2fc04784 462 ret++;
tass 5:445d2fc04784 463 }
tass 5:445d2fc04784 464 if (ret > 0)
tass 5:445d2fc04784 465 break;
tass 5:445d2fc04784 466 }
tass 5:445d2fc04784 467
tass 5:445d2fc04784 468 if(read)
tass 5:445d2fc04784 469 RESET_EVENT(_sock->event,PICO_SOCK_EV_RD|PICO_SOCK_EV_CONN);
tass 5:445d2fc04784 470 if(write)
tass 5:445d2fc04784 471 RESET_EVENT(_sock->event,PICO_SOCK_EV_WR);
tass 5:445d2fc04784 472
tass 5:445d2fc04784 473 return ret;
tass 5:445d2fc04784 474 }
tass 5:445d2fc04784 475
tass 5:445d2fc04784 476 int picotcp_setblocking(int sock, int blocking)
tass 5:445d2fc04784 477 {
tass 5:445d2fc04784 478 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 479 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 480
tass 5:445d2fc04784 481 _sock->blocking = blocking;
tass 5:445d2fc04784 482
tass 5:445d2fc04784 483 return 0;
tass 5:445d2fc04784 484 }
tass 5:445d2fc04784 485
tass 5:445d2fc04784 486
tass 5:445d2fc04784 487 int picotcp_join_multicast(int sock,const char* address,const char* local)
tass 5:445d2fc04784 488 {
tass 5:445d2fc04784 489 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 490 struct pico_ip4 inaddr_dst, inaddr_link;
tass 5:445d2fc04784 491 struct pico_ip_mreq mreq = {{0},{0}};
tass 5:445d2fc04784 492 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 493 pico_string_to_ipv4(address, &inaddr_dst.addr);
tass 5:445d2fc04784 494 pico_string_to_ipv4(local, &inaddr_link.addr); // local ip address ?
tass 5:445d2fc04784 495 mreq.mcast_group_addr = inaddr_dst;
tass 5:445d2fc04784 496 mreq.mcast_link_addr = inaddr_link;
tass 5:445d2fc04784 497 return pico_socket_setoption(_sock->sock, PICO_IP_ADD_MEMBERSHIP, &mreq);
tass 5:445d2fc04784 498 }
tass 5:445d2fc04784 499
tass 5:445d2fc04784 500 /************************** PICO BSD DNS LAYER **************************/
tass 5:445d2fc04784 501
tass 5:445d2fc04784 502 struct dnsQuery
tass 5:445d2fc04784 503 {
tass 5:445d2fc04784 504 PicoCondition * mutex;
tass 5:445d2fc04784 505 char * result;
tass 5:445d2fc04784 506 };
tass 5:445d2fc04784 507
tass 5:445d2fc04784 508 static void dispatch_dns(char *ip, void *arg)
tass 5:445d2fc04784 509 {
tass 5:445d2fc04784 510 ((struct dnsQuery *)arg)->result = ip;
tass 5:445d2fc04784 511 printf("Disp : %x\n",((struct dnsQuery *)arg)->mutex);
tass 5:445d2fc04784 512 ((struct dnsQuery *)arg)->mutex->unlock();
tass 5:445d2fc04784 513 printf("Result : %s\n",ip);
tass 5:445d2fc04784 514 }
tass 5:445d2fc04784 515
tass 5:445d2fc04784 516 struct hostent * picotcp_gethostbyname(const char *url)
tass 5:445d2fc04784 517 {
tass 5:445d2fc04784 518 struct dnsQuery * dns;
tass 5:445d2fc04784 519 struct hostent * hresult = NULL;
tass 5:445d2fc04784 520
tass 5:445d2fc04784 521 dns = (struct dnsQuery *)pico_zalloc(sizeof(struct dnsQuery));
tass 5:445d2fc04784 522
tass 5:445d2fc04784 523 if(!dns)
tass 5:445d2fc04784 524 return NULL;
tass 5:445d2fc04784 525
tass 5:445d2fc04784 526 dns->mutex = new PicoCondition();
tass 5:445d2fc04784 527
tass 5:445d2fc04784 528 pico_dns_client_getaddr(url,dispatch_dns,(void *)dns);
tass 5:445d2fc04784 529 dns->mutex->lock();
tass 5:445d2fc04784 530
tass 5:445d2fc04784 531 if(dns->result)
tass 5:445d2fc04784 532 {
tass 5:445d2fc04784 533 hresult = (struct hostent *)pico_zalloc(sizeof(struct hostent));
tass 5:445d2fc04784 534 hresult->h_addrtype = AF_INET; // ipv4
tass 5:445d2fc04784 535 // make a copy of the name
tass 5:445d2fc04784 536 hresult->h_name = new char[strlen(url)+1];
tass 5:445d2fc04784 537 memcpy(hresult->h_name,url,strlen(url)+1);
tass 5:445d2fc04784 538 hresult->h_aliases = NULL;
tass 5:445d2fc04784 539 // address list
tass 5:445d2fc04784 540 hresult->h_addr_list = new char* [2];
tass 5:445d2fc04784 541 hresult->h_addr_list[0] = dns->result;
tass 5:445d2fc04784 542 hresult->h_addr_list[1] = NULL;
tass 5:445d2fc04784 543 }
tass 5:445d2fc04784 544
tass 5:445d2fc04784 545 delete(dns->mutex);
tass 5:445d2fc04784 546 pico_free(dns);
tass 5:445d2fc04784 547 //
tass 5:445d2fc04784 548 return hresult;
tass 5:445d2fc04784 549 }
tass 5:445d2fc04784 550
tass 5:445d2fc04784 551 char * picotcp_gethostbyaddr(const char *ip)
tass 5:445d2fc04784 552 {
tass 5:445d2fc04784 553 struct dnsQuery * dns;
tass 5:445d2fc04784 554 char * result;
tass 5:445d2fc04784 555 dns = (struct dnsQuery *)pico_zalloc(sizeof(struct dnsQuery));
tass 5:445d2fc04784 556 int tries = 5u;
tass 5:445d2fc04784 557
tass 5:445d2fc04784 558 if(!dns)
tass 5:445d2fc04784 559 return NULL;
tass 5:445d2fc04784 560
tass 5:445d2fc04784 561 dns->mutex = new PicoCondition();
tass 5:445d2fc04784 562
tass 5:445d2fc04784 563 pico_dns_client_getname(ip,dispatch_dns,(void *)dns);
tass 5:445d2fc04784 564
tass 5:445d2fc04784 565 while(tries>0)
tass 5:445d2fc04784 566 {
tass 5:445d2fc04784 567 if(dns->mutex->lock() == false)
tass 5:445d2fc04784 568 tries--;
tass 5:445d2fc04784 569 else
tass 5:445d2fc04784 570 break;
tass 5:445d2fc04784 571 }
tass 5:445d2fc04784 572
tass 5:445d2fc04784 573 result = dns->result;
tass 5:445d2fc04784 574 delete(dns->mutex);
tass 5:445d2fc04784 575 pico_free(dns);
tass 5:445d2fc04784 576
tass 5:445d2fc04784 577 return result;
tass 5:445d2fc04784 578 }
tass 5:445d2fc04784 579
tass 5:445d2fc04784 580
tass 5:445d2fc04784 581 static void picotcp_loop(void const *args)
tass 5:445d2fc04784 582 {
tass 5:445d2fc04784 583 while(1) {
tass 5:445d2fc04784 584 pico_stack_tick();
tass 5:445d2fc04784 585 Thread::wait(1);
tass 5:445d2fc04784 586 }
tass 5:445d2fc04784 587 }
tass 5:445d2fc04784 588
tass 5:445d2fc04784 589 static Thread * pico_thread;
tass 5:445d2fc04784 590
tass 5:445d2fc04784 591 void picotcp_init(void)
tass 5:445d2fc04784 592 {
tass 5:445d2fc04784 593 //Thread pico_thread(picotcp_loop);
tass 5:445d2fc04784 594 pico_thread= new Thread(picotcp_loop);
tass 5:445d2fc04784 595 // doesn;t this call the ~Thread
tass 5:445d2fc04784 596 }
tass 5:445d2fc04784 597