1 /**************************************************************************/
2 /* ---------------------------------------------------------------------- */
3 /* Copyright (C) 2006 - 2008 FRESCOR consortium partners: */
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 */
12 /* Thales Communication S.A. FRANCE */
13 /* Visual Tools S.A. SPAIN */
14 /* Rapita Systems Ltd UK */
17 /* See http://www.frescor.org for a link to partners' websites */
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. */
25 /* This file is part of FWP (Frescor WLAN Protocol) */
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. */
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"
51 #include <netinet/in.h>
52 #include "fwp_utils.h"
55 #include "fwp_debug.h"
57 typedef unsigned int fwp_endpoint_id_t;
60 * Default fwp endpoint attributes
62 static fwp_endpoint_attr_t fwp_epoint_attr_default ={
63 .reliability = FWP_EPOINT_BESTEFFORT,
64 .max_connections = 20,
68 * FWP endpoint structure
71 /** Fwp endpoint attributes */
72 fwp_endpoint_attr_t attr;
73 /* Vres this fwp endpoint is bound to */
75 /** For send enpoint it contains destination address for
76 * receive endpoint it is filled with the msg source address
78 struct fwp_sockaddr peer;
79 /** Source/destination port */
81 /** Destination node */
83 /** Socket descriptor.
84 * In case of rebliable epoint it is a listen tcp socket.
87 /** File descriptor array of peers connected
88 * to this fwp receive endpoint.*/
91 * Number of connections
93 unsigned int nr_connections;
96 /** specific operation options*/
103 * \return On success returns fwp endpoint structure.
104 * On error, NULL is returned.
107 static fwp_endpoint_t* fwp_endpoint_alloc()
109 return (fwp_endpoint_t*) calloc(1,sizeof(fwp_endpoint_t));
115 * \return On success returns endpoint structure.
116 * On error, NULL is returned.
119 static inline void fwp_endpoint_free(fwp_endpoint_t *endpoint)
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.
131 int fwp_endpoint_destroy(fwp_endpoint_t *ep)
136 fwp_endpoint_free(ep);
141 * Get endpoint parameters
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.
150 int fwp_endpoint_get_params(fwp_endpoint_t *ep, unsigned int *node,
151 unsigned int *port, fwp_endpoint_attr_t *attr)
153 if (node) *node = ep->node;
154 if (port) *port = ep->port;
155 if (attr) *attr = ep->attr;
160 int fwp_endpoint_attr_init(fwp_endpoint_attr_t *attr)
162 bzero(attr, sizeof(fwp_endpoint_attr_t));
163 *attr = fwp_epoint_attr_default;
169 * Creates send endpoint
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
176 * \return Zero on success, -1 on error and sets errno appropriately.
179 int fwp_send_endpoint_create(unsigned int node,
181 fwp_endpoint_attr_t *attr,
182 fwp_endpoint_t **epoint)
184 struct sockaddr_in *addr;
185 fwp_endpoint_t *fwp_epoint;
187 fwp_epoint = fwp_endpoint_alloc();
193 /*epoint->type = FWP_SEND_EPOINT;
194 epoint->status = FWP_EPOINT_UNBOUND;
199 fwp_epoint->attr = *attr;
201 fwp_epoint->attr = fwp_epoint_attr_default;
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);
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) {
216 fwp_epoint->sockd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
217 if (fwp_epoint->sockd < 0) {
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));
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));
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");
245 FWP_DEBUG("FWP Send endpoint created.\n");
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)) {
254 fwp_send_endpoint_bind(fwp_epoint, fwp_epoint->vresd);
257 *epoint = fwp_epoint;
258 return fwp_epoint->sockd;
260 fwp_endpoint_destroy(fwp_epoint);
265 * Creates receive endpoint
267 * \param[in] port UDP port
268 * \param[in] attr Endpoint attributes
269 * \param[out] epointdp Pointer to the descriptor of newly created endpoint
271 * \return Zero on success, -1 on error and errno is set.
273 int fwp_receive_endpoint_create(unsigned int port,
274 fwp_endpoint_attr_t *attr,
275 fwp_endpoint_t **epp)
277 struct sockaddr_in *addr;
278 fwp_endpoint_t *fwp_epoint;
280 fwp_epoint = fwp_endpoint_alloc();
286 /*epoint->type = FWP_RECV_EPOINT;
287 epoint->status = FWP_EPOINT_UNBOUND;*/
290 fwp_epoint->attr = *attr;
292 fwp_epoint->attr = fwp_epoint_attr_default;
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);
301 if (fwp_epoint->attr.reliability == FWP_EPOINT_RELIABLE) {
302 if ((fwp_epoint->sockd = socket(PF_INET, SOCK_STREAM,
304 FWP_ERROR("Unable to open socket: %s", strerror(errno));
309 if (setsockopt(fwp_epoint->sockd,SOL_SOCKET, SO_REUSEADDR,
310 &yes, sizeof(yes)) == -1) {
311 FWP_ERROR("setsockopt(SO_REUSEADDR):%s",strerror(errno));
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 */
322 if (listen(fwp_epoint->sockd, fwp_epoint->attr.max_connections)){
323 FWP_ERROR("Error on listen call: %s\n", strerror(errno));
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;
335 FWP_DEBUG("Reliable receive endpoint port=%d created.\n",
338 if ((fwp_epoint->sockd = socket(PF_INET, SOCK_DGRAM,
340 FWP_ERROR("Unable to open socket: %s", strerror(errno));
344 if (bind(fwp_epoint->sockd,
345 (struct sockaddr*) &fwp_epoint->peer.addr,
346 fwp_epoint->peer.addrlen) == -1) {
348 FWP_ERROR("Bind error: %s", strerror(errno));
351 FWP_DEBUG("Best-Effort receive endpoint port=%d created.\n",
355 /*if (setsockopt(epoint->sockd, SOL_SOCKET, SO_RCVBUF,
356 &rcvbuf_size, sizeof(rcvbuf_size)) == -1) {
358 FWP_ERROR("Unable to set socket buffer size: %s", strerror(errno));
361 FWP_DEBUG("Receive endpoint buffer size is set.\n");
365 getsockname(fwp_epoint->sockd, (struct sockaddr*)&fwp_epoint->peer.addr,
366 &fwp_epoint->peer.addrlen);
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));
374 fwp_endpoint_destroy(fwp_epoint);
379 * Binds send endpoint to vres
381 * \param[in] vres identifier of vres
382 * \param[in] ep send endpoint identifier
384 * \return On success returns 0. On error, -1 and errno is set appropriately.
386 int fwp_send_endpoint_bind(fwp_endpoint_t *ep, fwp_vres_t *vres)
389 #ifndef FWP_WITHOUT_CONTNEGT
392 rv = fwp_vres_bind(vres, ep->sockd);
394 /* if send endpoint is already bound
395 if (epoint->type == FWP_EPOINT_BOUND) {
396 fwp_send_endpoint_unbind(epoint);
402 * Unbinds send endpoint from vres
404 * \param[in] epointd Send endpoint descriptor
405 * \return On success returns 0. On error, -1 is returned and errno is set appropriately.
408 int fwp_send_endpoint_unbind(fwp_endpoint_t *ep)
412 /* unlink epoint-vres mutually */
413 if ((rv = fwp_vres_unbind(ep->vres)) < 0)
420 * Accepts (TCP) client connection to receive endpoint
422 * \param[in] epointd Pointer to fwp endpoint
424 * On success, it returns zero.
427 static int fwp_receive_endpoint_accept(fwp_endpoint_t *fwp_epoint)
430 // fwp_endpoint_t *fwp_epoint = epointd;
434 if (fwp_epoint->nr_connections == fwp_epoint->attr.max_connections)
437 peer.addrlen = sizeof(struct sockaddr_in);
438 csockd = accept(fwp_epoint->sockd, (struct sockaddr*)peer.addr,
442 FWP_ERROR("Error on accept: %s\n", strerror(errno));
446 FWP_DEBUG("New connection accepted\n");
447 /* find free place */
449 while ((fwp_epoint->c_sockd[i])&& (i < fwp_epoint->nr_connections))
451 fwp_epoint->c_sockd[i] = csockd;
452 fwp_epoint->nr_connections++;
454 FD_SET(csockd, &fwp_epoint->fdset);
459 * Receives message from stream (TCP)
461 * \param[in] epointd Descriptor of endpoint
462 * \param[in] buffer Buffer to store message
463 * \param[in] buffer_size Size of buffer
466 * On success, it returns number of received bytes.
467 * On error, -1 is returned and errno is set appropriately.
470 int fwp_recv_conn(fwp_endpoint_t *ep, void *buffer,
473 fwp_sockaddr_t *peer = &ep->peer;
474 fd_set fdset = ep->fdset;
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)) {
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);
489 if (len < 0) /* Error */
492 FWP_DEBUG("Received tcp data\n");
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--;
510 * \param[in] epointd Descriptor of endpoint
511 * \param[in] buffer Buffer to store message
512 * \param[in] buffer_size Size of buffer
515 * On success, it returns number of received bytes.
516 * On error, -1 is returned and errno is set appropriately.
519 ssize_t fwp_recv(fwp_endpoint_t *ep,
520 void *buffer, const size_t buffer_size,
521 unsigned int *from, int flags)
523 fwp_sockaddr_t *peer = &ep->peer;
524 struct sockaddr_in *addr = (struct sockaddr_in*) ep->peer.addr;
528 /*if (!fwp_endpoint_is_valid(epointd)) {
533 if (ep->attr.reliability == FWP_EPOINT_BESTEFFORT) {
534 len = _fwp_recvfrom(ep->sockd, buffer,
535 buffer_size, 0, peer);
537 *from = addr->sin_addr.s_addr;
542 /* FWP_EPOINT_RELIABLE */
544 if (select(FD_SETSIZE, &fdset, (fd_set *)0,
545 (fd_set *)0, NULL) < 0) {
547 FWP_ERROR("Error in select: %s", strerror(errno));
551 if (FD_ISSET(ep->sockd, &fdset)) { /* is it listen socket? */
552 fwp_receive_endpoint_accept(ep);
556 /* Check client TCP sockets */
557 len = fwp_recv_conn(ep, buffer, buffer_size);
559 *from = addr->sin_addr.s_addr;
566 * Sends message through vres
568 * \param[in] epointd Endpoint descriptor
569 * \param[in] msg Message to sent
570 * \param[in] size Message size
573 * On success, it returns zero.
574 * On error, -1 is returned and errno is set appropriately.
577 int fwp_send(fwp_endpoint_t *ep,const void *msg, const size_t size)
579 struct fwp_msgb *msgb;
581 /* if (!fwp_endpoint_is_valid(epointd)){
585 if (!fwp_endpoint_is_bound(epointd)){
590 /*if (flags && MSG_DONTWAIT)
591 msgb = fwp_msgb_alloc(buffer_size);
593 if (!(msgb = fwp_msgb_alloc(size))) {
598 /*msgb->peer = &ep->peer;*/
599 /*msgb->data = msg;*/
600 /*msgb->flags = epoint->flags;*/
602 /* data must be copied since msg may change while
603 * message is waiting in transmission queue
605 memcpy(msgb->data, msg, size);
606 fwp_msgb_put(msgb, size);
607 /*msgb->tail = msgb->data + size;
612 /* TODO: test whether _fwp_vres_send is successful */
613 return fwp_vres_send(ep->vres, msgb);