meson: Simplify code for libusb dependency
[libjaylink.git] / libjaylink / socket.c
blob6a9fdd7692853280218ad466e14663c3e8807cae
1 /*
2 * This file is part of the libjaylink project.
4 * Copyright (C) 2016-2017 Marc Schink <jaylink-dev@marcschink.de>
6 * This program 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 of the License, or
9 * (at your option) any later version.
11 * This program 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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <errno.h>
21 #ifdef _WIN32
22 #include <winsock2.h>
23 #else
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #endif
30 #include "libjaylink.h"
31 #include "libjaylink-internal.h"
33 /**
34 * @file
36 * Socket abstraction layer.
39 /**
40 * Initiate a connection on a socket.
42 * @param[in] sock Socket descriptor.
43 * @param[in] address Address to establish the connection.
44 * @param[in] length Length of the structure pointed to by @p address in bytes.
45 * @param[in] timeout Connection timeout in milliseconds, 0 for no timeout.
47 * @retval JAYLINK_OK Success.
48 * @retval JAYLINK_ERR_ARG Invalid arguments.
49 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
50 * @retval JAYLINK_ERR Other error conditions.
52 JAYLINK_PRIV int socket_connect(int sock, const struct sockaddr *address,
53 size_t address_length, size_t timeout)
55 int ret;
56 fd_set fds;
57 struct timeval tv;
58 int socket_error;
59 size_t option_length;
61 if (!address)
62 return JAYLINK_ERR_ARG;
64 if (!socket_set_blocking(sock, false))
65 return JAYLINK_ERR;
66 #ifdef _WIN32
67 ret = connect(sock, address, address_length);
69 if (ret != 0 && WSAGetLastError() != WSAEWOULDBLOCK)
70 return JAYLINK_ERR;
71 #else
72 errno = 0;
73 ret = connect(sock, address, address_length);
75 if (ret != 0 && errno != EINPROGRESS)
76 return JAYLINK_ERR;
77 #endif
78 if (!ret)
79 return JAYLINK_OK;
81 FD_ZERO(&fds);
82 FD_SET(sock, &fds);
84 tv.tv_sec = timeout / 1000;
85 tv.tv_usec = (timeout % 1000) * 1000;
87 ret = select(sock + 1, NULL, &fds, NULL, &tv);
89 socket_set_blocking(sock, true);
91 if (!ret)
92 return JAYLINK_ERR_TIMEOUT;
94 option_length = sizeof(socket_error);
96 if (!socket_get_option(sock, SOL_SOCKET, SO_ERROR, &socket_error,
97 &option_length))
98 return JAYLINK_ERR;
100 if (!socket_error)
101 return JAYLINK_OK;
103 return JAYLINK_ERR;
107 * Close a socket.
109 * @param[in] sock Socket descriptor.
111 * @return Whether the socket was successfully closed.
113 JAYLINK_PRIV bool socket_close(int sock)
115 int ret;
117 #ifdef _WIN32
118 ret = closesocket(sock);
119 #else
120 ret = close(sock);
121 #endif
123 if (!ret)
124 return true;
126 return false;
130 * Bind an address to a socket.
132 * @param[in] sock Socket descriptor.
133 * @param[in] address Address to be bound to the socket.
134 * @param[in] length Length of the structure pointed to by @p address in bytes.
136 * @return Whether the address was successfully assigned to the socket.
138 JAYLINK_PRIV bool socket_bind(int sock, const struct sockaddr *address,
139 size_t length)
141 int ret;
143 ret = bind(sock, address, length);
145 #ifdef _WIN32
146 if (ret == SOCKET_ERROR)
147 return false;
148 #else
149 if (ret < 0)
150 return false;
151 #endif
153 return true;
157 * Send a message on a socket.
159 * @param[in] sock Socket descriptor.
160 * @param[in] buffer Buffer of the message to be sent.
161 * @param[in,out] length Length of the message in bytes. On success, the value
162 * gets updated with the actual number of bytes sent. The
163 * value is undefined on failure.
164 * @param[in] flags Flags to modify the function behaviour. Use bitwise OR to
165 * specify multiple flags.
167 * @return Whether the message was sent successfully.
169 JAYLINK_PRIV bool socket_send(int sock, const void *buffer, size_t *length,
170 int flags)
172 ssize_t ret;
174 ret = send(sock, buffer, *length, flags);
175 #ifdef _WIN32
176 if (ret == SOCKET_ERROR)
177 return false;
178 #else
179 if (ret < 0)
180 return false;
181 #endif
182 *length = ret;
184 return true;
188 * Receive a message from a socket.
190 * @param[in] sock Socket descriptor.
191 * @param[out] buffer Buffer to store the received message on success. Its
192 * content is undefined on failure.
193 * @param[in,out] length Maximum length of the message in bytes. On success,
194 * the value gets updated with the actual number of
195 * received bytes. The value is undefined on failure.
196 * @param[in] flags Flags to modify the function behaviour. Use bitwise OR to
197 * specify multiple flags.
199 * @return Whether a message was successfully received.
201 JAYLINK_PRIV bool socket_recv(int sock, void *buffer, size_t *length,
202 int flags)
204 ssize_t ret;
206 ret = recv(sock, buffer, *length, flags);
208 #ifdef _WIN32
209 if (ret == SOCKET_ERROR)
210 return false;
211 #else
212 if (ret < 0)
213 return false;
214 #endif
216 *length = ret;
218 return true;
222 * Send a message on a socket.
224 * @param[in] sock Socket descriptor.
225 * @param[in] buffer Buffer to send message from.
226 * @param[in,out] length Number of bytes to send. On success, the value gets
227 * updated with the actual number of bytes sent. The
228 * value is undefined on failure.
229 * @param[in] flags Flags to modify the function behaviour. Use bitwise OR to
230 * specify multiple flags.
231 * @param[in] address Destination address of the message.
232 * @param[in] address_length Length of the structure pointed to by @p address
233 * in bytes.
235 * @return Whether the message was successfully sent.
237 JAYLINK_PRIV bool socket_sendto(int sock, const void *buffer, size_t *length,
238 int flags, const struct sockaddr *address,
239 size_t address_length)
241 ssize_t ret;
243 ret = sendto(sock, buffer, *length, flags, address, address_length);
245 #ifdef _WIN32
246 if (ret == SOCKET_ERROR)
247 return false;
248 #else
249 if (ret < 0)
250 return false;
251 #endif
253 *length = ret;
255 return true;
259 * Receive a message from a socket.
261 * @param[in] sock Socket descriptor.
262 * @param[out] buffer Buffer to store the received message on success. Its
263 * content is undefined on failure.
264 * @param[in,out] length Maximum length of the message in bytes. On success,
265 * the value gets updated with the actual number of
266 * received bytes. The value is undefined on failure.
267 * @param[in] flags Flags to modify the function behaviour. Use bitwise OR to
268 * specify multiple flags.
269 * @param[out] address Structure to store the source address of the message on
270 * success. Its content is undefined on failure.
271 * Can be NULL.
272 * @param[in,out] address_length Length of the structure pointed to by
273 * @p address in bytes. On success, the value
274 * gets updated with the actual length of the
275 * structure. The value is undefined on failure.
276 * Should be NULL if @p address is NULL.
278 * @return Whether a message was successfully received.
280 JAYLINK_PRIV bool socket_recvfrom(int sock, void *buffer, size_t *length,
281 int flags, struct sockaddr *address, size_t *address_length)
283 ssize_t ret;
284 #ifdef _WIN32
285 int tmp;
287 tmp = *address_length;
288 ret = recvfrom(sock, buffer, *length, flags, address, &tmp);
290 if (ret == SOCKET_ERROR)
291 return false;
292 #else
293 socklen_t tmp;
295 tmp = *address_length;
296 ret = recvfrom(sock, buffer, *length, flags, address, &tmp);
298 if (ret < 0)
299 return false;
300 #endif
302 *address_length = tmp;
303 *length = ret;
305 return true;
309 * Get the value of a socket option.
311 * @param[in] sock Socket descriptor.
312 * @param[in] level Level at which the option is defined.
313 * @param[in] option Option to get the value for.
314 * @param[in] value Buffer to store the value.
315 * @param[in] length Length of the value buffer in bytes.
317 * @return Whether the option value was retrieved successfully.
319 JAYLINK_PRIV bool socket_get_option(int sock, int level, int option,
320 void *value, size_t *length)
322 if (!getsockopt(sock, level, option, value, (socklen_t *)length))
323 return true;
325 return false;
329 * Set the value of a socket option.
331 * @param[in] sock Socket descriptor.
332 * @param[in] level Level at which the option is defined.
333 * @param[in] option Option to set the value for.
334 * @param[in] value Buffer of the value to be set.
335 * @param[in] length Length of the value buffer in bytes.
337 * @return Whether the option value was set successfully.
339 JAYLINK_PRIV bool socket_set_option(int sock, int level, int option,
340 const void *value, size_t length)
342 if (!setsockopt(sock, level, option, value, length))
343 return true;
345 return false;
349 * Set the blocking mode of a socket.
351 * @param[in] sock Socket descriptor.
352 * @param[in] blocking Blocking mode.
354 * @return Whether the blocking mode was set successfully.
356 JAYLINK_PRIV bool socket_set_blocking(int sock, bool blocking)
358 int ret;
359 #ifdef _WIN32
360 u_long mode;
362 mode = !blocking;
363 ret = ioctlsocket(sock, FIONBIO, &mode);
365 if (ret != NO_ERROR)
366 return false;
367 #else
368 int flags;
370 flags = fcntl(sock, F_GETFL, 0);
372 if (flags < 0)
373 return false;
375 if (blocking)
376 flags &= ~O_NONBLOCK;
377 else
378 flags |= O_NONBLOCK;
380 ret = fcntl(sock, F_SETFL, flags);
382 if (ret != 0)
383 return false;
384 #endif
385 return true;