1 // CODYlib -*- mode:c++ -*-
2 // Copyright (C) 2020 Nathan Sidwell, nathan@acm.org
3 // License: Apache v2.0
14 #include <arpa/inet.h>
15 #include <netinet/in.h>
18 #ifndef AI_NUMERICSERV
19 #define AI_NUMERICSERV 0
22 // Server-side networking helpers
26 int ListenSocket (char const **e
, sockaddr
const *addr
, socklen_t len
,
29 char const *errstr
= nullptr;
31 int fd
= socket (addr
->sa_family
, SOCK_STREAM
, 0);
34 errstr
= "creating socket";
46 if (bind (fd
, addr
, len
) < 0)
48 errstr
= "binding socket";
52 if (listen (fd
, backlog
? backlog
: 17) < 0)
54 errstr
= "listening socket";
61 int ListenLocal (char const **e
, char const *name
, unsigned backlog
)
64 size_t len
= strlen (name
);
66 if (len
>= sizeof (addr
.sun_path
))
72 memset (&addr
, 0, offsetof (sockaddr_un
, sun_path
));
73 addr
.sun_family
= AF_UNIX
;
74 memcpy (addr
.sun_path
, name
, len
+ 1);
76 return ListenSocket (e
, (sockaddr
*)&addr
, sizeof (addr
), backlog
);
79 int ListenInet6 (char const **e
, char const *name
, int port
, unsigned backlog
)
81 addrinfo
*addrs
= nullptr;
83 char const *errstr
= nullptr;
85 fd
= socket (AF_INET6
, SOCK_STREAM
, 0);
88 errstr
= "creating socket";
103 hints
.ai_flags
= AI_NUMERICSERV
;
104 hints
.ai_family
= AF_INET6
;
105 hints
.ai_socktype
= SOCK_STREAM
;
106 hints
.ai_protocol
= 0;
107 hints
.ai_addrlen
= 0;
108 hints
.ai_addr
= nullptr;
109 hints
.ai_canonname
= nullptr;
110 hints
.ai_next
= nullptr;
112 /* getaddrinfo requires a port number, but is quite happy to accept
113 invalid ones. So don't rely on it. */
114 if (int err
= getaddrinfo (name
, "0", &hints
, &addrs
))
116 errstr
= gai_strerror (err
);
117 // What's the best errno to set?
123 memset (&addr
, 0, sizeof (addr
));
124 addr
.sin6_family
= AF_INET6
;
126 for (struct addrinfo
*next
= addrs
; next
; next
= next
->ai_next
)
127 if (next
->ai_family
== AF_INET6
128 && next
->ai_socktype
== SOCK_STREAM
)
130 sockaddr_in6
*in6
= (sockaddr_in6
*)next
->ai_addr
;
131 in6
->sin6_port
= htons (port
);
132 if (ntohs (in6
->sin6_port
) != port
)
134 else if (!bind (fd
, next
->ai_addr
, next
->ai_addrlen
))
138 errstr
= "binding socket";
142 freeaddrinfo (addrs
);
145 if (listen (fd
, backlog
? backlog
: 17) < 0)
147 errstr
= "listening socket";