]> git.saurik.com Git - apple/mdnsresponder.git/blob - ServiceRegistration/ioloop.h
mDNSResponder-1310.80.1.tar.gz
[apple/mdnsresponder.git] / ServiceRegistration / ioloop.h
1 /* ioloop.h
2 *
3 * Copyright (c) 2018-2019 Apple Computer, Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * Definitions for simple dispatch implementation.
18 */
19
20 #ifndef __IOLOOP_H
21 #define __IOLOOP_H
22
23 #ifdef IOLOOP_MACOS
24 #include <nw/private.h>
25 #include <Network/Network.h>
26 #include <xpc/xpc.h>
27 #include <xpc/private.h>
28 #endif
29
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <net/if_dl.h>
33
34 #ifndef __DSO_H
35 typedef struct dso_state dso_state_t;
36 #endif
37
38 typedef union addr addr_t;
39 union addr {
40 struct sockaddr sa;
41 struct sockaddr_in sin;
42 struct sockaddr_in6 sin6;
43 struct {
44 char len;
45 char family;
46 int index;
47 uint8_t addr[8];
48 } ether_addr;
49 };
50
51 #define IOLOOP_NTOP(addr, buf) \
52 (((addr)->sa.sa_family == AF_INET || (addr)->sa.sa_family == AF_INET6) \
53 ? (inet_ntop((addr)->sa.sa_family, ((addr)->sa.sa_family == AF_INET \
54 ? (void *)&(addr)->sin.sin_addr \
55 : (void *)&(addr)->sin6.sin6_addr), buf, sizeof buf) != NULL) \
56 : snprintf(buf, sizeof buf, "Address type %d", (addr)->sa.sa_family))
57
58 struct message {
59 int ref_count;
60 #ifndef IOLOOP_MACOS
61 addr_t src;
62 addr_t local;
63 #endif
64 int ifindex;
65 uint16_t length;
66 dns_wire_t wire;
67 };
68
69
70 typedef struct dso_transport comm_t;
71 typedef struct io io_t;
72 typedef struct subproc subproc_t;
73 typedef struct wakeup wakeup_t;
74 typedef struct dnssd_txn dnssd_txn_t;
75
76 typedef void (*dnssd_txn_finalize_callback_t)(void *NONNULL context);
77 typedef void (*wakeup_callback_t)(void *NONNULL context);
78 typedef void (*finalize_callback_t)(void *NONNULL context);
79 typedef void (*cancel_callback_t)(void *NONNULL context);
80 typedef void (*ready_callback_t)(void *NONNULL context, uint16_t port);
81 typedef void (*io_callback_t)(io_t *NONNULL io, void *NONNULL context);
82 typedef void (*comm_callback_t)(comm_t *NONNULL comm);
83 typedef void (*datagram_callback_t)(comm_t *NONNULL comm, message_t *NONNULL message, void *NULLABLE context);
84 typedef void (*connect_callback_t)(comm_t *NONNULL connection, void *NULLABLE context);
85 typedef void (*disconnect_callback_t)(comm_t *NONNULL comm, int error);
86 enum interface_address_change { interface_address_added, interface_address_deleted, interface_address_unchanged };
87 typedef void (*interface_callback_t)(void *NULLABLE context, const char *NONNULL name,
88 const addr_t *NONNULL address, const addr_t *NONNULL netmask,
89 uint32_t flags, enum interface_address_change event_type);
90 typedef void (*subproc_callback_t)(void *NULLABLE context, int status, const char *NULLABLE error);
91 #ifdef IOLOOP_MACOS
92 typedef bool (*ioloop_xpc_callback_t)(xpc_connection_t NULLABLE conn, xpc_object_t NULLABLE request);
93 #endif
94
95 typedef struct tls_context tls_context_t;
96
97 #define IOLOOP_SECOND 1000LL
98 #define IOLOOP_MINUTE 60 * IOLOOP_SECOND
99 #define IOLOOP_HOUR 60 * IOLOOP_MINUTE
100 #define IOLOOP_DAY 24 * IOLOOP_HOUR
101
102 struct io {
103 int ref_count;
104 io_t *NULLABLE next;
105 io_callback_t NULLABLE read_callback;
106 io_callback_t NULLABLE write_callback;
107 finalize_callback_t NULLABLE finalize;
108 void *NULLABLE context;
109 io_t *NULLABLE cancel_on_close;
110 #ifdef IOLOOP_MACOS
111 dispatch_source_t NULLABLE read_source;
112 dispatch_source_t NULLABLE write_source;
113 #else
114 bool want_read : 1;
115 bool want_write : 1;
116 #endif
117 int fd;
118 };
119
120 struct wakeup {
121 int ref_count;
122 wakeup_t *NULLABLE next;
123 void *NULLABLE context;
124 wakeup_callback_t NULLABLE wakeup;
125 finalize_callback_t NULLABLE finalize;
126 #ifdef IOLOOP_MACOS
127 dispatch_source_t NULLABLE dispatch_source;
128 #else
129 int64_t wakeup_time;
130 #endif
131 };
132
133 struct dso_transport {
134 int ref_count;
135 #ifdef IOLOOP_MACOS
136 nw_connection_t NULLABLE connection;
137 nw_listener_t NULLABLE listener;
138 nw_parameters_t NULLABLE parameters;
139 int writes_pending;
140 bool read_pending; // Only ever one.
141 bool server; // Indicates that this connection was created by a listener
142 bool connection_ready;
143 wakeup_t *NULLABLE idle_timer;
144 // nw_connection objects aren't necessarily ready to write to immediately. But when we create an outgoing connection, we
145 // typically want to write to it immediately. So we have a one-datum queue in case this happens; if the connection takes
146 // so long to get ready that another write happens, we drop the first write. This will work okay for UDP connections, where
147 // the retransmit logic is in the application. For future, we may want to rearchitect the flow so that the write is always
148 // done in a callback.
149 dispatch_data_t NULLABLE pending_write;
150 #else
151 io_t io;
152 #endif
153 uint16_t listen_port;
154 uint16_t *NULLABLE avoid_ports;
155 int num_avoid_ports;
156 bool avoiding;
157 char *NONNULL name;
158 void *NULLABLE context;
159 datagram_callback_t NULLABLE datagram_callback;
160 comm_callback_t NULLABLE close_callback;
161 connect_callback_t NULLABLE connected;
162 disconnect_callback_t NULLABLE disconnected;
163 finalize_callback_t NULLABLE finalize;
164 cancel_callback_t NULLABLE cancel;
165 ready_callback_t NULLABLE ready;
166 message_t *NULLABLE message;
167 uint8_t *NULLABLE buf;
168 dso_state_t *NULLABLE dso;
169 tls_context_t *NULLABLE tls_context;
170 addr_t address, multicast;
171 size_t message_length_len;
172 size_t message_length, message_cur;
173 uint8_t message_length_bytes[2];
174 bool tcp_stream: 1;
175 bool is_multicast: 1;
176 };
177
178 #define MAX_SUBPROC_ARGS 20
179 struct subproc {
180 int ref_count;
181 #ifdef IOLOOP_MACOS
182 dispatch_source_t NULLABLE dispatch_source;
183 #else
184 subproc_t *NULLABLE next;
185 #endif
186 int pipe_fds[2];
187 io_t *NULLABLE output_fd;
188 void *NULLABLE context;
189 subproc_callback_t NONNULL callback;
190 finalize_callback_t NULLABLE finalize;
191 char *NULLABLE argv[MAX_SUBPROC_ARGS + 1];
192 int argc;
193 pid_t pid;
194 };
195
196 struct dnssd_txn {
197 int ref_count;
198 DNSServiceRef NULLABLE sdref;
199 void *NULLABLE context;
200 void *NULLABLE aux_pointer;
201 dnssd_txn_finalize_callback_t NULLABLE finalize_callback;
202 };
203
204 extern int64_t ioloop_now;
205 int getipaddr(addr_t *NONNULL addr, const char *NONNULL p);
206 int64_t ioloop_timenow(void);
207 message_t *NULLABLE message_allocate(size_t message_size);
208 void message_free(message_t *NONNULL message);
209 void ioloop_close(io_t *NONNULL io);
210 void ioloop_add_reader(io_t *NONNULL io, io_callback_t NONNULL callback);
211 wakeup_t *NULLABLE ioloop_wakeup_create(void);
212 #define ioloop_wakeup_retain(wakeup) ioloop_wakeup_retain_(wakeup, __FILE__, __LINE__)
213 void ioloop_wakeup_retain_(wakeup_t *NONNULL wakeup, const char *NONNULL file, int line);
214 #define ioloop_wakeup_release(wakeup) ioloop_wakeup_release_(wakeup, __FILE__, __LINE__)
215 void ioloop_wakeup_release_(wakeup_t *NONNULL wakeup, const char *NONNULL file, int line);
216 bool ioloop_add_wake_event(wakeup_t *NONNULL wakeup, void *NULLABLE context,
217 wakeup_callback_t NONNULL callback, finalize_callback_t NULLABLE finalize,
218 int milliseconds);
219 void ioloop_cancel_wake_event(wakeup_t *NONNULL wakeup);
220
221 bool ioloop_init(void);
222 int ioloop(void);
223
224 #define ioloop_comm_retain(comm) ioloop_comm_retain_(comm, __FILE__, __LINE__)
225 void ioloop_comm_retain_(comm_t *NONNULL comm, const char *NONNULL file, int line);
226 #define ioloop_comm_release(wakeup) ioloop_comm_release_(wakeup, __FILE__, __LINE__)
227 void ioloop_comm_release_(comm_t *NONNULL comm, const char *NONNULL file, int line);
228 void ioloop_comm_cancel(comm_t *NONNULL comm);
229 #define ioloop_listener_retain(comm) ioloop_listener_retain_(comm, __FILE__, __LINE__)
230 void ioloop_listener_retain_(comm_t *NONNULL listener, const char *NONNULL file, int line);
231 #define ioloop_listener_release(wakeup) ioloop_listener_release_(wakeup, __FILE__, __LINE__)
232 void ioloop_listener_release_(comm_t *NONNULL listener, const char *NONNULL file, int line);
233 void ioloop_listener_cancel(comm_t *NONNULL comm);
234 comm_t *NULLABLE ioloop_listener_create(bool stream, bool tls, uint16_t *NULLABLE avoid_ports, int num_avoid_ports,
235 const addr_t *NULLABLE ip_address, const char *NULLABLE multicast,
236 const char *NONNULL name, datagram_callback_t NONNULL datagram_callback,
237 connect_callback_t NULLABLE connected, cancel_callback_t NULLABLE cancel,
238 ready_callback_t NULLABLE ready, finalize_callback_t NULLABLE finalize,
239 void *NULLABLE context);
240 comm_t *NULLABLE ioloop_connection_create(addr_t *NONNULL remote_address, bool tls, bool stream,
241 datagram_callback_t NONNULL datagram_callback,
242 connect_callback_t NULLABLE connected,
243 disconnect_callback_t NULLABLE disconnected,
244 finalize_callback_t NULLABLE finalize,
245 void *NONNULL context);
246 #define ioloop_message_retain(wakeup) ioloop_message_retain_(wakeup, __FILE__, __LINE__)
247 void ioloop_message_retain_(message_t *NONNULL message, const char *NONNULL file, int line);
248 #define ioloop_message_release(wakeup) ioloop_message_release_(wakeup, __FILE__, __LINE__)
249 void ioloop_message_release_(message_t *NONNULL message, const char *NONNULL file, int line);
250 bool ioloop_send_message(comm_t *NONNULL connection, message_t *NULLABLE responding_to,
251 struct iovec *NONNULL iov, int iov_len);
252 bool ioloop_map_interface_addresses(void *NULLABLE context, interface_callback_t NONNULL callback);
253 ssize_t ioloop_recvmsg(int sock, uint8_t *NONNULL buffer, size_t buffer_length, int *NONNULL ifindex,
254 int *NONNULL hoplimit, addr_t *NONNULL source, addr_t *NONNULL destination);
255 #define ioloop_subproc_release(subproc) ioloop_subproc_release_(subproc, __FILE__, __LINE__)
256 void ioloop_subproc_release_(subproc_t *NONNULL subproc, const char *NONNULL file, int line);
257 #define ioloop_subproc_retain(subproc) ioloop_subproc_retain_(subproc, __FILE__, __LINE__)
258 void ioloop_subproc_retain_(subproc_t *NONNULL subproc, const char *NONNULL file, int line);
259 subproc_t *NULLABLE ioloop_subproc(const char *NONNULL exepath, char *NULLABLE *NONNULL argv, int argc,
260 subproc_callback_t NULLABLE callback, io_callback_t NULLABLE output_callback,
261 void *NULLABLE context);
262 #define ioloop_dnssd_txn_add(ref, context, finalize) ioloop_dnssd_txn_add_(ref, context, finalize, __FILE__, __LINE__)
263 dnssd_txn_t *NULLABLE
264 ioloop_dnssd_txn_add_(DNSServiceRef NONNULL ref, void *NULLABLE context,
265 dnssd_txn_finalize_callback_t NULLABLE callback, const char *NONNULL file, int line);
266 void ioloop_dnssd_txn_cancel(dnssd_txn_t *NONNULL txn);
267 #define ioloop_dnssd_txn_retain(txn) ioloop_dnssd_txn_retain_(txn, __FILE__, __LINE__)
268 void ioloop_dnssd_txn_retain_(dnssd_txn_t *NONNULL txn, const char *NONNULL file, int line);
269 #define ioloop_dnssd_txn_release(txn) ioloop_dnssd_txn_release_(txn, __FILE__, __LINE__)
270 void ioloop_dnssd_txn_release_(dnssd_txn_t *NONNULL txn, const char *NONNULL file, int line);
271 #endif
272 void ioloop_dnssd_txn_set_aux_pointer(dnssd_txn_t *NONNULL txn, void *NULLABLE aux_pointer);
273 void *NULLABLE ioloop_dnssd_txn_get_aux_pointer(dnssd_txn_t *NONNULL txn);
274 void *NULLABLE ioloop_dnssd_txn_get_context(dnssd_txn_t *NONNULL txn);
275
276 #define ioloop_file_descriptor_create(fd, context, finalize) \
277 ioloop_file_descriptor_create_(fd, context, finalize, __FILE__, __LINE__)
278 io_t *NULLABLE ioloop_file_descriptor_create_(int fd, void *NULLABLE context, finalize_callback_t NULLABLE finalize,
279 const char *NONNULL file, int line);
280 #define ioloop_file_descriptor_retain(file_descriptor) ioloop_file_descriptor_retain_(file_descriptor, __FILE__, \
281 __LINE__)
282 void ioloop_file_descriptor_retain_(io_t *NONNULL file_descriptor, const char *NONNULL file, int line);
283 #define ioloop_file_descriptor_release(file_descriptor) ioloop_file_descriptor_release_(file_descriptor, __FILE__, \
284 __LINE__)
285 void ioloop_file_descriptor_release_(io_t *NONNULL file_descriptor, const char *NONNULL file, int line);
286
287 bool ioloop_interface_monitor_start(void);
288
289 #ifdef IOLOOP_MACOS
290 xpc_connection_t NULLABLE ioloop_create_xpc_service(const char *NONNULL name, ioloop_xpc_callback_t NONNULL callback);
291 #endif
292
293 // Local Variables:
294 // mode: C
295 // tab-width: 4
296 // c-file-style: "bsd"
297 // c-basic-offset: 4
298 // fill-column: 108
299 // indent-tabs-mode: nil
300 // End: