]> rtime.felk.cvut.cz Git - frescor/fwp.git/blob - fwp/lib/fwp/fwp_endpoint.c
0531284cbfe763c0e39f39b5a40ac4beb8848195
[frescor/fwp.git] / fwp / lib / fwp / fwp_endpoint.c
1 /**************************************************************************/
2 /* ---------------------------------------------------------------------- */
3 /* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                 */
4 /*                                                                        */
5 /*   Universidad de Cantabria,              SPAIN                         */
6 /*   University of York,                    UK                            */
7 /*   Scuola Superiore Sant'Anna,            ITALY                         */
8 /*   Kaiserslautern University,             GERMANY                       */
9 /*   Univ. Politécnica  Valencia,           SPAIN                        */
10 /*   Czech Technical University in Prague,  CZECH REPUBLIC                */
11 /*   ENEA                                   SWEDEN                        */
12 /*   Thales Communication S.A.              FRANCE                        */
13 /*   Visual Tools S.A.                      SPAIN                         */
14 /*   Rapita Systems Ltd                     UK                            */
15 /*   Evidence                               ITALY                         */
16 /*                                                                        */
17 /*   See http://www.frescor.org for a link to partners' websites          */
18 /*                                                                        */
19 /*          FRESCOR project (FP6/2005/IST/5-034026) is funded             */
20 /*       in part by the European Union Sixth Framework Programme          */
21 /*       The European Union is not liable of any use that may be          */
22 /*       made of this code.                                               */
23 /*                                                                        */
24 /*                                                                        */
25 /*  This file is part of FWP (Frescor WLAN Protocol)                      */
26 /*                                                                        */
27 /* FWP is free software; you can redistribute it and/or modify it         */
28 /* under terms of the GNU General Public License as published by the      */
29 /* Free Software Foundation; either version 2, or (at your option) any    */
30 /* later version.  FWP is distributed in the hope that it will be         */
31 /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty    */
32 /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU    */
33 /* General Public License for more details. You should have received a    */
34 /* copy of the GNU General Public License along with FWP; see file        */
35 /* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
36 /* Cambridge, MA 02139, USA.                                              */
37 /*                                                                        */
38 /* As a special exception, including FWP header files in a file,          */
39 /* instantiating FWP generics or templates, or linking other files        */
40 /* with FWP objects to produce an executable application, does not        */
41 /* by itself cause the resulting executable application to be covered     */
42 /* by the GNU General Public License. This exception does not             */
43 /* however invalidate any other reasons why the executable file might be  */
44 /* covered by the GNU Public License.                                     */
45 /**************************************************************************/
46 #include "fwp_endpoint.h"
47 #include "fwp_msgb.h"
48 #include <errno.h>
49 #include <stdlib.h>
50 #include <unistd.h>
51 #include <netinet/in.h>
52 #include "fwp_utils.h"
53
54 #include <pthread.h>
55 #include "fwp_debug.h"
56
57 typedef unsigned int fwp_endpoint_id_t;
58
59 /**
60  * Default fwp endpoint attributes
61  */
62 static fwp_endpoint_attr_t fwp_epoint_attr_default ={
63         .reliability = FWP_EPOINT_BESTEFFORT, 
64         .max_connections = 20,
65 };
66
67 /**
68  * FWP endpoint structure
69  */
70 struct fwp_endpoint{
71         /** Fwp endpoint attributes */
72         fwp_endpoint_attr_t     attr;
73         /* Vres this fwp endpoint is bound to */
74         fwp_vres_t              *vres;
75         /** For send enpoint it contains destination address for
76          * receive endpoint it is filled with the msg source address
77          */
78         struct fwp_sockaddr     peer;   
79         /** Source/destination port */
80         unsigned int            port;   
81         /** Destination node */
82         int                     node;
83         /** Socket descriptor.
84          * In case of rebliable epoint it is a listen tcp socket.
85          */
86         int                     sockd; 
87         /** File descriptor array of peers connected 
88          * to this fwp receive endpoint.*/
89         int                     *c_sockd;
90         /**
91          * Number of connections 
92          */
93         unsigned int            nr_connections;
94         /** client fdset */
95         fd_set                  fdset;
96         /** specific operation options*/
97         int                     flags;  
98 };
99
100 /**
101  * Allocates endpoint
102  *
103  * \return On success returns fwp endpoint structure. 
104  * On error, NULL is returned. 
105  *
106  */
107 static fwp_endpoint_t* fwp_endpoint_alloc()
108 {
109         return (fwp_endpoint_t*) calloc(1,sizeof(fwp_endpoint_t));
110 }
111
112 /**
113  * Allocates endpoint
114  *
115  * \return On success returns endpoint structure. 
116  * On error, NULL is returned. 
117  *
118  */
119 static inline void fwp_endpoint_free(fwp_endpoint_t *endpoint)
120 {
121         free(endpoint);
122 }
123
124 /**
125  * Destroy endpoint
126  *
127  * \param[in] epd Endpoint descriptor
128  * \return On success 0 is returned. 
129  * On error, negative error value is returned and errno is set appropriately. 
130  */
131 int fwp_endpoint_destroy(fwp_endpoint_t *ep)
132 {
133         if (ep->sockd > 0) 
134                 close(ep->sockd);
135         
136         fwp_endpoint_free(ep);  
137         return 0;
138 }
139
140 /**
141  * Get endpoint parameters
142  *
143  * \param[in] ep Endpoint descriptor
144  * \param[out] node Node identifier
145  * \param[out] port Port
146  * \param[out] attr Endpoint`s attributes
147  * \return On success 0 is returned. 
148  * On error, negative error value is returned. 
149  */
150 int fwp_endpoint_get_params(fwp_endpoint_t *ep, unsigned int *node, 
151                                 unsigned int *port, fwp_endpoint_attr_t *attr)
152 {
153         if (node) *node = ep->node;
154         if (port) *port = ep->port;
155         if (attr) *attr = ep->attr;
156         
157         return 0;
158 }
159
160 int fwp_endpoint_attr_init(fwp_endpoint_attr_t *attr)
161 {
162         bzero(attr, sizeof(fwp_endpoint_attr_t));
163         *attr = fwp_epoint_attr_default;
164
165         return 0;
166 }
167
168 /**
169  * Creates send endpoint
170  *
171  * \param[in] node IP address of destination node
172  * \param[in] port UDP port
173  * \param[in] attr Endpoint attributes
174  * \param[out] epp  Pointer to the descriptor of newly created endpoint
175  *
176  * \return Zero on success, -1 on error and sets errno appropriately. 
177  *
178  */
179 int fwp_send_endpoint_create(unsigned int node,
180                                 unsigned int port, 
181                                 fwp_endpoint_attr_t *attr,
182                                 fwp_endpoint_t **epoint)
183 {       
184         struct sockaddr_in *addr;
185         fwp_endpoint_t *fwp_epoint;
186
187         fwp_epoint = fwp_endpoint_alloc();      
188         if (!fwp_epoint) {
189                 errno = ENOMEM;
190                 return -1;
191         }
192         
193         /*epoint->type = FWP_SEND_EPOINT;
194         epoint->status = FWP_EPOINT_UNBOUND;
195         epoint->node = node;
196         epoint->port = port;
197         */
198         if (attr)
199                 fwp_epoint->attr  = *attr;
200         else
201                 fwp_epoint->attr = fwp_epoint_attr_default;
202                 
203         addr = (struct sockaddr_in *)&(fwp_epoint->peer.addr);
204         bzero((char*) addr, sizeof(*addr));
205         addr->sin_family = AF_INET;
206         addr->sin_addr.s_addr = node;
207         addr->sin_port = htons(port);
208         fwp_epoint->peer.addrlen = sizeof(struct sockaddr_in);
209         
210         if (fwp_epoint->attr.reliability == FWP_EPOINT_RELIABLE) {
211                 fwp_epoint->sockd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
212                 if (fwp_epoint->sockd < 0) {
213                         goto err;
214                 }
215         } else {
216                 fwp_epoint->sockd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
217                 if (fwp_epoint->sockd < 0) {
218                         goto err;
219                 }
220         
221                 /* Enable broadcasts */
222                 /*unsigned int yes = 1;
223                 if (setsockopt(fwp_epoint->sockd,SOL_SOCKET, SO_BROADCAST, 
224                                &yes, sizeof(yes)) == -1) {
225                         FWP_DEBUG("setsockopt(SO_BROADCAST): %s", strerror(errno));
226                         goto err;
227                 }*/
228         
229         }
230         
231         unsigned int yes = 1;
232         if (setsockopt(fwp_epoint->sockd,SOL_SOCKET, SO_REUSEADDR, 
233                                &yes, sizeof(yes)) == -1) {
234                         FWP_DEBUG("setsockopt(SO_REUSEADDR): %s", strerror(errno));
235                         goto err;
236         }
237
238         if (connect(fwp_epoint->sockd,
239                         (struct sockaddr*) &fwp_epoint->peer.addr, 
240                         fwp_epoint->peer.addrlen)) {
241                 FWP_DEBUG("FWp connect error\n"); 
242                 goto err;
243         }
244         
245         FWP_DEBUG("FWP Send endpoint created.\n"); 
246
247 #ifdef FWP_WITHOUT_CONTNEGT
248         /* Create vres with default parameters */
249         FWP_DEBUG("Creating default vres\n");
250         if (fwp_vres_create(&fwp_vres_params_default, &fwp_epoint->vresd)) {
251                 goto err;
252         }
253         
254         fwp_send_endpoint_bind(fwp_epoint, fwp_epoint->vresd);
255 #endif
256         
257         *epoint = fwp_epoint;
258         return fwp_epoint->sockd;               
259 err:
260         fwp_endpoint_destroy(fwp_epoint);
261         return -1;      
262 }
263
264 /**
265  * Creates receive endpoint
266  *
267  * \param[in] port UDP port
268  * \param[in] attr Endpoint attributes
269  * \param[out] epointdp  Pointer to the descriptor of newly created endpoint
270  *
271  * \return Zero on success, -1 on error and errno is set.
272  */
273 int fwp_receive_endpoint_create(unsigned int port,
274                                 fwp_endpoint_attr_t *attr,
275                                 fwp_endpoint_t **epp)
276 {
277         struct sockaddr_in *addr;
278         fwp_endpoint_t *fwp_epoint;
279
280         fwp_epoint = fwp_endpoint_alloc();      
281         if (!fwp_epoint) {
282                 errno = ENOMEM;
283                 return -1;
284         }
285         
286         /*epoint->type = FWP_RECV_EPOINT;
287         epoint->status = FWP_EPOINT_UNBOUND;*/
288         
289         if (attr)
290                 fwp_epoint->attr  = *attr;
291         else
292                 fwp_epoint->attr = fwp_epoint_attr_default;
293
294         addr = (struct sockaddr_in *) &(fwp_epoint->peer.addr);
295         addr->sin_family = AF_INET;
296         /* TODO: set listen interface, maybe through config struct*/
297         addr->sin_addr.s_addr = FWP_ANY_NODE;
298         fwp_epoint->port  = addr->sin_port = htons(port);
299         fwp_epoint->peer.addrlen = sizeof(struct sockaddr_in);
300         
301         if (fwp_epoint->attr.reliability == FWP_EPOINT_RELIABLE) {
302                 if ((fwp_epoint->sockd = socket(PF_INET, SOCK_STREAM, 
303                                                 IPPROTO_TCP)) < 0) {
304                         FWP_ERROR("Unable to open socket: %s", strerror(errno));
305                         goto err;
306                 }       
307                 
308                 int yes = 1;
309                 if (setsockopt(fwp_epoint->sockd,SOL_SOCKET, SO_REUSEADDR,
310                                &yes, sizeof(yes)) == -1) {
311                         FWP_ERROR("setsockopt(SO_REUSEADDR):%s",strerror(errno));
312                         goto err;
313                 }
314
315                 if (bind(fwp_epoint->sockd, (struct sockaddr*) &fwp_epoint->peer.addr, 
316                                 fwp_epoint->peer.addrlen) == -1) {
317                         FWP_ERROR("Bind error: %s", strerror(errno));
318                         /* TODO: remove all error messages from all libraries */
319                         goto err;
320                 }
321                 
322                 if (listen(fwp_epoint->sockd, fwp_epoint->attr.max_connections)){
323                         FWP_ERROR("Error on listen call: %s\n", strerror(errno));
324                         goto err;
325                 }
326                 
327                 FD_ZERO(&fwp_epoint->fdset);
328                 /*add listen socket */
329                 FD_SET(fwp_epoint->sockd, &fwp_epoint->fdset); 
330                 fwp_epoint->c_sockd = 
331                                 (int*)malloc(fwp_epoint->attr.max_connections);
332                 bzero(fwp_epoint->c_sockd, fwp_epoint->attr.max_connections);
333                 fwp_epoint->nr_connections = 0;
334
335                 FWP_DEBUG("Reliable receive endpoint port=%d created.\n", 
336                                 fwp_epoint->port); 
337         } else {
338                 if ((fwp_epoint->sockd = socket(PF_INET, SOCK_DGRAM, 
339                                                 IPPROTO_UDP)) < 0) {
340                         FWP_ERROR("Unable to open socket: %s", strerror(errno));
341                         goto err;
342                 }
343                 
344                 if (bind(fwp_epoint->sockd, 
345                         (struct sockaddr*) &fwp_epoint->peer.addr, 
346                         fwp_epoint->peer.addrlen) == -1) {
347                         
348                         FWP_ERROR("Bind error: %s", strerror(errno));
349                         goto err;
350                 }
351                 FWP_DEBUG("Best-Effort receive endpoint port=%d created.\n", 
352                                 fwp_epoint->port); 
353         }
354                 
355         /*if (setsockopt(epoint->sockd, SOL_SOCKET, SO_RCVBUF, 
356                         &rcvbuf_size, sizeof(rcvbuf_size)) == -1) {
357                 
358                 FWP_ERROR("Unable to set socket buffer size: %s", strerror(errno));
359                 return -1;
360         }else {
361                 FWP_DEBUG("Receive endpoint buffer size is set.\n");
362         }
363         */
364         
365         getsockname(fwp_epoint->sockd, (struct sockaddr*)&fwp_epoint->peer.addr, 
366                         &fwp_epoint->peer.addrlen);
367
368         addr = (struct sockaddr_in*) fwp_epoint->peer.addr;
369         fwp_epoint->port = ntohs(addr->sin_port);
370         FWP_DEBUG("Recv port= %d\n",ntohs(addr->sin_port));     
371         *epp = fwp_epoint;
372         return 0;
373 err:
374         fwp_endpoint_destroy(fwp_epoint);
375         return errno;
376 }
377
378 /**
379  * Binds send endpoint to vres
380  *
381  * \param[in] vres identifier of vres
382  * \param[in] ep send endpoint identifier
383  *
384  * \return On success returns 0. On error, -1 and errno is set appropriately.
385  */
386 int fwp_send_endpoint_bind(fwp_endpoint_t *ep, fwp_vres_t *vres)
387 {
388         int rv = 0;
389 #ifndef FWP_WITHOUT_CONTNEGT
390         
391         ep->vres = vres;
392         rv = fwp_vres_bind(vres, ep->sockd);
393 #endif
394         /* if send endpoint is already bound 
395         if (epoint->type == FWP_EPOINT_BOUND) {  
396                 fwp_send_endpoint_unbind(epoint);
397         }*/
398         return rv;
399 }
400
401 /**
402  * Unbinds send endpoint from vres
403  *
404  * \param[in] epointd Send endpoint descriptor 
405  * \return On success returns 0. On error, -1 is returned and errno is set appropriately.
406  *
407  */
408 int fwp_send_endpoint_unbind(fwp_endpoint_t *ep)
409 {
410         int rv = 0;
411
412         /* unlink epoint-vres mutually */
413         if ((rv = fwp_vres_unbind(ep->vres)) < 0) 
414                 return rv;
415
416         return 0;
417 }
418
419 /**
420  * Accepts (TCP) client connection to receive endpoint
421  *
422  * \param[in] epointd Pointer to fwp endpoint
423  * \return
424  * On success, it returns zero.  
425  *
426  */
427 static int fwp_receive_endpoint_accept(fwp_endpoint_t *fwp_epoint)
428 {
429         int csockd;
430 //      fwp_endpoint_t *fwp_epoint = epointd;
431         fwp_sockaddr_t  peer;
432         int i;
433
434         if (fwp_epoint->nr_connections == fwp_epoint->attr.max_connections)
435                 return -1;
436
437         peer.addrlen = sizeof(struct sockaddr_in);
438         csockd = accept(fwp_epoint->sockd, (struct sockaddr*)peer.addr,
439                         &peer.addrlen);
440         
441         if (csockd < 0) {
442                 FWP_ERROR("Error on accept: %s\n", strerror(errno));
443                 return errno;   
444         }               
445
446         FWP_DEBUG("New connection accepted\n");
447         /* find free place */           
448         i = 0;
449         while ((fwp_epoint->c_sockd[i])&& (i < fwp_epoint->nr_connections)) 
450                                 i++;
451         fwp_epoint->c_sockd[i] = csockd; 
452         fwp_epoint->nr_connections++;
453                 
454         FD_SET(csockd, &fwp_epoint->fdset);
455         return 0;       
456
457
458 /**
459  * Receives message from stream (TCP)
460  *
461  * \param[in] epointd Descriptor of endpoint
462  * \param[in] buffer Buffer to store message
463  * \param[in] buffer_size Size of buffer
464  *
465  * \return
466  * On success, it returns number of received bytes.  
467  * On error, -1 is returned and errno is set appropriately.
468  *
469  */
470 int fwp_recv_conn(fwp_endpoint_t *ep, void *buffer, 
471                         size_t buffer_size)
472 {
473         fwp_sockaddr_t *peer = &ep->peer;
474         fd_set fdset = ep->fdset;
475         ssize_t len;
476         int i;
477
478         FWP_DEBUG("Checking for tcp data\n");
479         for (i = 0; i < ep->nr_connections; i++) {
480                 if (!FD_ISSET(ep->c_sockd[i], &fdset)) {
481                         continue;       
482                 }       
483                         
484                 FWP_DEBUG("Prepare to receive tcp data\n");
485                 peer->addrlen = sizeof(struct sockaddr_in);
486                 len = _fwp_recvfrom(ep->c_sockd[i], buffer, 
487                                         buffer_size,0, peer);
488
489                 if (len < 0) /* Error */
490                         return len;
491                 
492                 FWP_DEBUG("Received tcp data\n");
493                 if (len)
494                         return len;
495         
496                 /* tcp connection closed */
497                 FWP_DEBUG("Connection closed\n");
498                 FD_CLR(ep->c_sockd[i], &ep->fdset);
499                 memcpy(ep->c_sockd+i, ep->c_sockd+i+1, 
500                         sizeof(int)*(ep->nr_connections -i-1));
501                 ep->nr_connections--;
502                 return 0;
503         }
504         return 0;
505 }
506
507 /**
508  * Receives message
509  *
510  * \param[in] epointd Descriptor of endpoint
511  * \param[in] buffer Buffer to store message
512  * \param[in] buffer_size Size of buffer
513  *
514  * \return
515  * On success, it returns number of received bytes.  
516  * On error, -1 is returned and errno is set appropriately.
517  *
518  */
519 ssize_t fwp_recv(fwp_endpoint_t *ep,
520                         void *buffer, const size_t buffer_size,
521                         unsigned int *from, int flags)
522 {
523         fwp_sockaddr_t *peer = &ep->peer;
524         struct sockaddr_in *addr = (struct sockaddr_in*) ep->peer.addr;
525         ssize_t len;
526         fd_set fdset;
527         
528         /*if (!fwp_endpoint_is_valid(epointd)) {
529                 errno = EINVAL;
530                 return -1;
531         }*/
532         
533         if (ep->attr.reliability == FWP_EPOINT_BESTEFFORT) {    
534                 len = _fwp_recvfrom(ep->sockd, buffer, 
535                                         buffer_size, 0, peer);
536                 
537                 *from = addr->sin_addr.s_addr;
538                 return len;
539         }
540         
541         while (1){
542                 /* FWP_EPOINT_RELIABLE */
543                 fdset = ep->fdset;
544                 if (select(FD_SETSIZE, &fdset, (fd_set *)0, 
545                            (fd_set *)0, NULL) < 0) {
546                 
547                         FWP_ERROR("Error in select: %s", strerror(errno));
548                         return -1;
549                 }
550         
551                 if (FD_ISSET(ep->sockd, &fdset)) { /* is it listen socket? */
552                         fwp_receive_endpoint_accept(ep);
553                         continue;
554                 }
555
556                 /* Check client TCP sockets */
557                 len = fwp_recv_conn(ep, buffer, buffer_size);
558                 if (len) {
559                         *from = addr->sin_addr.s_addr;
560                         return len;
561                 }
562         }
563 }
564
565 /**
566  * Sends message through vres
567  *
568  * \param[in] epointd Endpoint descriptor
569  * \param[in] msg Message to sent
570  * \param[in] size Message size
571  *
572  * \return
573  * On success, it returns zero.  
574  * On error, -1 is returned and errno is set appropriately.
575  *
576  */
577 int fwp_send(fwp_endpoint_t *ep,const void *msg, const size_t size)
578 {
579         struct fwp_msgb *msgb;
580         
581 /*      if (!fwp_endpoint_is_valid(epointd)){
582                 errno = EINVAL;
583                 return -1;
584         }
585         if (!fwp_endpoint_is_bound(epointd)){
586                 errno = EPERM;
587                 return -1;
588         }*/
589
590         /*if (flags && MSG_DONTWAIT) 
591                 msgb = fwp_msgb_alloc(buffer_size);
592         else {*/
593                 if (!(msgb = fwp_msgb_alloc(size))) {
594                         errno = ENOMEM;
595                         return -1;
596                 }
597
598                 /*msgb->peer = &ep->peer;*/
599                 /*msgb->data = msg;*/
600                 /*msgb->flags = epoint->flags;*/
601                 
602                 /* data must be copied since msg may change while
603                  * message is waiting in transmission queue 
604                  * */
605                 memcpy(msgb->data, msg, size);
606                 fwp_msgb_put(msgb, size);
607                 /*msgb->tail = msgb->data + size;
608                 msgb->len = size;*/
609
610         /*}*/
611
612         /* TODO: test whether _fwp_vres_send is successful */
613         return fwp_vres_send(ep->vres, msgb);
614 }
615