1 // CODYlib -*- mode:c++ -*-
2 // Copyright (C) 2020 Nathan Sidwell, nathan@acm.org
3 // License: Apache v2.0
15 #include <arpa/inet.h>
16 #include <netinet/in.h>
19 #ifndef AI_NUMERICSERV
20 #define AI_NUMERICSERV 0
23 // Client-side networking helpers
27 int OpenSocket (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 (connect (fd
, addr
, len
) < 0)
48 errstr
= "connecting socket";
55 int OpenLocal (char const **e
, char const *name
)
58 size_t len
= strlen (name
);
60 if (len
>= sizeof (addr
.sun_path
))
66 memset (&addr
, 0, offsetof (sockaddr_un
, sun_path
));
67 addr
.sun_family
= AF_UNIX
;
68 memcpy (addr
.sun_path
, name
, len
+ 1);
69 return OpenSocket (e
, (sockaddr
*)&addr
, sizeof (addr
));
72 int OpenInet6 (char const **e
, char const *name
, int port
)
74 addrinfo
*addrs
= nullptr;
76 char const *errstr
= nullptr;
78 fd
= socket (AF_INET6
, SOCK_STREAM
, 0);
97 hints
.ai_family
= AF_INET6
;
98 hints
.ai_socktype
= SOCK_STREAM
;
99 hints
.ai_protocol
= 0;
100 hints
.ai_addrlen
= 0;
101 hints
.ai_addr
= nullptr;
102 hints
.ai_canonname
= nullptr;
103 hints
.ai_next
= nullptr;
105 if (int err
= getaddrinfo (name
, nullptr, &hints
, &addrs
))
107 errstr
= gai_strerror (err
);
108 // What's the best errno to set?
114 memset (&addr
, 0, sizeof (addr
));
115 addr
.sin6_family
= AF_INET6
;
117 for (struct addrinfo
*next
= addrs
; next
; next
= next
->ai_next
)
118 if (next
->ai_family
== AF_INET6
119 && next
->ai_socktype
== SOCK_STREAM
)
121 sockaddr_in6
*in6
= (sockaddr_in6
*)next
->ai_addr
;
122 in6
->sin6_port
= htons (port
);
123 if (ntohs (in6
->sin6_port
) != port
)
125 else if (!connect (fd
, next
->ai_addr
, next
->ai_addrlen
))
128 errstr
= "connecting";
132 freeaddrinfo (addrs
);