1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
/* Licensed under BSD-MIT - see LICENSE file for details */
#ifndef CCAN_NET_H
#define CCAN_NET_H
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdbool.h>
struct pollfd;
/**
* net_client_lookup - look up a network name to connect to.
* @hostname: the name to look up
* @service: the service to look up
* @family: Usually AF_UNSPEC, otherwise AF_INET or AF_INET6.
* @socktype: SOCK_DGRAM or SOCK_STREAM.
*
* This will do a synchronous lookup of a given name, returning a linked list
* of results, or NULL on error. You should use freeaddrinfo() to free it.
*
* Example:
* #include <stdio.h>
* #include <poll.h>
* #include <err.h>
* ...
* struct addrinfo *addr;
*
* // Get a TCP connection to ccan.ozlabs.org daytime port.
* addr = net_client_lookup("ccan.ozlabs.org", "daytime",
* AF_UNSPEC, SOCK_STREAM);
* if (!addr)
* errx(1, "Failed to look up daytime at ccan.ozlabs.org");
*/
struct addrinfo *net_client_lookup(const char *hostname,
const char *service,
int family,
int socktype);
/**
* net_connect - connect to a server
* @addrinfo: linked list struct addrinfo (usually from net_client_lookup).
*
* This synchronously connects to a server described by @addrinfo, or returns
* -1 on error (and sets errno).
*
* Example:
* int fd;
* ...
* fd = net_connect(addr);
* if (fd < 0)
* err(1, "Failed to connect to ccan.ozlabs.org");
* freeaddrinfo(addr);
*/
int net_connect(const struct addrinfo *addrinfo);
/**
* net_connect_async - initiate connect to a server
* @addrinfo: linked list struct addrinfo (usually from net_client_lookup).
* @pfds: array of two struct pollfd.
*
* This begins connecting to a server described by @addrinfo,
* and places the one or two file descriptors into pfds[0] and pfds[1].
* It returns a valid file descriptor if connect() returned immediately.
*
* Otherwise it returns -1 and sets errno, most likely EINPROGRESS.
* In this case, poll() on pfds and call net_connect_complete().
*
* Example:
* struct pollfd pfds[2];
* ...
* fd = net_connect_async(addr, pfds);
* if (fd < 0 && errno != EINPROGRESS)
* err(1, "Failed to connect to ccan.ozlabs.org");
*/
int net_connect_async(const struct addrinfo *addrinfo, struct pollfd *pfds);
/**
* net_connect_complete - complete net_connect_async call.
* @pfds: array of two struct pollfd handed to net_connect_async.
*
* When poll() reports some activity, this determines whether a connection
* has completed. If so, it cleans up and returns the connected fd.
* Otherwise, it returns -1, and sets errno (usually EINPROGRESS).
*
* Example:
* // After net_connect_async.
* while (fd < 0 && errno == EINPROGRESS) {
* // Wait for activity...
* poll(pfds, 2, -1);
* fd = net_connect_complete(pfds);
* }
* if (fd < 0)
* err(1, "connecting");
* printf("Connected on fd %i!\n", fd);
*/
int net_connect_complete(struct pollfd *pfds);
/**
* net_connect_abort - abort a net_connect_async call.
* @pfds: array of two struct pollfd handed to net_connect_async.
*
* Closes the file descriptors.
*
* Example:
* // After net_connect_async.
* if (poll(pfds, 2, 1000) == 0) { // Timeout.
* net_connect_abort(pfds);
* fd = -1;
* } else {
* fd = net_connect_complete(pfds);
* if (fd < 0)
* err(1, "connecting");
* }
*/
void net_connect_abort(struct pollfd *pfds);
/**
* net_server_lookup - look up a service name to bind to.
* @service: the service to look up
* @family: Usually AF_UNSPEC, otherwise AF_INET or AF_INET6.
* @socktype: SOCK_DGRAM or SOCK_STREAM.
*
* This will do a synchronous lookup of a given name, returning a linked list
* of results, or NULL on error. You should use freeaddrinfo() to free it.
*
* Example:
* #include <stdio.h>
* #include <err.h>
* ...
* struct addrinfo *addr;
*
* // Get address(es) to bind for our service.
* addr = net_server_lookup("8888", AF_UNSPEC, SOCK_STREAM);
* if (!addr)
* errx(1, "Failed to look up 8888 to bind to");
*/
struct addrinfo *net_server_lookup(const char *service,
int family,
int socktype);
/**
* net_bind - create listening socket(s)
* @addrinfo: the address(es) to bind to.
* @fds: array of two fds.
*
* This will create one (or if necessary) two sockets, mark them
* SO_REUSEADDR, bind them to the given address(es), and make them
* listen() (if the socket type is SOCK_STREAM or SOCK_SEQPACKET).
*
* Returns -1 (and sets errno) on error, or 1 or 2 depending on how many
* @fds are valid.
*
* Example:
* int fds[2], i, num_fds;
*
* num_fds = net_bind(addr, fds);
* if (num_fds < 0)
* err(1, "Failed to listen on port 8888");
*
* for (i = 0; i < num_fds; i++)
* printf(" Got fd %u/%u: %i\n", i, num_fds, fds[i]);
*/
int net_bind(const struct addrinfo *addrinfo, int fds[2]);
#endif /* CCAN_NET_H */
|