3 * Copyright (c) 2018-2019 Apple Computer, Inc. All rights reserved.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * Definitions for simple dispatch implementation.
24 #include <nw/private.h>
25 #include <Network/Network.h>
27 #include <xpc/private.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <net/if_dl.h>
35 typedef struct dso_state dso_state_t
;
38 typedef union addr addr_t
;
41 struct sockaddr_in sin
;
42 struct sockaddr_in6 sin6
;
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))
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
;
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
);
92 typedef bool (*ioloop_xpc_callback_t
)(xpc_connection_t NULLABLE conn
, xpc_object_t NULLABLE request
);
95 typedef struct tls_context tls_context_t
;
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
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
;
111 dispatch_source_t NULLABLE read_source
;
112 dispatch_source_t NULLABLE write_source
;
122 wakeup_t
*NULLABLE next
;
123 void *NULLABLE context
;
124 wakeup_callback_t NULLABLE wakeup
;
125 finalize_callback_t NULLABLE finalize
;
127 dispatch_source_t NULLABLE dispatch_source
;
133 struct dso_transport
{
136 nw_connection_t NULLABLE connection
;
137 nw_listener_t NULLABLE listener
;
138 nw_parameters_t NULLABLE parameters
;
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
;
153 uint16_t listen_port
;
154 uint16_t *NULLABLE avoid_ports
;
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];
175 bool is_multicast
: 1;
178 #define MAX_SUBPROC_ARGS 20
182 dispatch_source_t NULLABLE dispatch_source
;
184 subproc_t
*NULLABLE next
;
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];
198 DNSServiceRef NULLABLE sdref
;
199 void *NULLABLE context
;
200 void *NULLABLE aux_pointer
;
201 dnssd_txn_finalize_callback_t NULLABLE finalize_callback
;
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
,
219 void ioloop_cancel_wake_event(wakeup_t
*NONNULL wakeup
);
221 bool ioloop_init(void);
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
);
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
);
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__, \
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__, \
285 void ioloop_file_descriptor_release_(io_t
*NONNULL file_descriptor
, const char *NONNULL file
, int line
);
287 bool ioloop_interface_monitor_start(void);
290 xpc_connection_t NULLABLE
ioloop_create_xpc_service(const char *NONNULL name
, ioloop_xpc_callback_t NONNULL callback
);
296 // c-file-style: "bsd"
299 // indent-tabs-mode: nil