Paparazzi UAS  v5.8.2_stable-0-g6260b7c
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
udp_socket.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009-2015 The Paparazzi Team
3  *
4  * This file is part of Paparazzi.
5  *
6  * Paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * Paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
27 #include "udp_socket.h"
28 #include <sys/socket.h>
29 #include <arpa/inet.h>
30 #include <netdb.h>
31 #include <sys/ioctl.h>
32 #include <stdio.h>
33 #include <errno.h>
34 #include <string.h>
35 
36 //#define TRACE(type,fmt,args...) fprintf(stderr, fmt, args)
37 #define TRACE(type,fmt,args...)
38 #define TRACE_ERROR 1
39 
49 int udp_socket_create(struct UdpSocket *sock, char *host, int port_out, int port_in, bool_t broadcast)
50 {
51  if (sock == NULL) {
52  return -1;
53  }
54 
55 #ifndef LINUX_LINK_STATIC
56  /* try to convert host ipv4 address to binary format */
57  struct in_addr host_ip;
58  if (host[0] != '\0' && !inet_aton(host, &host_ip)) {
59  /* not an IP address, try to resolve hostname */
60  struct hostent *hp;
61  hp = gethostbyname(host);
62  if (!hp) {
63  fprintf(stderr, "could not obtain address of %s\n", host);
64  return -1;
65  }
66  /* check if IPv4 address */
67  if (hp->h_addrtype == AF_INET && hp->h_length == 4) {
68  /* simply use first address */
69  memcpy(&host_ip.s_addr, hp->h_addr_list[0], hp->h_length);
70  } else {
71  return -1;
72  }
73  }
74 #endif
75 
76  // Create the socket with the correct protocl
77  sock->sockfd = socket(PF_INET, SOCK_DGRAM, 0);
78  int one = 1;
79  // Enable reusing of address
80  setsockopt(sock->sockfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
81 #ifdef SO_REUSEPORT
82  // needed for OSX
83  setsockopt(sock->sockfd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
84 #endif
85 
86  // Enable broadcasting
87  if (broadcast) {
88  setsockopt(sock->sockfd, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one));
89  }
90 
91  // if an input port was specified, bind to it
92  if (port_in >= 0) {
93  // Create the input address
94  sock->addr_in.sin_family = PF_INET;
95  sock->addr_in.sin_port = htons(port_in);
96  sock->addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
97 
98  bind(sock->sockfd, (struct sockaddr *)&sock->addr_in, sizeof(sock->addr_in));
99  }
100 
101  // set the output/destination address for use in sendto later
102  sock->addr_out.sin_family = PF_INET;
103  sock->addr_out.sin_port = htons(port_out);
104 #ifndef LINUX_LINK_STATIC
105  sock->addr_out.sin_addr.s_addr = host_ip.s_addr;
106 #else
107  sock->addr_out.sin_addr.s_addr = inet_addr(host);
108 #endif
109  return 0;
110 }
111 
119 int udp_socket_send(struct UdpSocket *sock, uint8_t *buffer, uint32_t len)
120 {
121  if (sock == NULL) {
122  return -1;
123  }
124 
125  ssize_t bytes_sent = sendto(sock->sockfd, buffer, len, 0,
126  (struct sockaddr *)&sock->addr_out, sizeof(sock->addr_out));
127  if (bytes_sent != ((ssize_t)len)) {
128  TRACE(TRACE_ERROR, "error sending to sock %d (%d)\n", (int)bytes_sent, strerror(errno));
129  }
130  return bytes_sent;
131 }
132 
140 int udp_socket_send_dontwait(struct UdpSocket *sock, uint8_t *buffer, uint32_t len)
141 {
142  if (sock == NULL) {
143  return -1;
144  }
145 
146  ssize_t bytes_sent = sendto(sock->sockfd, buffer, len, MSG_DONTWAIT,
147  (struct sockaddr *)&sock->addr_out, sizeof(sock->addr_out));
148  return bytes_sent;
149 }
150 
159 int udp_socket_recv_dontwait(struct UdpSocket *sock, uint8_t *buffer, uint32_t len)
160 {
161  socklen_t slen = sizeof(struct sockaddr_in);
162  ssize_t bytes_read = recvfrom(sock->sockfd, buffer, len, MSG_DONTWAIT,
163  (struct sockaddr *)&sock->addr_in, &slen);
164 
165  if (bytes_read == -1) {
166  // If not data is available, simply return zero bytes read, no error
167  if (errno == EWOULDBLOCK) {
168  return 0;
169  } else {
170  TRACE(TRACE_ERROR, "error reading from sock error %d \n", errno);
171  }
172  }
173 
174  return bytes_read;
175 }
176 
184 int udp_socket_recv(struct UdpSocket *sock, uint8_t *buffer, uint32_t len)
185 {
186  socklen_t slen = sizeof(struct sockaddr_in);
187  ssize_t bytes_read = recvfrom(sock->sockfd, buffer, len, 0,
188  (struct sockaddr *)&sock->addr_in, &slen);
189 
190  return (int)bytes_read;
191 }
192 
193 int udp_socket_subscribe_multicast(struct UdpSocket *sock, const char* multicast_addr) {
194  // Create the request
195  struct ip_mreq mreq;
196  mreq.imr_multiaddr.s_addr = inet_addr(multicast_addr);
197  mreq.imr_interface.s_addr = htonl(INADDR_ANY);
198 
199  // Send the request
200  return setsockopt(sock->sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq));
201 }
202 
203 int udp_socket_set_recvbuf(struct UdpSocket *sock, int buf_size) {
204  // Set and check
205  unsigned int optval_size = 4;
206  int buf_ret;
207  setsockopt(sock->sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&buf_size, optval_size);
208  getsockopt(sock->sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&buf_ret, &optval_size);
209 
210  if(buf_size != buf_ret)
211  return -1;
212 
213  return 0;
214 }
int udp_socket_send_dontwait(struct UdpSocket *sock, uint8_t *buffer, uint32_t len)
Send a packet from buffer, non-blocking.
Definition: udp_socket.c:140
int udp_socket_recv_dontwait(struct UdpSocket *sock, uint8_t *buffer, uint32_t len)
Receive a UDP packet, dont wait.
Definition: udp_socket.c:159
int udp_socket_recv(struct UdpSocket *sock, uint8_t *buffer, uint32_t len)
Receive one UDP packet, blocking.
Definition: udp_socket.c:184
Easily create and use UDP sockets.
#define TRACE_ERROR
Definition: udp_socket.c:38
int udp_socket_subscribe_multicast(struct UdpSocket *sock, const char *multicast_addr)
Definition: udp_socket.c:193
int sockfd
Definition: udp_socket.h:35
int udp_socket_send(struct UdpSocket *sock, uint8_t *buffer, uint32_t len)
Send a packet from buffer, blocking.
Definition: udp_socket.c:119
unsigned long uint32_t
Definition: types.h:18
struct sockaddr_in addr_in
Definition: udp_socket.h:36
struct sockaddr_in addr_out
Definition: udp_socket.h:37
unsigned char uint8_t
Definition: types.h:14
int udp_socket_create(struct UdpSocket *sock, char *host, int port_out, int port_in, bool_t broadcast)
Create UDP socket and bind it.
Definition: udp_socket.c:49
#define TRACE(type, fmt, args...)
Definition: udp_socket.c:37
int udp_socket_set_recvbuf(struct UdpSocket *sock, int buf_size)
Definition: udp_socket.c:203