int
rspamd_inet_address_listen (const rspamd_inet_addr_t *addr, gint type,
- gboolean async)
+ enum rspamd_inet_address_listen_opts opts,
+ gint listen_queue)
{
gint fd, r;
- gint on = 1;
+ gint on = 1, serrno;
const struct sockaddr *sa;
const char *path;
return -1;
}
- fd = rspamd_socket_create (addr->af, type, 0, async);
+ fd = rspamd_socket_create (addr->af, type, 0,
+ (opts & RSPAMD_INET_ADDRESS_LISTEN_ASYNC));
if (fd == -1) {
return -1;
}
sa = &addr->u.in.addr.sa;
}
- (void)setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof (gint));
+#if defined(SO_REUSEADDR)
+ if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof (gint)) == -1) {
+ msg_err ("cannot set SO_REUSEADDR on %d: %d", fd, strerror (errno));
+ goto err;
+ }
+#endif
+
+#if defined(SO_REUSEPORT)
+ if (opts & RSPAMD_INET_ADDRESS_LISTEN_REUSEPORT) {
+ on = 1;
+
+ if (setsockopt (fd, SOL_SOCKET, SO_REUSEPORT, (const void *)&on, sizeof (gint)) == -1) {
+ msg_err ("cannot set SO_REUSEPORT on %d: %d", fd, strerror (errno));
+ goto err;
+ }
+ }
+#endif
#ifdef HAVE_IPV6_V6ONLY
if (addr->af == AF_INET6) {
r = bind (fd, sa, addr->slen);
if (r == -1) {
- if (!async || errno != EINPROGRESS) {
- close (fd);
+ if (!(opts & RSPAMD_INET_ADDRESS_LISTEN_ASYNC) || errno != EINPROGRESS) {
msg_warn ("bind %s failed: %d, '%s'",
rspamd_inet_address_to_string_pretty (addr),
errno,
strerror (errno));
- return -1;
+
+ goto err;
}
}
path, addr->u.un->mode, strerror (errno));
}
}
- r = listen (fd, -1);
+
+ r = listen (fd, listen_queue);
if (r == -1) {
msg_warn ("listen %s failed: %d, '%s'",
rspamd_inet_address_to_string_pretty (addr),
errno, strerror (errno));
- close (fd);
- return -1;
+
+ goto err;
}
}
return fd;
+
+err:
+ /* Error path */
+ serrno = errno;
+
+ if (fd != -1) {
+ close (fd);
+ }
+
+ errno = serrno;
+
+ return -1;
}
gssize
int rspamd_inet_address_connect (const rspamd_inet_addr_t *addr, gint type,
gboolean async);
+enum rspamd_inet_address_listen_opts {
+ RSPAMD_INET_ADDRESS_LISTEN_DEFAULT = 0,
+ RSPAMD_INET_ADDRESS_LISTEN_ASYNC = (1u << 0u),
+ RSPAMD_INET_ADDRESS_LISTEN_REUSEPORT = (1u << 1u),
+};
/**
* Listen on a specified inet address
* @param addr
* @param type
- * @param async
+ * @param opts
* @return
*/
int rspamd_inet_address_listen (const rspamd_inet_addr_t *addr, gint type,
- gboolean async);
+ enum rspamd_inet_address_listen_opts opts,
+ gint listen_queue);
/**
* Check whether specified ip is valid (not INADDR_ANY or INADDR_NONE) for ipv4 or ipv6
*/
if (listen_type & RSPAMD_WORKER_SOCKET_TCP) {
fd = rspamd_inet_address_listen (g_ptr_array_index (addrs, i),
- SOCK_STREAM, TRUE);
+ SOCK_STREAM, RSPAMD_INET_ADDRESS_LISTEN_ASYNC, -1);
if (fd != -1) {
ls = g_malloc0 (sizeof (*ls));
ls->addr = rspamd_inet_address_copy (g_ptr_array_index (addrs, i));
}
if (listen_type & RSPAMD_WORKER_SOCKET_UDP) {
fd = rspamd_inet_address_listen (g_ptr_array_index (addrs, i),
- SOCK_DGRAM, TRUE);
+ SOCK_DGRAM, RSPAMD_INET_ADDRESS_LISTEN_ASYNC, -1);
if (fd != -1) {
ls = g_malloc0 (sizeof (*ls));
ls->addr = rspamd_inet_address_copy (g_ptr_array_index (addrs, i));
}
else {
control_fd = rspamd_inet_address_listen (control_addr, SOCK_STREAM,
- TRUE);
+ RSPAMD_INET_ADDRESS_LISTEN_ASYNC, -1);
if (control_fd == -1) {
msg_err_main ("cannot open control socket at path: %s",
rspamd_main->cfg->control_socket_path);