2 #include <sys/socket.h>
14 static void usock_set_flags(int sock
, unsigned int type
)
16 if (!(type
& USOCK_NOCLOEXEC
))
17 fcntl(sock
, F_SETFD
, fcntl(sock
, F_GETFD
) | FD_CLOEXEC
);
19 if (type
& USOCK_NONBLOCK
)
20 fcntl(sock
, F_SETFL
, fcntl(sock
, F_GETFL
) | O_NONBLOCK
);
23 static int usock_connect(struct sockaddr
*sa
, int sa_len
, int family
, int socktype
, bool server
)
27 sock
= socket(family
, socktype
, 0);
33 setsockopt(sock
, SOL_SOCKET
, SO_REUSEADDR
, &one
, sizeof(one
));
35 if (!bind(sock
, sa
, sa_len
) &&
36 (socktype
!= SOCK_STREAM
|| !listen(sock
, SOMAXCONN
)))
39 if (!connect(sock
, sa
, sa_len
) || errno
== EINPROGRESS
)
47 static int usock_unix(const char *host
, int socktype
, bool server
)
49 struct sockaddr_un sun
= {.sun_family
= AF_UNIX
};
51 if (strlen(host
) >= sizeof(sun
.sun_path
)) {
55 strcpy(sun
.sun_path
, host
);
57 return usock_connect((struct sockaddr
*)&sun
, sizeof(sun
), AF_UNIX
, socktype
, server
);
60 static int usock_inet(int type
, const char *host
, const char *service
, int socktype
, bool server
)
62 struct addrinfo
*result
, *rp
;
63 struct addrinfo hints
= {
64 .ai_family
= (type
& USOCK_IPV6ONLY
) ? AF_INET6
:
65 (type
& USOCK_IPV4ONLY
) ? AF_INET
: AF_UNSPEC
,
66 .ai_socktype
= socktype
,
67 .ai_flags
= AI_ADDRCONFIG
68 | ((type
& USOCK_SERVER
) ? AI_PASSIVE
: 0)
69 | ((type
& USOCK_NUMERIC
) ? AI_NUMERICHOST
: 0),
73 if (getaddrinfo(host
, service
, &hints
, &result
))
76 for (rp
= result
; rp
!= NULL
; rp
= rp
->ai_next
) {
77 sock
= usock_connect(rp
->ai_addr
, rp
->ai_addrlen
, rp
->ai_family
, socktype
, server
);
86 int usock(int type
, const char *host
, const char *service
) {
87 int socktype
= ((type
& 0xff) == USOCK_TCP
) ? SOCK_STREAM
: SOCK_DGRAM
;
88 bool server
= !!(type
& USOCK_SERVER
);
91 if (type
& USOCK_UNIX
)
92 sock
= usock_unix(host
, socktype
, server
);
94 sock
= usock_inet(type
, host
, service
, socktype
, server
);
99 usock_set_flags(sock
, type
);