Home | History | Annotate | Line # | Download | only in DSO
      1  1.1  christos /* dso-transport.h
      2  1.1  christos  *
      3  1.1  christos  * Copyright (c) 2018-2021 Apple Inc. All rights reserved.
      4  1.1  christos  *
      5  1.1  christos  * Licensed under the Apache License, Version 2.0 (the "License");
      6  1.1  christos  * you may not use this file except in compliance with the License.
      7  1.1  christos  * You may obtain a copy of the License at
      8  1.1  christos  *
      9  1.1  christos  *     https://www.apache.org/licenses/LICENSE-2.0
     10  1.1  christos  *
     11  1.1  christos  * Unless required by applicable law or agreed to in writing, software
     12  1.1  christos  * distributed under the License is distributed on an "AS IS" BASIS,
     13  1.1  christos  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  1.1  christos  * See the License for the specific language governing permissions and
     15  1.1  christos  * limitations under the License.
     16  1.1  christos  *
     17  1.1  christos  */
     18  1.1  christos 
     19  1.1  christos #ifndef __DSO_TRANSPORT_H
     20  1.1  christos #define __DSO_TRANSPORT_H
     21  1.1  christos 
     22  1.1  christos #include "mdns_addr_tailq.h"   // For mdns_addr_tailq_t.
     23  1.1  christos 
     24  1.1  christos #ifdef DSO_USES_NETWORK_FRAMEWORK
     25  1.1  christos #include <Network/Network.h>
     26  1.1  christos #endif
     27  1.1  christos 
     28  1.1  christos // Maximum number of IP addresses that we'll deal with as a result of looking up a name
     29  1.1  christos // to which to connect.
     30  1.1  christos #define MAX_DSO_CONNECT_ADDRS 16
     31  1.1  christos 
     32  1.1  christos // Threshold above which we indicate that a DSO connection isn't writable.   This is advisory,
     33  1.1  christos // but e.g. for a Discovery Relay, if the remote proxy isn't consuming what we are sending, we
     34  1.1  christos // should start dropping packets on the floor rather than just queueing more and more packets.
     35  1.1  christos // 60k may actually be too much.   This is used when we're using NW Framework, because it doesn't
     36  1.1  christos // allow us to use TCP_NOTSENT_LOWAT directly.
     37  1.1  christos #define MAX_UNSENT_BYTES 60000
     38  1.1  christos 
     39  1.1  christos // Use 0 to represent an invalid ID for the object dso_connect_state_t and dso_transport_t.
     40  1.1  christos #define DSO_CONNECT_STATE_INVALID_SERIAL 0
     41  1.1  christos #define DSO_TRANSPORT_INVALID_SERIAL 0
     42  1.1  christos 
     43  1.1  christos struct dso_transport {
     44  1.1  christos     dso_state_t *dso;              // DSO state for which this is the transport
     45  1.1  christos     struct dso_transport *next;    // Transport is on list of transports.
     46  1.1  christos     void *event_context;           // I/O event context
     47  1.1  christos     mDNSAddr remote_addr;          // The IP address to which we have connected
     48  1.1  christos     int remote_port;               // The port to which we have connected
     49  1.1  christos 
     50  1.1  christos     uint32_t serial;               // Serial number for locating possibly freed dso_transport_t structs.
     51  1.1  christos #ifdef DSO_USES_NETWORK_FRAMEWORK
     52  1.1  christos     nw_connection_t connection;
     53  1.1  christos     dispatch_data_t to_write;
     54  1.1  christos     size_t bytes_to_write;
     55  1.1  christos     size_t unsent_bytes;
     56  1.1  christos     bool write_failed;             // This is set if any of the parts of the dso_write process fail
     57  1.1  christos #else
     58  1.1  christos     TCPSocket *connection;         // Socket connected to Discovery Proxy
     59  1.1  christos     size_t bytes_needed;
     60  1.1  christos     size_t message_length;         // Length of message we are currently accumulating, if known
     61  1.1  christos     uint8_t *inbuf;                // Buffer for incoming messages.
     62  1.1  christos     size_t inbuf_size;
     63  1.1  christos     uint8_t *inbufp;               // Current read pointer (may not be in inbuf)
     64  1.1  christos     bool need_length;              // True if we need a 2-byte length
     65  1.1  christos 
     66  1.1  christos     uint8_t lenbuf[2];             // Buffer for storing the length in a DNS TCP message
     67  1.1  christos 
     68  1.1  christos #define MAX_WRITE_HUNKS 4          // When writing a DSO message, we need this many separate hunks.
     69  1.1  christos     const uint8_t *to_write[MAX_WRITE_HUNKS];
     70  1.1  christos     ssize_t write_lengths[MAX_WRITE_HUNKS];
     71  1.1  christos     int num_to_write;
     72  1.1  christos #endif // DSO_USES_NETWORK_FRAMEWORK
     73  1.1  christos 
     74  1.1  christos     uint8_t *outbuf;               // Output buffer for building and sending DSO messages
     75  1.1  christos     size_t outbuf_size;
     76  1.1  christos };
     77  1.1  christos 
     78  1.1  christos typedef struct dso_lookup dso_lookup_t;
     79  1.1  christos struct dso_lookup {
     80  1.1  christos     dso_lookup_t *next;
     81  1.1  christos     DNSServiceRef sdref;
     82  1.1  christos };
     83  1.1  christos 
     84  1.1  christos typedef struct dso_connect_state dso_connect_state_t;
     85  1.1  christos 
     86  1.1  christos typedef enum {
     87  1.1  christos     // When the object is created and holds a reference to the context, the callback(see below) is called with
     88  1.1  christos     // dso_connect_life_cycle_create.
     89  1.1  christos     dso_connect_life_cycle_create,
     90  1.1  christos     // When the object is canceled, the callback(see below) is called with dso_connect_life_cycle_cancel to provide a
     91  1.1  christos     // chance for the context to do the corresponding cleaning work(cancel or release/free).
     92  1.1  christos     dso_connect_life_cycle_cancel,
     93  1.1  christos     // When the object is freed, the callback(see below) is called with dso_connect_life_cycle_free to provide a chance
     94  1.1  christos     // for the context to clean anything remains allocated.
     95  1.1  christos     dso_connect_life_cycle_free
     96  1.1  christos } dso_connect_life_cycle_t;
     97  1.1  christos 
     98  1.1  christos typedef bool (*dso_connect_life_cycle_context_callback_t)(const dso_connect_life_cycle_t life_cycle,
     99  1.1  christos      void *const context, dso_connect_state_t *const dso_connect);
    100  1.1  christos 
    101  1.1  christos typedef struct dso_transport_address dso_transport_address_t;
    102  1.1  christos struct dso_transport_address {
    103  1.1  christos     dso_transport_address_t *next;
    104  1.1  christos     mDNSAddr address;
    105  1.1  christos     mDNSIPPort port;
    106  1.1  christos };
    107  1.1  christos 
    108  1.1  christos struct dso_connect_state {
    109  1.1  christos     dso_connect_state_t *next;
    110  1.1  christos     dso_event_callback_t callback;
    111  1.1  christos     dso_state_t *dso;
    112  1.1  christos     char *detail;
    113  1.1  christos     void *context;
    114  1.1  christos 
    115  1.1  christos     // The callback gets called when dso_state_t is created, canceled or finalized to do some status maintaining
    116  1.1  christos     // operation for the context. This is passed into dso_state_create(), when dso_connect_state_t uses the context to
    117  1.1  christos     // create a new dso_state_t in dso_connection_succeeded().
    118  1.1  christos     dso_life_cycle_context_callback_t dso_context_callback;
    119  1.1  christos     // The callback gets called when dso_connect_t is created, canceled or finalized to do some status maintaining
    120  1.1  christos     // operation for the context.
    121  1.1  christos     dso_connect_life_cycle_context_callback_t dso_connect_context_callback;
    122  1.1  christos     TCPListener *listener;
    123  1.1  christos 
    124  1.1  christos     uint32_t serial; // Serial number that identifies a specific dso_connect_state_t.
    125  1.1  christos     char *hostname;
    126  1.1  christos 
    127  1.1  christos     // A list of addresses that we've discovered, and the next address to try.
    128  1.1  christos     dso_transport_address_t *addrs, *next_addr;
    129  1.1  christos     DNSServiceRef lookup;
    130  1.1  christos     mDNSBool canceled; // Indicates if the dso_connect_state_t has been canceled and should be ignored for processing.
    131  1.1  christos 
    132  1.1  christos     mDNSBool connecting;
    133  1.1  christos 
    134  1.1  christos #if MDNSRESPONDER_SUPPORTS(APPLE, TERMINUS_ASSISTED_UNICAST_DISCOVERY)
    135  1.1  christos     // A boolean value to indicate whether the dso session should use the preconfigured TLS server certificates to
    136  1.1  christos     // perform the trust evaluation.
    137  1.1  christos     mDNSBool trusts_alternative_server_certificates;
    138  1.1  christos #endif
    139  1.1  christos 
    140  1.1  christos     mDNSIPPort config_port, connect_port;
    141  1.1  christos     dso_transport_t *transport;
    142  1.1  christos #ifdef DSO_USES_NETWORK_FRAMEWORK
    143  1.1  christos     nw_connection_t connection;
    144  1.1  christos     bool tls_enabled;
    145  1.1  christos #else
    146  1.1  christos     size_t inbuf_size;
    147  1.1  christos #endif
    148  1.1  christos     size_t outbuf_size;
    149  1.1  christos     int max_outstanding_queries;
    150  1.1  christos     mDNSs32 last_event;
    151  1.1  christos     mDNSs32 reconnect_time;
    152  1.1  christos     mDNSu32 if_idx; // The index of the interface where the DSO session is established through.
    153  1.1  christos };
    154  1.1  christos 
    155  1.1  christos typedef struct {
    156  1.1  christos 	TCPListener *listener;
    157  1.1  christos     dso_event_callback_t callback;
    158  1.1  christos 	void *context;
    159  1.1  christos } dso_listen_context_t;
    160  1.1  christos 
    161  1.1  christos typedef struct {
    162  1.1  christos     const uint8_t *message;
    163  1.1  christos     size_t length;
    164  1.1  christos } dso_message_payload_t;
    165  1.1  christos 
    166  1.1  christos void dso_transport_init(void);
    167  1.1  christos mStatus dso_set_connection(dso_state_t *dso, TCPSocket *socket);
    168  1.1  christos void dso_schedule_reconnect(mDNS *m, dso_connect_state_t *cs, mDNSs32 when);
    169  1.1  christos void dso_set_callback(dso_state_t *dso, void *context, dso_event_callback_t cb);
    170  1.1  christos mStatus dso_message_write(dso_state_t *dso, dso_message_t *msg, bool disregard_low_water);
    171  1.1  christos dso_connect_state_t *dso_connect_state_create(
    172  1.1  christos     const char *hostname, mDNSAddr *addr, mDNSIPPort port,
    173  1.1  christos     int max_outstanding_queries, size_t inbuf_size, size_t outbuf_size,
    174  1.1  christos     dso_event_callback_t callback,
    175  1.1  christos     dso_state_t *dso, void *context,
    176  1.1  christos     const dso_life_cycle_context_callback_t dso_context_callback,
    177  1.1  christos     const dso_connect_life_cycle_context_callback_t dso_connect_context_callback,
    178  1.1  christos     const char *detail);
    179  1.1  christos #ifdef DSO_USES_NETWORK_FRAMEWORK
    180  1.1  christos void dso_connect_state_use_tls(dso_connect_state_t *cs);
    181  1.1  christos #endif
    182  1.1  christos void dso_connect_state_cancel(dso_connect_state_t *const cs);
    183  1.1  christos bool dso_connect(dso_connect_state_t *connect_state);
    184  1.1  christos void dso_reconnect(dso_connect_state_t *cs, dso_state_t *dso);
    185  1.1  christos mStatus dso_listen(dso_connect_state_t *listen_context);
    186  1.1  christos bool dso_write_start(dso_transport_t *transport, size_t length);
    187  1.1  christos bool dso_write_finish(dso_transport_t *transport);
    188  1.1  christos void dso_write(dso_transport_t *transport, const uint8_t *buf, size_t length);
    189  1.1  christos #endif // __DSO_TRANSPORT_H
    190  1.1  christos 
    191  1.1  christos // Local Variables:
    192  1.1  christos // mode: C
    193  1.1  christos // tab-width: 4
    194  1.1  christos // c-file-style: "bsd"
    195  1.1  christos // c-basic-offset: 4
    196  1.1  christos // fill-column: 108
    197  1.1  christos // indent-tabs-mode: nil
    198  1.1  christos // End:
    199