Home | History | Annotate | Line # | Download | only in ServiceRegistration
      1 /* service-publisher.c
      2  *
      3  * Copyright (c) 2023-2024 Apple 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  *     https://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  * This file contains code to queue and send updates for Thread services.
     18  */
     19 
     20 #ifndef LINUX
     21 #include <netinet/in.h>
     22 #include <net/if.h>
     23 #include <netinet6/in6_var.h>
     24 #include <netinet6/nd6.h>
     25 #include <net/if_media.h>
     26 #include <sys/stat.h>
     27 #else
     28 #define _GNU_SOURCE
     29 #include <netinet/in.h>
     30 #include <fcntl.h>
     31 #include <bsd/stdlib.h>
     32 #include <net/if.h>
     33 #endif
     34 #include <sys/socket.h>
     35 #include <sys/ioctl.h>
     36 #include <net/route.h>
     37 #include <netinet/icmp6.h>
     38 #include <stdio.h>
     39 #include <unistd.h>
     40 #include <errno.h>
     41 #include <stdlib.h>
     42 #include <string.h>
     43 #include <ctype.h>
     44 #include <arpa/inet.h>
     45 #include <stdlib.h>
     46 #include <stddef.h>
     47 #include <dns_sd.h>
     48 #include <inttypes.h>
     49 #include <signal.h>
     50 
     51 #ifdef IOLOOP_MACOS
     52 #include <xpc/xpc.h>
     53 
     54 #include <TargetConditionals.h>
     55 #include <SystemConfiguration/SystemConfiguration.h>
     56 #include <SystemConfiguration/SCPrivate.h>
     57 #include <SystemConfiguration/SCNetworkConfigurationPrivate.h>
     58 #include <SystemConfiguration/SCNetworkSignature.h>
     59 #include <network_information.h>
     60 
     61 #include <CoreUtils/CoreUtils.h>
     62 #endif // IOLOOP_MACOS
     63 
     64 #include "srp.h"
     65 #include "dns-msg.h"
     66 #include "ioloop.h"
     67 #include "srp-crypto.h"
     68 
     69 #include "cti-services.h"
     70 #include "srp-gw.h"
     71 #include "srp-proxy.h"
     72 #include "srp-mdns-proxy.h"
     73 #include "adv-ctl-server.h"
     74 #include "dnssd-proxy.h"
     75 #include "srp-proxy.h"
     76 #include "route.h"
     77 #include "ifpermit.h"
     78 #include "srp-dnssd.h"
     79 
     80 #define STATE_MACHINE_IMPLEMENTATION 1
     81 typedef enum {
     82     service_publisher_state_invalid,
     83     service_publisher_state_startup,
     84     service_publisher_state_waiting_to_publish,
     85     service_publisher_state_not_publishing,
     86     service_publisher_state_start_listeners,
     87     service_publisher_state_publishing,
     88 } state_machine_state_t;
     89 #define state_machine_state_invalid service_publisher_state_invalid
     90 
     91 #include "state-machine.h"
     92 #include "thread-service.h"
     93 #include "service-tracker.h"
     94 
     95 #include "service-publisher.h"
     96 #include "thread-tracker.h"
     97 #include "node-type-tracker.h"
     98 
     99 // This is pretty short because our normal use case is connecting to a single device, so we don't actually anticipate
    100 // normally seeing a service. But if we do, we don't suffer power events, so we don't need to desynchronize from other
    101 // devices booting at the same time. So we just want to wait long enough that if there's already a service published,
    102 // we see it and don't publish.
    103 #define SERVICE_PUBLISHER_START_WAIT 750
    104 
    105 // When a competing service is lost, we want to wait a bit longer.
    106 #define SERVICE_PUBLISHER_LOST_WAIT 5000
    107 
    108 // When the listener restarts, we don't actually want to wait.
    109 #define SERVICE_PUBLISHER_LISTENER_RESTART_WAIT 1
    110 
    111 #define ADDRESS_RECORD_TTL  4500
    112 #define OTHER_RECORD_TTL    4500
    113 
    114 struct service_publisher {
    115     int ref_count;
    116     state_machine_header_t state_header;
    117     char *id;
    118     char *thread_interface_name;
    119     srp_server_t *server_state;
    120     wakeup_t *NULLABLE wakeup_timer;
    121     wakeup_t *NULLABLE sed_timeout;
    122     comm_t *srp_listener;
    123     void (*reconnect_callback)(void *context);
    124     thread_service_t *published_unicast_service;
    125     thread_service_t *published_anycast_service;
    126     thread_service_t *publication_queue;
    127     cti_connection_t active_data_set_connection;
    128     cti_connection_t wed_tracker_connection;
    129     cti_connection_t neighbor_tracker_connection;
    130     struct in6_addr thread_mesh_local_address;
    131     struct in6_addr wed_ml_eid;
    132     struct in6_addr neighbor_ml_eid;
    133     char *NULLABLE wed_ext_address_string;
    134     char *NULLABLE wed_ml_eid_string;
    135     char *NULLABLE neighbor_ml_eid_string;
    136     int startup_delay_range;
    137     int retry_interval; // Retry interval in seconds for re-publishing service(s)
    138     uint16_t srp_listener_port;
    139     bool have_ml_eid;
    140     bool first_time;
    141     bool force_publication;
    142     bool canceled;
    143     bool have_srp_listener;
    144     bool seen_service_list;
    145     bool stopped;
    146     bool have_thread_interface_name;
    147     bool have_unicast_in_net_data, have_anycast_in_net_data;
    148     bool cached_services_published, started_stale_service_timeout;
    149 };
    150 
    151 static uint64_t service_publisher_serial_number;
    152 
    153 static void service_publisher_queue_run(service_publisher_t *publisher);
    154 
    155 void
    156 service_publisher_unadvertise_all(service_publisher_t *publisher)
    157 {
    158     srp_server_t *server_state = publisher->server_state;
    159 
    160     publisher->cached_services_published = false;
    161     for (adv_host_t *host = server_state->hosts; host; host = host->next) {
    162         // If we have an outstanding update, finish it.
    163         if (host->update != NULL) {
    164             srp_mdns_update_finished(host->update);
    165         }
    166         if (host->addresses != NULL) {
    167             for (int i = 0; i < host->addresses->num; i++) {
    168                 adv_record_t *record = host->addresses->vec[i];
    169                 if (record != NULL) {
    170                     if (record->rrtype == dns_rrtype_aaaa && record->rdlen == 16) {
    171                         SEGMENTED_IPv6_ADDR_GEN_SRP(record->rdata, rdata_buf);
    172                         INFO("unadvertising " PRI_S_SRP " IN AAAA " PRI_SEGMENTED_IPv6_ADDR_SRP " rec %p rref %p",
    173                              host->name, SEGMENTED_IPv6_ADDR_PARAM_SRP(record->rdata, rdata_buf),
    174                             record, record->rref);
    175                     }
    176                     srp_mdns_shared_record_remove(server_state, record);
    177                     // DNSServiceRemoveRecord should clear the cache, but it doesn't.
    178                     DNSServiceReconfirmRecord(0, server_state->advertise_interface, host->name, record->rrtype,
    179                                               dns_qclass_in, record->rdlen, record->rdata);
    180                 }
    181             }
    182         }
    183         if (host->key_record != NULL) {
    184             srp_mdns_shared_record_remove(server_state, host->key_record);
    185         }
    186         if (host->instances != NULL) {
    187             for (int i = 0; i < host->instances->num; i++) {
    188                 adv_instance_t *instance = host->instances->vec[i];
    189                 if (instance != NULL && instance->txn != NULL) {
    190                     INFO("unadvertising " PRI_S_SRP "." PRI_S_SRP " instance %p sdref %p",
    191                          instance->instance_name, instance->service_type, instance, instance->txn->sdref);
    192                     ioloop_dnssd_txn_cancel(instance->txn);
    193                     ioloop_dnssd_txn_release(instance->txn);
    194                     instance->txn = NULL;
    195                 }
    196             }
    197         }
    198     }
    199 }
    200 
    201 static void
    202 service_publisher_instance_callback(DNSServiceRef UNUSED sdref, DNSServiceFlags UNUSED flags, DNSServiceErrorType error_code,
    203                                     const char *name, const char *regtype, const char *domain, void *context)
    204 {
    205     adv_instance_t *instance = context;
    206     if (error_code != kDNSServiceErr_NoError) {
    207         INFO("DNSServiceRegister failed: " PUB_S_SRP "." PUB_S_SRP " host " PRI_S_SRP ": %d (instance %p sdref %p)",
    208              name, regtype, domain, error_code, instance, instance->txn == NULL ? 0 : instance->txn->sdref);
    209         ioloop_dnssd_txn_cancel(instance->txn);
    210         ioloop_dnssd_txn_release(instance->txn);
    211         instance->txn = NULL;
    212     } else {
    213         INFO("DNSServiceRegister succeeded: " PUB_S_SRP "." PUB_S_SRP " host " PRI_S_SRP " (instance %p sdref %p)",
    214              instance->instance_name, instance->service_type, instance->host->registered_name,
    215              instance, instance->txn == NULL ? 0 : instance->txn->sdref);
    216     }
    217 }
    218 
    219 static void
    220 service_publisher_re_advertise_instance(srp_server_t *server_state, adv_host_t *host, adv_instance_t *instance)
    221 {
    222     DNSServiceRef service_ref = server_state->shared_registration_txn->sdref;
    223 
    224     // Make sure we don't double-register.
    225     if (instance->txn != NULL) {
    226         if (instance->txn->sdref != NULL) {
    227             if (instance->shared_txn == (intptr_t)server_state->shared_registration_txn) {
    228                 INFO("instance is already registered: " PUB_S_SRP "." PUB_S_SRP " host " PRI_S_SRP
    229                      " (instance %p sdref %p)",
    230                      instance->instance_name, instance->service_type, host->registered_name,
    231                      instance, instance->txn->sdref);
    232                 return;
    233             }
    234             INFO("instance registration is stale: " PUB_S_SRP "." PUB_S_SRP " host " PRI_S_SRP
    235                  " (instance %p sdref %p)",
    236                  instance->instance_name, instance->service_type, host->registered_name,
    237                  instance, instance->txn->sdref);
    238             instance->txn->sdref = NULL;
    239         }
    240         ioloop_dnssd_txn_release(instance->txn);
    241         instance->txn = NULL;
    242     }
    243 
    244     // Get the TSR attribute for the host object.
    245     char time_buf[TSR_TIMESTAMP_STRING_LEN];
    246     DNSServiceAttributeRef tsr_attribute = srp_message_tsr_attribute_generate(NULL, host->key_id,
    247                                                                               time_buf, sizeof(time_buf));
    248 
    249     int err = dns_service_register_wa(server_state, &service_ref,
    250                                       (kDNSServiceFlagsShareConnection | kDNSServiceFlagsNoAutoRename |
    251                                        kDNSServiceFlagsKnownUnique), server_state->advertise_interface,
    252                                       instance->instance_name, instance->service_type, NULL,
    253                                       host->registered_name, htons(instance->port), instance->txt_length,
    254                                       instance->txt_data, tsr_attribute, service_publisher_instance_callback, instance);
    255 
    256     // This would happen if we pass NULL for regtype, which we don't, or if we run out of memory, or if
    257     // the server isn't running; in the second two cases, we can always try again later.
    258     if (err != kDNSServiceErr_NoError) {
    259         INFO("DNSServiceRegister failed: " PUB_S_SRP "." PUB_S_SRP " host " PRI_S_SRP ": %d (instance %p)",
    260              instance->instance_name, instance->service_type, host->registered_name, err, instance);
    261     } else {
    262         INFO("DNSServiceRegister succeeded: " PUB_S_SRP "." PUB_S_SRP " host " PRI_S_SRP " at " PUB_S_SRP
    263              " (instance %p sdref %p)",
    264              instance->instance_name, instance->service_type, host->registered_name, time_buf,
    265              instance, service_ref);
    266         instance->txn = ioloop_dnssd_txn_add_subordinate(service_ref, instance, adv_instance_context_release, NULL);
    267         if (instance->txn == NULL) {
    268             ERROR("no memory for instance transaction.");
    269             DNSServiceRefDeallocate(service_ref);
    270             return;
    271         }
    272         instance->shared_txn = (intptr_t)server_state->shared_registration_txn;
    273         adv_instance_retain(instance); // for the callback
    274     }
    275 }
    276 
    277 static void
    278 service_publisher_record_callback(DNSServiceRef UNUSED sdref, DNSRecordRef rref,
    279                                   DNSServiceFlags UNUSED flags, DNSServiceErrorType error_code, void *context)
    280 {
    281     adv_record_t *record = context;
    282     const char *host_name = record->host != NULL ? record->host->name : "<null>";
    283     if (error_code != kDNSServiceErr_NoError) {
    284         ERROR("re-registration for " PRI_S_SRP " (record %p rref %p) failed with code %d",
    285               host_name, record, rref, error_code);
    286         record->rref = NULL;
    287         record->shared_txn = 0;
    288         adv_record_release(record); // no more callbacks.
    289     } else {
    290         INFO("re-registration for " PRI_S_SRP " (record %p rref %p) succeeded.", host_name, record, rref);
    291         // could get more callbacks.
    292     }
    293 }
    294 
    295 static void
    296 service_publisher_re_advertise_record(srp_server_t *server_state, adv_host_t *host, adv_record_t *record)
    297 {
    298     const DNSServiceRef service_ref = host->server_state->shared_registration_txn->sdref;
    299 
    300     // Make sure we don't double register.
    301     if (record->rref != NULL) {
    302         if (record->shared_txn == (intptr_t)server_state->shared_registration_txn) {
    303             INFO("host is already registered: " PUB_S_SRP " (record %p rref %p)",
    304                  host->registered_name, record, record->rref);
    305             return;
    306         }
    307         INFO("host registration is stale: " PUB_S_SRP " (record %p rref %p)",
    308              host->registered_name, record, record->rref);
    309         srp_mdns_shared_record_remove(host->server_state, record);
    310     }
    311 
    312     // Get the TSR attribute for the host object.
    313     char time_buf[TSR_TIMESTAMP_STRING_LEN];
    314     DNSServiceAttributeRef tsr_attribute = srp_message_tsr_attribute_generate(NULL, host->key_id,
    315                                                                               time_buf, sizeof(time_buf));
    316 
    317     int err = dns_service_register_record_wa(server_state, service_ref, &record->rref, kDNSServiceFlagsKnownUnique,
    318                                              server_state->advertise_interface, host->registered_name,
    319                                              record->rrtype, dns_qclass_in, record->rdlen, record->rdata, ADDRESS_RECORD_TTL,
    320                                              tsr_attribute, service_publisher_record_callback, record);
    321     if (err != kDNSServiceErr_NoError) {
    322         INFO("DNSServiceRegisterRecord failed on host " PUB_S_SRP ": %d (record %p)", host->name, err, record);
    323     } else {
    324         INFO("DNSServiceRegisterRecord succeeded on host " PUB_S_SRP " at " PUB_S_SRP " (record %p rref %p)",
    325              host->name, time_buf, record, record->rref);
    326         record->shared_txn = (intptr_t)host->server_state->shared_registration_txn;
    327         adv_record_retain(record); // for the callback
    328     }
    329 }
    330 
    331 // Re-advertise records that match the address of the WED device we're bonded to if we're bonded to a WED device, or
    332 // that match the mesh-local prefix of our mesh-local address.  This is a best effort--if it fails, we log it, but it
    333 // just means that our cached info isn't discoverable and we have to wait for a new registration, which should come soon
    334 // or else the cached data wasn't valid.
    335 void
    336 service_publisher_re_advertise_matching(service_publisher_t *publisher)
    337 {
    338     if (publisher->state_header.state == service_publisher_state_invalid) {
    339         INFO("publisher is in an invalid state, so we shouldn't re-advertise anything.");
    340         return;
    341     }
    342 
    343     srp_server_t *server_state = publisher->server_state;
    344 
    345     // If we don't yet have a shared connection, create one.
    346     if (!srp_mdns_shared_registration_txn_setup(server_state)) {
    347         return;
    348     }
    349 
    350     for (adv_host_t *host = server_state->hosts; host; host = host->next) {
    351         bool matched = false;
    352 
    353         if (host->addresses != NULL) {
    354             for (int i = 0; i < host->addresses->num; i++) {
    355                 adv_record_t *record = host->addresses->vec[i];
    356                 // A match means that if we are in WED p2p mode, the ML-EID of the WED matches the record. If not, then
    357                 // it means that the record is on the mesh-local prefix. In both cases, the record has to be a valid
    358                 // AAAA record, of course.
    359                 if (record != NULL && record->rrtype == dns_rrtype_aaaa && record->rdlen == 16 &&
    360                     (publisher->wed_ml_eid_string != NULL
    361                      ? !in6addr_compare(&publisher->wed_ml_eid, (struct in6_addr *)record->rdata)
    362                      : !in6prefix_compare(&publisher->thread_mesh_local_address, (struct in6_addr *)record->rdata, 8)))
    363                 {
    364                     SEGMENTED_IPv6_ADDR_GEN_SRP(record->rdata, rdata_buf);
    365                     INFO("re-advertising " PRI_S_SRP " IN AAAA " PRI_SEGMENTED_IPv6_ADDR_SRP,
    366                          host->name, SEGMENTED_IPv6_ADDR_PARAM_SRP(record->rdata, rdata_buf));
    367                     service_publisher_re_advertise_record(server_state, host, record);
    368                     matched = true;
    369                 }
    370             }
    371         }
    372         if (matched) {
    373             if (host->key_record != NULL) {
    374                 service_publisher_re_advertise_record(server_state, host, host->key_record);
    375             }
    376             if (host->instances != NULL) {
    377                 for (int i = 0; i < host->instances->num; i++) {
    378                     adv_instance_t *instance = host->instances->vec[i];
    379                     if (instance != NULL && instance->txn == NULL) {
    380                         service_publisher_re_advertise_instance(server_state, host, instance);
    381                     }
    382                 }
    383             }
    384         }
    385     }
    386 
    387     publisher->cached_services_published = true;
    388 }
    389 
    390 bool
    391 service_publisher_is_address_mesh_local(service_publisher_t *publisher, addr_t *address)
    392 {
    393     if (address->sa.sa_family == AF_INET) {
    394         IPv4_ADDR_GEN_SRP(&address->sin.sin_addr, addr_buf);
    395         if (!IN_LOOPBACK(address->sin.sin_addr.s_addr)) {
    396             INFO(PRI_IPv4_ADDR_SRP "is not mesh-local", IPv4_ADDR_PARAM_SRP(&address->sin.sin_addr, addr_buf));
    397             return false;
    398         }
    399         INFO(PRI_IPv4_ADDR_SRP "is the IPv4 loopback address", IPv4_ADDR_PARAM_SRP(&address->sin.sin_addr, addr_buf));
    400         return true;
    401     }
    402     if (address->sa.sa_family != AF_INET6) {
    403         INFO("address family %d can't be mesh-local", address->sa.sa_family);
    404         return false;
    405     }
    406 
    407     uint8_t *addr_ptr = (uint8_t *)&address->sin6.sin6_addr;
    408     SEGMENTED_IPv6_ADDR_GEN_SRP(addr_ptr, addr_buf);
    409     if (IN6_IS_ADDR_LOOPBACK(&address->sin6.sin6_addr)) {
    410         INFO(PRI_SEGMENTED_IPv6_ADDR_SRP " is the IPv6 loopback address.",
    411              SEGMENTED_IPv6_ADDR_PARAM_SRP(addr_ptr, addr_buf));
    412         return true;
    413     }
    414     static const uint8_t ipv4mapped_loopback[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 127, 0, 0, 1 };
    415     if (!memcmp(&address->sin6.sin6_addr, ipv4mapped_loopback, sizeof(ipv4mapped_loopback))) {
    416         INFO(PRI_SEGMENTED_IPv6_ADDR_SRP " is the IPv4-mapped loopback address.",
    417              SEGMENTED_IPv6_ADDR_PARAM_SRP(addr_ptr, addr_buf));
    418         return true;
    419     }
    420 
    421     if (!publisher->have_ml_eid) {
    422         INFO(PRI_SEGMENTED_IPv6_ADDR_SRP "is not mesh-local",
    423              SEGMENTED_IPv6_ADDR_PARAM_SRP(addr_ptr, addr_buf));
    424         return false;
    425     }
    426 
    427     SEGMENTED_IPv6_ADDR_GEN_SRP(&publisher->thread_mesh_local_address, mle_buf);
    428     if (in6prefix_compare(&address->sin6.sin6_addr, &publisher->thread_mesh_local_address, 8)) {
    429         INFO(PRI_SEGMENTED_IPv6_ADDR_SRP
    430              " is not on the same prefix as mesh-local address " PRI_SEGMENTED_IPv6_ADDR_SRP ".",
    431              SEGMENTED_IPv6_ADDR_PARAM_SRP(addr_ptr, addr_buf),
    432              SEGMENTED_IPv6_ADDR_PARAM_SRP(&publisher->thread_mesh_local_address, mle_buf));
    433         return false;
    434     }
    435     INFO(PRI_SEGMENTED_IPv6_ADDR_SRP "is on the same prefix as mesh-local address " PRI_SEGMENTED_IPv6_ADDR_SRP ".",
    436          SEGMENTED_IPv6_ADDR_PARAM_SRP(addr_ptr, addr_buf),
    437          SEGMENTED_IPv6_ADDR_PARAM_SRP(&publisher->thread_mesh_local_address, mle_buf));
    438     return true;
    439 }
    440 
    441 static void
    442 service_publisher_finalize(service_publisher_t *publisher)
    443 {
    444     thread_service_release(publisher->published_unicast_service);
    445     thread_service_release(publisher->published_anycast_service);
    446     thread_service_list_release(&publisher->publication_queue);
    447 
    448     free(publisher->state_header.name);
    449     free(publisher->wed_ext_address_string);
    450     free(publisher->wed_ml_eid_string);
    451     free(publisher->neighbor_ml_eid_string);
    452     free(publisher->id);
    453     ioloop_wakeup_release(publisher->wakeup_timer);
    454     free(publisher);
    455 }
    456 
    457 RELEASE_RETAIN_FUNCS(service_publisher);
    458 
    459 static void
    460 service_publisher_context_release(void *context)
    461 {
    462     service_publisher_t *publisher = context;
    463     RELEASE_HERE(publisher, service_publisher);
    464 }
    465 
    466 static void
    467 service_publisher_update_callback(void *context, cti_status_t status)
    468 {
    469     service_publisher_t *publisher = context;
    470     thread_service_t *service = publisher->publication_queue;
    471 
    472     if (publisher->canceled) {
    473         RELEASE_HERE(publisher, service_publisher);
    474         return;
    475     }
    476 
    477     if (service == NULL) {
    478         ERROR("no pending service update");
    479         return;
    480     }
    481     char status_buf[256];
    482     snprintf(status_buf, sizeof(status_buf), "is in state %s, status = %d",
    483              thread_service_publication_state_name_get(service->publication_state), status);
    484     thread_service_note(publisher->id, service, status_buf);
    485     if (status == kCTIStatus_NoError) {
    486         if (service->publication_state == add_pending) {
    487             service->publication_state = add_complete;
    488         } else if (service->publication_state == delete_pending) {
    489             service->publication_state = delete_complete;
    490         }
    491     } else {
    492         if (service->publication_state == add_pending) {
    493             service->publication_state = add_failed;
    494         } else if (service->publication_state == delete_pending) {
    495             service->publication_state = delete_failed;
    496         }
    497     }
    498     publisher->publication_queue = service->next;
    499     thread_service_release(service);
    500     if (!publisher->canceled) {
    501         service_publisher_queue_run(publisher);
    502     }
    503     RELEASE_HERE(publisher, service_publisher);
    504 }
    505 
    506 static cti_status_t
    507 service_publisher_service_update(service_publisher_t *publisher, thread_service_t *service, bool add)
    508 {
    509     uint8_t service_data[20];
    510     uint8_t server_data[20];
    511     size_t service_data_length, server_data_length;
    512     switch(service->service_type) {
    513     default:
    514         return kCTIStatus_Invalid;
    515     case unicast_service:
    516         service_data[0] = THREAD_SRP_SERVER_OPTION;
    517         service_data_length = 1;
    518         memcpy(server_data, &service->u.unicast.address, 16);
    519         memcpy(&server_data[16], service->u.unicast.port, 2);
    520         server_data_length = 18;
    521         break;
    522     case anycast_service:
    523         service_data[0] = THREAD_SRP_SERVER_ANYCAST_OPTION;
    524         service_data[1] = service->u.anycast.sequence_number;
    525         service_data_length = 2;
    526         server_data_length = 0;
    527         break;
    528     case pref_id:
    529         return kCTIStatus_BadParam; // Not supported anymore.
    530     }
    531 
    532     if (add) {
    533         return cti_add_service(publisher->server_state, publisher, service_publisher_update_callback, NULL,
    534                                THREAD_ENTERPRISE_NUMBER, service_data, service_data_length, server_data, server_data_length);
    535     } else {
    536         return cti_remove_service(publisher->server_state, publisher, service_publisher_update_callback, NULL,
    537                                   THREAD_ENTERPRISE_NUMBER, service_data, service_data_length);
    538     }
    539 }
    540 
    541 static void
    542 service_publisher_queue_run(service_publisher_t *publisher)
    543 {
    544     thread_service_t *service = publisher->publication_queue;
    545     if (service == NULL) {
    546         INFO("the queue is empty.");
    547         return;
    548     }
    549     if (service->publication_state == delete_pending || service->publication_state == add_pending) {
    550         INFO("there is a pending update at the head of the queue.");
    551         return;
    552     }
    553     if (service->publication_state == want_delete) {
    554         cti_status_t status = service_publisher_service_update(publisher, service, false);
    555         if (status != kCTIStatus_NoError) {
    556             ERROR("cti_remove_service failed: %d", status);
    557             // For removes, we'll leave it on the queue
    558         } else {
    559             service->publication_state = delete_pending;
    560             RETAIN_HERE(publisher, service_publisher); // for the callback
    561         }
    562     } else if (service->publication_state == want_add) {
    563         cti_status_t status = service_publisher_service_update(publisher, service, true);
    564         if (status != kCTIStatus_NoError) {
    565             ERROR("cti_add_service failed: %d", status);
    566             publisher->publication_queue = service->next;
    567             thread_service_release(service);
    568         } else {
    569             service->publication_state = add_pending;
    570             RETAIN_HERE(publisher, service_publisher); // for the callback
    571         }
    572     } else {
    573         char status_buf[256];
    574         snprintf(status_buf, sizeof(status_buf), "is in unexpected state %s on the publication queue",
    575                  thread_service_publication_state_name_get(service->publication_state));
    576         thread_service_note(publisher->id, service, status_buf);
    577         publisher->publication_queue = service->next;
    578         thread_service_release(service);
    579     }
    580 }
    581 
    582 static void
    583 service_publisher_queue_update(service_publisher_t *publisher, thread_service_t *service,
    584                                thread_service_publication_state_t initial_state)
    585 {
    586     thread_service_t **ppref;
    587 
    588     thread_service_t **p_published;
    589     if (service->service_type == unicast_service) {
    590         p_published = &publisher->published_unicast_service;
    591     } else if (service->service_type == unicast_service) {
    592         p_published = &publisher->published_unicast_service;
    593     } else {
    594         ERROR("unsupported service type %d", service->service_type);
    595         return;
    596     }
    597     if (thread_service_equal(*p_published, service)) {
    598         FAULT("published service still present: %p", *p_published);
    599     }
    600     service->publication_state = initial_state;
    601     if (initial_state == want_add) {
    602         *p_published = service;
    603         thread_service_retain(*p_published);
    604     }
    605     // Find the end of the queue
    606     for (ppref = &publisher->publication_queue; *ppref != NULL; ppref = &(*ppref)->next)
    607         ;
    608     *ppref = service;
    609     // Retain the service on the queue.
    610     thread_service_retain(*ppref);
    611     service_publisher_queue_run(publisher);
    612 }
    613 
    614 static thread_service_t *
    615 service_publisher_create_service_for_queue(thread_service_t *service)
    616 {
    617     switch(service->service_type) {
    618     case unicast_service:
    619         return thread_service_unicast_create(service->rloc16, service->u.unicast.address.s6_addr,
    620                                              service->u.unicast.port, service->service_id);
    621     case anycast_service:
    622         return thread_service_anycast_create(service->rloc16, service->u.anycast.sequence_number, service->service_id);
    623     case pref_id:
    624         return thread_service_pref_id_create(service->rloc16, service->u.pref_id.partition_id,
    625                                              service->u.pref_id.prefix, service->service_id);
    626     default:
    627         return NULL;
    628     }
    629 }
    630 
    631 static void UNUSED
    632 service_publisher_service_publish(service_publisher_t *publisher, thread_service_t *service)
    633 {
    634     service_publisher_queue_update(publisher, service, want_add);
    635 }
    636 
    637 static void UNUSED
    638 service_publisher_service_unpublish(service_publisher_t *publisher, thread_service_type_t service_type, bool enqueue)
    639 {
    640     thread_service_t *service;
    641 
    642     if (service_type == unicast_service) {
    643         service = publisher->published_unicast_service;
    644         publisher->published_unicast_service = NULL;
    645     } else if (service_type == anycast_service) {
    646         service = publisher->published_anycast_service;
    647         publisher->published_anycast_service = NULL;
    648     } else {
    649         ERROR("unsupported service type %d", service_type);
    650         return;
    651     }
    652     if (service == NULL) {
    653         ERROR("request to unpublished service that's not present");
    654         return;
    655     }
    656 
    657     if (enqueue) {
    658         thread_service_t *to_delete = service_publisher_create_service_for_queue(service);
    659         service_publisher_queue_update(publisher, to_delete, want_delete);
    660         thread_service_release(to_delete); // service_publisher_queue_update explicitly retains the references it makes.
    661         thread_service_release(service); // No longer published.
    662     }
    663 }
    664 
    665 static void
    666 service_publisher_unpublish_stale_service(service_publisher_t *publisher, thread_service_t *service)
    667 {
    668     // If there's a stale service, don't try to publish the real service until we see the stale service go away.
    669     INFO("setting seen_service_list to false");
    670     publisher->seen_service_list = false;
    671 
    672     thread_service_t *to_delete = service_publisher_create_service_for_queue(service);
    673 
    674     if (to_delete == NULL) {
    675         thread_service_note(publisher->id, service, "no memory for service to delete");
    676     } else {
    677         service_publisher_queue_update(publisher, to_delete, want_delete);
    678         thread_service_release(to_delete); // service_publisher_queue_update explicitly retains all the references it makes
    679         service->ignore = true;
    680     }
    681 }
    682 
    683 static void
    684 service_publisher_wait_expired(void *context)
    685 {
    686     service_publisher_t *publisher = context;
    687     state_machine_event_t *event = state_machine_event_create(state_machine_event_type_timeout, NULL);
    688     if (event == NULL) {
    689         ERROR("unable to allocate event to deliver");
    690         return;
    691     }
    692     state_machine_event_deliver(&publisher->state_header, event);
    693     RELEASE_HERE(event, state_machine_event);
    694 }
    695 
    696 static void
    697 service_publisher_start_wait(service_publisher_t *publisher, int32_t milliseconds)
    698 {
    699     ioloop_add_wake_event(publisher->wakeup_timer, publisher, service_publisher_wait_expired,
    700                           service_publisher_context_release, milliseconds);
    701     RETAIN_HERE(publisher, service_publisher); // For wakeup
    702 }
    703 
    704 static bool
    705 service_publisher_have_competing_unicast_service(service_publisher_t *publisher, bool want_stale_service_timeout)
    706 {
    707     thread_service_t *NULLABLE published_service = publisher->published_unicast_service;
    708     bool competing_service_present = false;
    709 
    710     for (thread_service_t *service = service_tracker_services_get(publisher->server_state->service_tracker);
    711          service != NULL; service = service->next)
    712     {
    713         if (service->ignore) {
    714             continue;
    715         }
    716         if (service->service_type == unicast_service) {
    717             if (published_service == NULL) {
    718                 if (service->rloc16 == publisher->server_state->rloc16 ||
    719                     (publisher->have_ml_eid &&
    720                      !in6addr_compare(&service->u.unicast.address, &publisher->thread_mesh_local_address)))
    721                 {
    722                     thread_service_note(publisher->id, service,
    723                                         "is on our ml-eid or rloc16 but we aren't publishing it, so it's stale.");
    724                     service_publisher_unpublish_stale_service(publisher, service);
    725 
    726                     if (want_stale_service_timeout &&
    727                         !publisher->cached_services_published && !publisher->started_stale_service_timeout)
    728                     {
    729                         INFO("starting wakeup timer to publish cached services after stale service timeout.");
    730                         publisher->started_stale_service_timeout = true;
    731                         service_publisher_start_wait(publisher, 2000);
    732                     }
    733                     continue;
    734                 }
    735                 thread_service_note(publisher->id, service, "is not ours and we aren't publishing.");
    736                 competing_service_present = true;
    737             // First check to see if the other service is on the mesh-local prefix. If it's not, it wins.
    738             } else if (in6prefix_compare(&service->u.unicast.address, &published_service->u.unicast.address, 8)) {
    739                 competing_service_present = true;
    740                 thread_service_note(publisher->id, service, "is a competing service.");
    741             } else {
    742                 int cmp = in6addr_compare(&service->u.unicast.address, &published_service->u.unicast.address);
    743 
    744                 // If equal, compare ports...
    745                 if (!cmp) {
    746                     cmp = memcmp(service->u.unicast.port, published_service->u.unicast.port,
    747                                  sizeof(service->u.unicast.port));
    748                     // If the port doesn't match our published service, it's a weird stale service (this probably can't
    749                     // happen);
    750                     if (cmp) {
    751                         thread_service_note(publisher->id, service,
    752                                             "is on our ml-eid but is not the one we are publishing, so it's stale.");
    753                         service_publisher_unpublish_stale_service(publisher, service);
    754                         continue;
    755                     } else {
    756                         thread_service_note(publisher->id, service, "is the one we are publishing.");
    757                     }
    758                 } else {
    759                     // This is a stale service published on our RLOC16 with a different ML-EID.
    760                     if (service->rloc16 == publisher->server_state->rloc16) {
    761                         thread_service_note(publisher->id, service,
    762                                             "is a stale service published on our rloc16 with a different ml-eid.");
    763                         service_publisher_unpublish_stale_service(publisher, service);
    764                         continue;
    765                     } else if (cmp < 0) {
    766                         competing_service_present = true;
    767                         thread_service_note(publisher->id, service, "is not ours and wins against ours.");
    768                     } else {
    769                         thread_service_note(publisher->id, service, "is not ours and loses against ours.");
    770                     }
    771                 }
    772             }
    773         }
    774     }
    775     return competing_service_present;
    776 }
    777 
    778 static bool
    779 service_publisher_have_anycast_service(service_publisher_t *publisher)
    780 {
    781     bool anycast_service_present = false;
    782 
    783     for (thread_service_t *service = service_tracker_services_get(publisher->server_state->service_tracker);
    784          service != NULL; service = service->next)
    785     {
    786         if (service->ignore) {
    787             continue;
    788         }
    789         if (service->service_type == anycast_service) {
    790             thread_service_note(publisher->id, service, "is present and supersedes our unicast service");
    791             anycast_service_present = true;
    792         }
    793     }
    794     return anycast_service_present;
    795 }
    796 
    797 void
    798 service_publisher_wanted_service_added(service_publisher_t *publisher)
    799 {
    800     state_machine_event_t *event = state_machine_event_create(state_machine_event_type_srp_needed, NULL);
    801     if (event == NULL) {
    802         ERROR("unable to allocate event to deliver");
    803         return;
    804     }
    805     state_machine_event_deliver(&publisher->state_header, event);
    806     RELEASE_HERE(event, state_machine_event);
    807 }
    808 
    809 static void
    810 service_publisher_sed_timeout_expired(void *context)
    811 {
    812     service_publisher_t *publisher = context;
    813 
    814     if (publisher->sed_timeout != NULL) {
    815         ioloop_wakeup_release(publisher->sed_timeout);
    816         publisher->sed_timeout = NULL;
    817     }
    818     if (publisher->neighbor_ml_eid_string == NULL) {
    819         publisher->neighbor_ml_eid_string = strdup("none");
    820         memset(&publisher->neighbor_ml_eid, 0, sizeof(publisher->neighbor_ml_eid));
    821     }
    822     state_machine_event_t *event = state_machine_event_create(state_machine_event_type_neighbor_ml_eid_changed, NULL);
    823     if (event == NULL) {
    824         ERROR("unable to allocate event to deliver");
    825     } else {
    826         state_machine_event_deliver(&publisher->state_header, event);
    827         RELEASE_HERE(event, state_machine_event);
    828     }
    829 }
    830 
    831 static void
    832 service_publisher_service_tracker_callback(void *context)
    833 {
    834     service_publisher_t *publisher = context;
    835 
    836     // If we get a service list update when we're associated, set the seen_service-list flag to true. This tells us we can proceed
    837     // with publishing a service if we just associated to the thread network.
    838     if (thread_tracker_associated_get(publisher->server_state->thread_tracker, false)) {
    839         INFO("setting seen_service_list to true");
    840         publisher->seen_service_list = true;
    841     }
    842 
    843     state_machine_event_t *event = state_machine_event_create(state_machine_event_type_service_list_changed, NULL);
    844     if (event == NULL) {
    845         ERROR("unable to allocate event to deliver");
    846         return;
    847     }
    848     state_machine_event_deliver(&publisher->state_header, event);
    849     RELEASE_HERE(event, state_machine_event);
    850 }
    851 
    852 static void
    853 service_publisher_thread_tracker_callback(void *context)
    854 {
    855     service_publisher_t *publisher = context;
    856 
    857     // This is a temporary hack because right now we won't get a prefix list event on associate, and we need
    858     // the (presumably empty) prefix list event to trigger an immediate service advertisement.
    859     // IMPORTANT: when this is fixed, make sure to start the service_tracker in thread-device.c again.
    860     // To work around this issue, we stop service list events in the service tracker when we dissociate, and
    861     // restart events when we re-associate.
    862     // Hack is tracked in rdar://109266343 (Optimize SRP registration time)
    863     if (!thread_tracker_associated_get(publisher->server_state->thread_tracker, false)) {
    864         service_tracker_stop(publisher->server_state->service_tracker);
    865     } else {
    866         service_tracker_start(publisher->server_state->service_tracker);
    867     }
    868 
    869     state_machine_event_t *event = state_machine_event_create(state_machine_event_type_thread_network_state_changed, NULL);
    870     if (event == NULL) {
    871         ERROR("unable to allocate event to deliver");
    872         return;
    873     }
    874     state_machine_event_deliver(&publisher->state_header, event);
    875     RELEASE_HERE(event, state_machine_event);
    876 }
    877 
    878 static void
    879 service_publisher_node_type_tracker_callback(void *context)
    880 {
    881     service_publisher_t *publisher = context;
    882     state_machine_event_t *event = state_machine_event_create(state_machine_event_type_thread_node_type_changed, NULL);
    883     if (event == NULL) {
    884         ERROR("unable to allocate event to deliver");
    885         return;
    886     }
    887     state_machine_event_deliver(&publisher->state_header, event);
    888     RELEASE_HERE(event, state_machine_event);
    889 }
    890 
    891 // Service publisher states
    892 //
    893 // <startup>
    894 //      on entry: start timer for a random amount of time
    895 //      timer event: -> <waiting to publish>
    896 //      other events: ignore
    897 // <waiting to publish>
    898 //      on entry: check for service present
    899 //                yes: -> <not publishing>
    900 //                check for ML-EID present
    901 //                yes: -> <start listeners>
    902 //      ML-EID shows up: -> <start listeners>
    903 //      service shows up: -> <not publishing>
    904 // <not publishing>
    905 //      on entry: do nothing
    906 //      last service advertisement goes away: -> <waiting to publish>
    907 // <start listeners>
    908 //      on entry: start listeners
    909 //      listener ready: -> <publishing>
    910 // <publishing>
    911 //      on entry: publish the service
    912 //                start wait timer
    913 //      on timery expiry: publish the service again
    914 //      our service shows up: stop the timer
    915 //      winning service shows up: stop advertising
    916 //                                -> <not publishing>
    917 
    918 static state_machine_state_t service_publisher_action_startup(state_machine_header_t *state_header,
    919                                                               state_machine_event_t *event);
    920 static state_machine_state_t service_publisher_action_waiting_to_publish(state_machine_header_t *state_header,
    921                                                                          state_machine_event_t *event);
    922 static state_machine_state_t service_publisher_action_not_publishing(state_machine_header_t *state_header,
    923                                                                  state_machine_event_t *event);
    924 static state_machine_state_t service_publisher_action_start_listeners(state_machine_header_t *state_header,
    925                                                                       state_machine_event_t *event);
    926 static state_machine_state_t service_publisher_action_publishing(state_machine_header_t *state_header,
    927                                                                  state_machine_event_t *event);
    928 
    929 #define SERVICE_PUB_NAME_DECL(name) service_publisher_state_##name, #name
    930 static state_machine_decl_t service_publisher_states[] = {
    931     { SERVICE_PUB_NAME_DECL(invalid),                            NULL },
    932     { SERVICE_PUB_NAME_DECL(startup),                            service_publisher_action_startup },
    933     { SERVICE_PUB_NAME_DECL(waiting_to_publish),                 service_publisher_action_waiting_to_publish },
    934     { SERVICE_PUB_NAME_DECL(not_publishing),                     service_publisher_action_not_publishing },
    935     { SERVICE_PUB_NAME_DECL(start_listeners),                    service_publisher_action_start_listeners },
    936     { SERVICE_PUB_NAME_DECL(publishing),                         service_publisher_action_publishing },
    937 };
    938 #define SERVICE_PUBLISHER_NUM_STATES ((sizeof(service_publisher_states)) / (sizeof(state_machine_decl_t)))
    939 
    940 #define STATE_MACHINE_HEADER_TO_PUBLISHER(state_header)                                                                \
    941     if (state_header->state_machine_type != state_machine_type_service_publisher) {                                    \
    942         ERROR("state header type isn't service_publisher: %d", state_header->state_machine_type);                      \
    943         return service_publisher_state_invalid;                                                                        \
    944     }                                                                                                                  \
    945     service_publisher_t *publisher = state_header->state_object
    946 
    947 // In the startup state, we wait for a timeout to expire before doing anything. This gives other devices on the Thread mesh
    948 // an opportunity to publish as well.
    949 static state_machine_state_t
    950 service_publisher_action_startup(state_machine_header_t *state_header, state_machine_event_t *event)
    951 {
    952     STATE_MACHINE_HEADER_TO_PUBLISHER(state_header);
    953     BR_STATE_ANNOUNCE(publisher, event);
    954 
    955     if (event == NULL) {
    956         // We only need a random startup delay for stub routers, which are generally powered devices that can synchronize
    957         // on restart after a power failure.
    958 #if STUB_ROUTER
    959         if (publisher->server_state->stub_router_enabled) {
    960             service_publisher_start_wait(publisher, publisher->startup_delay_range + srp_random16() % publisher->startup_delay_range);
    961             RETAIN_HERE(publisher, service_publisher); // For wakeup
    962             return service_publisher_state_invalid;
    963         }
    964 #endif
    965         return service_publisher_state_waiting_to_publish;
    966     }
    967 
    968     // The only way out of the startup state is for the timer to expire--we don't care about prefixes showing up or
    969     // going away.
    970     if (event->type == state_machine_event_type_timeout) {
    971         INFO("startup timeout");
    972         return service_publisher_state_waiting_to_publish;
    973     }
    974 
    975     BR_UNEXPECTED_EVENT(publisher, event);
    976 }
    977 
    978 static bool
    979 service_publisher_can_publish(service_publisher_t *publisher)
    980 {
    981     bool no_anycast_service = true;
    982     bool no_competing_service = true;
    983     bool associated = true;
    984     bool router = false;
    985     bool have_ml_eid = true;
    986     bool have_thread_interface_name = true;
    987     bool can_publish = true;
    988     bool sleepy_router = false;
    989     bool sleepy_end_device = false;
    990     bool have_node_type = false;
    991     bool have_wed_ml_eid = true;
    992     bool have_neighbor_ml_eid = true;
    993 
    994     // Check the conditions that prevent publication.
    995     if (service_publisher_have_competing_unicast_service(publisher, false)) {
    996         no_competing_service = false;
    997         can_publish = false;
    998     }
    999     if (service_publisher_have_anycast_service(publisher)) {
   1000         no_anycast_service = false;
   1001         can_publish = false;
   1002     }
   1003     srp_server_t *server_state = publisher->server_state;
   1004     if (!thread_tracker_associated_get(server_state->thread_tracker, false)) {
   1005         associated = false;
   1006         can_publish = false;
   1007         INFO("setting seen_service_list to false");
   1008         publisher->seen_service_list = false;
   1009     }
   1010 
   1011     thread_node_type_t node_type = node_type_tracker_thread_node_type_get(server_state->node_type_tracker, false);
   1012     switch(node_type) {
   1013     case node_type_router:
   1014     case node_type_leader:
   1015         router = true;
   1016         have_node_type = true;
   1017         break;
   1018     case node_type_sleepy_router:
   1019         sleepy_router = true;
   1020         have_node_type = true;
   1021         break;
   1022     case node_type_unknown:
   1023         have_node_type = false;
   1024         can_publish = false;
   1025         break;
   1026     case node_type_sleepy_end_device:
   1027     case node_type_synchronized_sleepy_end_device:
   1028         sleepy_end_device = true;
   1029         have_node_type = true;
   1030         break;
   1031     default:
   1032         have_node_type = true;
   1033         break;
   1034     }
   1035 
   1036     if (!publisher->have_ml_eid) {
   1037         have_ml_eid = false;
   1038         can_publish = false;
   1039     }
   1040     if (!publisher->have_thread_interface_name) {
   1041         have_thread_interface_name = false;
   1042         can_publish = false;
   1043     }
   1044     if (!publisher->seen_service_list) {
   1045         can_publish = false;
   1046     }
   1047     if (publisher->stopped) {
   1048         can_publish = false;
   1049     }
   1050     if (publisher->wed_ml_eid_string == NULL) {
   1051         have_wed_ml_eid = false;
   1052         if (sleepy_router) {
   1053             can_publish = false;
   1054         }
   1055     }
   1056     if (publisher->neighbor_ml_eid_string == NULL) {
   1057         have_neighbor_ml_eid = false;
   1058         if (sleepy_end_device) {
   1059             if (publisher->sed_timeout == NULL) {
   1060                 publisher->sed_timeout = ioloop_wakeup_create();
   1061                 if (publisher->sed_timeout != NULL) {
   1062                     ioloop_add_wake_event(publisher->sed_timeout, publisher, service_publisher_sed_timeout_expired,
   1063                                           service_publisher_context_release, 500);
   1064                     RETAIN_HERE(publisher, service_publisher);
   1065                 }
   1066             }
   1067             can_publish = false;
   1068         }
   1069     }
   1070 
   1071     INFO(PUB_S_SRP PUB_S_SRP PUB_S_SRP PUB_S_SRP PUB_S_SRP PUB_S_SRP PUB_S_SRP PUB_S_SRP PUB_S_SRP PUB_S_SRP PUB_S_SRP PUB_S_SRP PUB_S_SRP PUB_S_SRP,
   1072          can_publish ?                         "can publish" :  "can't publish",
   1073          publisher->seen_service_list ?                   "" : " have not seen service list",
   1074          no_competing_service ?                           "" : " competing service present",
   1075          no_anycast_service ?                             "" : " anycast service present",
   1076          associated ?                                     "" : " not associated ",
   1077          router ?                                         "" : " not a router ",
   1078          sleepy_router ?                                  "" : " not a sleepy router",
   1079          sleepy_end_device ?                              "" : " not a sleepy end device",
   1080          have_node_type ?                                 "" : " don't have node type",
   1081          have_ml_eid ?                                    "" : " no ml-eid ",
   1082          have_wed_ml_eid ?                                "" : " no wed ml-eid ",
   1083          have_neighbor_ml_eid ?                           "" : " no neighbor ml-eid ",
   1084          have_thread_interface_name ?                     "" : " no thread interface name ",
   1085          publisher->stopped ?                     " stopped" : "");
   1086     return can_publish;
   1087 }
   1088 
   1089 // This function tells the caller whether the service publisher could publish a service. This will be the case either
   1090 // because it actually is publishing a service, or because it's in the process of finding out if it can publish a
   1091 // service, or preparing to publish a service. In practice, this means that the only state for which the answer is false
   1092 // at present is the "not_publishing" state.
   1093 bool
   1094 service_publisher_could_publish(service_publisher_t *publisher)
   1095 {
   1096     if (publisher == NULL) {
   1097         return false;
   1098     }
   1099     if (publisher->state_header.state == service_publisher_state_startup ||
   1100         publisher->state_header.state == service_publisher_state_waiting_to_publish ||
   1101         publisher->state_header.state == service_publisher_state_start_listeners ||
   1102         publisher->state_header.state == service_publisher_state_publishing)
   1103     {
   1104         return true;
   1105     }
   1106     return false;
   1107 }
   1108 
   1109 void
   1110 service_publisher_stop_publishing(service_publisher_t *publisher)
   1111 {
   1112     publisher->stopped = true;
   1113     state_machine_event_t *event = state_machine_event_create(state_machine_event_type_stop, NULL);
   1114     if (event == NULL) {
   1115         ERROR("unable to allocate event to deliver");
   1116         return;
   1117     }
   1118     state_machine_event_deliver(&publisher->state_header, event);
   1119     RELEASE_HERE(event, state_machine_event);
   1120 }
   1121 
   1122 // We go to this state whenever we think we might need to publish, but are not yet publishing. So this state
   1123 // acts as a gatekeeper: if there is already a service published, we go straight to not_publishing. If we don't
   1124 // yet have an ML-EID, we have to wait until we get one to publish. If, while we are waiting for the ML-EID,
   1125 // we see a service show up, we go to not_publishing. Otherwise, when the ML-EID comes, we go to the listener_start
   1126 // page.
   1127 static state_machine_state_t
   1128 service_publisher_action_waiting_to_publish(state_machine_header_t *state_header, state_machine_event_t *event)
   1129 {
   1130     STATE_MACHINE_HEADER_TO_PUBLISHER(state_header);
   1131     BR_STATE_ANNOUNCE(publisher, event);
   1132 
   1133     // We do the same thing here whether we've gotten an event or just on entry, so no need to check.
   1134     if (service_publisher_can_publish(publisher)) {
   1135         ioloop_cancel_wake_event(publisher->wakeup_timer);
   1136         publisher->started_stale_service_timeout = false;
   1137         return service_publisher_state_start_listeners;
   1138     }
   1139     if (service_publisher_have_competing_unicast_service(publisher, true)) {
   1140         ioloop_cancel_wake_event(publisher->wakeup_timer);
   1141         publisher->started_stale_service_timeout = false;
   1142         return service_publisher_state_not_publishing;
   1143     }
   1144     // If we saw a stale service, we'll get a timeout event here.
   1145     if (event != NULL && event->type == state_machine_event_type_timeout && !publisher->cached_services_published) {
   1146         service_publisher_re_advertise_matching(publisher);
   1147     }
   1148     return service_publisher_state_invalid;
   1149 }
   1150 
   1151 // We get into this state when there is a competing service that wins the election against our service.
   1152 // We only leave the state when there is no longer a competing prefix.
   1153 static state_machine_state_t
   1154 service_publisher_action_not_publishing(state_machine_header_t *state_header, state_machine_event_t *event)
   1155 {
   1156     STATE_MACHINE_HEADER_TO_PUBLISHER(state_header);
   1157     BR_STATE_ANNOUNCE(publisher, event);
   1158 
   1159     if (event == NULL) {
   1160         if (publisher->published_unicast_service != NULL) {
   1161             service_publisher_service_unpublish(publisher, unicast_service, true);
   1162         }
   1163         return service_publisher_state_invalid;
   1164     }
   1165 
   1166     // We do the same thing here for any event we get, because we're just waiting for conditions to be right.
   1167     if (service_publisher_can_publish(publisher)) {
   1168         publisher->startup_delay_range = SERVICE_PUBLISHER_LOST_WAIT;
   1169         return service_publisher_state_startup;
   1170     }
   1171     return service_publisher_state_invalid;
   1172 }
   1173 
   1174 static void
   1175 service_publisher_listener_cancel_callback(comm_t *UNUSED listener, void *context)
   1176 {
   1177     srp_server_t *server_state = context;
   1178     service_publisher_t *publisher = server_state->service_publisher;
   1179     if (publisher != NULL) {
   1180         state_machine_event_t *event = state_machine_event_create(state_machine_event_type_listener_canceled, NULL);
   1181         if (event == NULL) {
   1182             ERROR("unable to allocate event to deliver");
   1183             return;
   1184         }
   1185         state_machine_event_deliver(&publisher->state_header, event);
   1186         RELEASE_HERE(event, state_machine_event);
   1187     }
   1188 }
   1189 
   1190 static void
   1191 service_publisher_listener_cancel(service_publisher_t *publisher)
   1192 {
   1193     if (publisher->srp_listener != NULL) {
   1194         ioloop_listener_cancel(publisher->srp_listener);
   1195         ioloop_comm_release(publisher->srp_listener);
   1196         publisher->srp_listener = NULL;
   1197     }
   1198     publisher->have_srp_listener = false;
   1199     service_publisher_unadvertise_all(publisher);
   1200 }
   1201 
   1202 static void
   1203 service_publisher_listener_ready(void *context, uint16_t port)
   1204 {
   1205     srp_server_t *server_state = context;
   1206     service_publisher_t *publisher = server_state->service_publisher;
   1207     if (publisher != NULL) {
   1208         state_machine_event_t *event = state_machine_event_create(state_machine_event_type_listener_ready, NULL);
   1209         if (event == NULL) {
   1210             ERROR("unable to allocate event to deliver");
   1211             return;
   1212         }
   1213         publisher->have_srp_listener = true;
   1214         publisher->srp_listener_port = port;
   1215         state_machine_event_deliver(&publisher->state_header, event);
   1216         RELEASE_HERE(event, state_machine_event);
   1217     }
   1218 }
   1219 
   1220 static void
   1221 service_publisher_listener_start(service_publisher_t *publisher)
   1222 {
   1223     if (publisher->srp_listener) {
   1224         FAULT("listener still present");
   1225         service_publisher_listener_cancel(publisher);
   1226     }
   1227     publisher->srp_listener = srp_proxy_listen(NULL, 0, publisher->thread_interface_name, service_publisher_listener_ready,
   1228                                                service_publisher_listener_cancel_callback, NULL,
   1229                                                NULL, publisher->server_state);
   1230     if (publisher->srp_listener == NULL) {
   1231         ERROR("failed to setup SRP listener");
   1232     }
   1233     service_publisher_re_advertise_matching(publisher);
   1234 }
   1235 
   1236 // We go to this state when we have decided to publish, but perhaps do not currently have an SRP listener
   1237 // running.
   1238 static state_machine_state_t
   1239 service_publisher_action_start_listeners(state_machine_header_t *state_header, state_machine_event_t *event)
   1240 {
   1241     STATE_MACHINE_HEADER_TO_PUBLISHER(state_header);
   1242     BR_STATE_ANNOUNCE(publisher, event);
   1243 
   1244     if (event == NULL) {
   1245         if (publisher->have_srp_listener) {
   1246             if (publisher->srp_listener != NULL) {
   1247                 return service_publisher_state_publishing;
   1248             }
   1249             FAULT("have_srp_listener is true but there's no listener!");
   1250             publisher->have_srp_listener = false;
   1251         }
   1252         service_publisher_listener_start(publisher);
   1253         return service_publisher_state_invalid;
   1254     }
   1255 
   1256     // If we get a competing service while we're waiting for the listener to start, cancel the listener.
   1257     // We do the same thing here for any event we get, because we're just waiting for conditions to be right.
   1258     if (!service_publisher_can_publish(publisher)) {
   1259         service_publisher_listener_cancel(publisher);
   1260         return service_publisher_state_not_publishing;
   1261     }
   1262 
   1263     // If the listener is ready, we can publish.
   1264     if (event->type == state_machine_event_type_listener_ready) {
   1265         return service_publisher_state_publishing;
   1266     }
   1267 
   1268     return service_publisher_state_invalid;
   1269 }
   1270 
   1271 static state_machine_state_t
   1272 service_publisher_published_services_seen(service_publisher_t *publisher)
   1273 {
   1274     return ((publisher->published_unicast_service == NULL || publisher->have_unicast_in_net_data) &&
   1275             (publisher->published_anycast_service == NULL || publisher->have_anycast_in_net_data));
   1276 }
   1277 
   1278 static bool
   1279 service_publisher_wanted_service_missing(service_publisher_t *publisher)
   1280 {
   1281     srp_server_t *server_state = publisher->server_state;
   1282 
   1283         // If we get here, the named service instance is not represented in the current set of services
   1284         // about which we have information.
   1285 #if STUB_ROUTER
   1286     if (server_state->stub_router_enabled) {
   1287         return true; // always publish when stub router
   1288     }
   1289 #endif
   1290     if (server_state->srp_service_needed) {
   1291         INFO("srp_service_needed == true -> true");
   1292         return true; // srp service unconditionally requested
   1293     }
   1294 
   1295     for (wanted_service_t *service = server_state->wanted_services; service != NULL; service = service->next) {
   1296         for (adv_host_t *host = server_state->hosts; host != NULL; host = host->next) {
   1297             if (host->instances != NULL) {
   1298                 for (int i = 0; i < host->instances->num; i++) {
   1299                     adv_instance_t *instance = host->instances->vec[i];
   1300                     if (instance != NULL) {
   1301                         if (!strcasecmp(instance->instance_name, service->name) &&
   1302                             !adv_ctl_service_types_compare(service->service_type, instance->service_type))
   1303                         {
   1304                             if (host->addresses != NULL) {
   1305                                 for (int j = 0; j < host->addresses->num; j++) {
   1306                                     adv_record_t *address = host->addresses->vec[j];
   1307                                     if (address != NULL) {
   1308                                         if (address->rdlen == 16 &&
   1309                                             !in6prefix_compare((struct in6_addr *)address->rdata,
   1310                                                                &publisher->thread_mesh_local_address, 8))
   1311                                         {
   1312                                             goto instance_found;
   1313                                         }
   1314                                     }
   1315                                 }
   1316                                 INFO("srp service " PRI_S_SRP "." PRI_S_SRP " present as " PRI_S_SRP
   1317                                      " but has no address on local mesh -> true",
   1318                                      service->name, service->service_type, instance->instance_name);
   1319                                 return true; // There is no valid address for this instance in the cache.
   1320                             }
   1321                             INFO("srp service " PRI_S_SRP "." PRI_S_SRP " present but no addresses -> true",
   1322                                  service->name, service->service_type);
   1323                             return true; // We didn't find the named instance in the database
   1324                         }
   1325                     }
   1326                 }
   1327             }
   1328         }
   1329         INFO("service " PRI_S_SRP "." PRI_S_SRP " host not present -> true", service->name, service->service_type);
   1330         return true;
   1331     instance_found:
   1332         INFO("service " PRI_S_SRP "." PRI_S_SRP " is present", service->name, service->service_type);
   1333     }
   1334     INFO("all needed services present -> false");
   1335     return false; // There weren't any named instances for which we don't have a usable registration.
   1336 }
   1337 
   1338 // We enter this state when we have an SRP listener and no competing unicast services. On entry, we publish our unicast service.
   1339 // If a competing service shows up that wins, we stop publishing and cancel the listener. Otherwise we remain in this state.
   1340 static state_machine_state_t
   1341 service_publisher_action_publishing(state_machine_header_t *state_header, state_machine_event_t *event)
   1342 {
   1343     STATE_MACHINE_HEADER_TO_PUBLISHER(state_header);
   1344     BR_STATE_ANNOUNCE(publisher, event);
   1345 
   1346     if (event == NULL || event->type == state_machine_event_type_timeout ||
   1347         event->type == state_machine_event_type_srp_needed)
   1348     {
   1349         if (publisher->published_unicast_service != NULL) {
   1350             // We shouldn't see a published service on state entry.
   1351             if (event == NULL) {
   1352                 ERROR("unicast service still published!");
   1353             }
   1354             // Only actually enqueue a delete if we aren't retrying.
   1355             service_publisher_service_unpublish(publisher, unicast_service, event == NULL);
   1356         }
   1357 
   1358         // On non-BR devices, don't actually publish the service until we get a signal that it's needed.
   1359         if (!publisher->server_state->srp_on_demand || service_publisher_wanted_service_missing(publisher)) {
   1360             uint8_t port[] = { publisher->srp_listener_port >> 8, publisher->srp_listener_port & 255 };
   1361             thread_service_t *service = thread_service_unicast_create(publisher->server_state->rloc16,
   1362                                                                       (uint8_t *)&publisher->thread_mesh_local_address,
   1363                                                                       port, 0);
   1364             service_publisher_service_publish(publisher, service);
   1365             thread_service_release(service); // service_publisher_publish retains the references it keeps.
   1366 
   1367             // Set up a retransmit timer in case the service publication fails.
   1368             if (event == NULL) {
   1369                 publisher->retry_interval = 5; // First retry after five seconds
   1370             } else {
   1371                 // Maybe the service tracker is wedged, so restart it
   1372                 service_tracker_start(publisher->server_state->service_tracker);
   1373 
   1374                 // Exponential backoff.
   1375                 if (publisher->retry_interval < 3600) {
   1376                     publisher->retry_interval *= 2;
   1377                 }
   1378             }
   1379             service_publisher_start_wait(publisher, (publisher->retry_interval * MSEC_PER_SEC +
   1380                                                      srp_random32() % (publisher->retry_interval * MSEC_PER_SEC) / 2));
   1381         }
   1382 
   1383         return service_publisher_state_invalid;
   1384     }
   1385 
   1386     // If the listener got canceled for some reason, restart it.
   1387     if (event->type == state_machine_event_type_listener_canceled) {
   1388         service_publisher_service_unpublish(publisher, unicast_service, true);
   1389         publisher->startup_delay_range = SERVICE_PUBLISHER_LISTENER_RESTART_WAIT;
   1390         return service_publisher_state_startup;
   1391     }
   1392 
   1393     // Any other event triggers a re-evaluation.
   1394     if (event->type == state_machine_event_type_ml_eid_changed) {
   1395         service_publisher_listener_cancel(publisher);
   1396         service_publisher_service_unpublish(publisher, unicast_service, true);
   1397         return service_publisher_state_startup;
   1398     }
   1399 
   1400     if (!service_publisher_can_publish(publisher)) {
   1401         service_publisher_listener_cancel(publisher);
   1402         service_publisher_service_unpublish(publisher, unicast_service, true);
   1403         return service_publisher_state_not_publishing;
   1404     }
   1405 
   1406     // If we haven't yet seen all the services we are publishing in the network data, check to see if it showed up.
   1407     if (event->type == state_machine_event_type_service_list_changed &&
   1408         !service_publisher_published_services_seen(publisher))
   1409     {
   1410         publisher->have_unicast_in_net_data = false;
   1411         publisher->have_anycast_in_net_data = false;
   1412         for (thread_service_t *service = service_tracker_services_get(publisher->server_state->service_tracker);
   1413              service != NULL; service = service->next)
   1414         {
   1415             if (service->service_type == unicast_service && service->ncp &&
   1416                 publisher->published_unicast_service != NULL &&
   1417                 !in6addr_compare(&service->u.unicast.address, &publisher->published_unicast_service->u.unicast.address) &&
   1418                 !memcmp(service->u.unicast.port, publisher->published_unicast_service->u.unicast.port, 2))
   1419             {
   1420                 publisher->have_unicast_in_net_data = true;
   1421             }
   1422             else if (service->service_type == anycast_service && service->ncp &&
   1423                        publisher->server_state->have_rloc16 && service->rloc16 == publisher->server_state->rloc16 &&
   1424                        publisher->published_anycast_service != NULL &&
   1425                        service->u.anycast.sequence_number == publisher->published_anycast_service->u.anycast.sequence_number)
   1426             {
   1427                 publisher->have_anycast_in_net_data = true;
   1428             }
   1429         }
   1430 
   1431         // If all of the services we are publishing are showing up in NCP, we can cancel the timer and go to the publishing state.
   1432         if (service_publisher_published_services_seen(publisher)) {
   1433             ioloop_cancel_wake_event(publisher->wakeup_timer);
   1434             return service_publisher_state_invalid;
   1435         }
   1436     }
   1437     return service_publisher_state_invalid;
   1438 }
   1439 
   1440 void
   1441 service_publisher_cancel(service_publisher_t *publisher)
   1442 {
   1443     ioloop_cancel_wake_event(publisher->wakeup_timer);
   1444     service_publisher_listener_cancel(publisher);
   1445     service_tracker_callback_cancel(publisher->server_state->service_tracker, publisher);
   1446     thread_tracker_callback_cancel(publisher->server_state->thread_tracker, publisher);
   1447     node_type_tracker_callback_cancel(publisher->server_state->node_type_tracker, publisher);
   1448     if (publisher->active_data_set_connection != NULL) {
   1449         cti_events_discontinue(publisher->active_data_set_connection);
   1450         publisher->active_data_set_connection = NULL;
   1451         RELEASE_HERE(publisher, service_publisher);
   1452     }
   1453     if (publisher->wed_tracker_connection != NULL) {
   1454         cti_events_discontinue(publisher->wed_tracker_connection);
   1455         publisher->wed_tracker_connection = NULL;
   1456         RELEASE_HERE(publisher, service_publisher);
   1457     }
   1458     if (publisher->neighbor_tracker_connection != NULL) {
   1459         cti_events_discontinue(publisher->neighbor_tracker_connection);
   1460         publisher->neighbor_tracker_connection = NULL;
   1461         RELEASE_HERE(publisher, service_publisher);
   1462     }
   1463     state_machine_cancel(&publisher->state_header);
   1464 }
   1465 
   1466 service_publisher_t *
   1467 service_publisher_create(srp_server_t *server_state)
   1468 {
   1469     service_publisher_t *ret = NULL, *publisher = calloc(1, sizeof(*publisher));
   1470     if (publisher == NULL) {
   1471         return publisher;
   1472     }
   1473     RETAIN_HERE(publisher, service_publisher);
   1474     publisher->wakeup_timer = ioloop_wakeup_create();
   1475     if (publisher->wakeup_timer == NULL) {
   1476         ERROR("wakeup timer alloc failed");
   1477         goto out;
   1478     }
   1479 
   1480     char server_id_buf[100];
   1481     snprintf(server_id_buf, sizeof(server_id_buf), "[SP%lld]", ++service_publisher_serial_number);
   1482     publisher->id = strdup(server_id_buf);
   1483     if (publisher->id == NULL) {
   1484         ERROR("no memory for server ID");
   1485         goto out;
   1486     }
   1487 
   1488     if (!state_machine_header_setup(&publisher->state_header,
   1489                                     publisher, publisher->id,
   1490                                     state_machine_type_service_publisher,
   1491                                     service_publisher_states,
   1492                                     SERVICE_PUBLISHER_NUM_STATES)) {
   1493         ERROR("header setup failed");
   1494         goto out;
   1495     }
   1496 
   1497     publisher->server_state = server_state;
   1498     if (!service_tracker_callback_add(server_state->service_tracker, service_publisher_service_tracker_callback,
   1499                                       service_publisher_context_release, publisher))
   1500     {
   1501         goto out;
   1502     }
   1503     RETAIN_HERE(publisher, service_publisher); // for service tracker
   1504 
   1505     if (!thread_tracker_callback_add(server_state->thread_tracker, service_publisher_thread_tracker_callback,
   1506                                      service_publisher_context_release, publisher))
   1507     {
   1508         goto out;
   1509     }
   1510     RETAIN_HERE(publisher, service_publisher); // for thread network state tracker
   1511 
   1512     if (!node_type_tracker_callback_add(server_state->node_type_tracker, service_publisher_node_type_tracker_callback,
   1513                                         service_publisher_context_release, publisher))
   1514     {
   1515         goto out;
   1516     }
   1517     RETAIN_HERE(publisher, service_publisher); // for thread network state tracker
   1518 
   1519     // Set the first_time flag so that we'll know to remove any locally-published on-mesh prefixes.
   1520     publisher->first_time = true;
   1521     publisher->startup_delay_range = SERVICE_PUBLISHER_START_WAIT;
   1522     ret = publisher;
   1523     publisher = NULL;
   1524 out:
   1525     if (publisher != NULL) {
   1526         RELEASE_HERE(publisher, service_publisher);
   1527     }
   1528     return ret;
   1529 }
   1530 
   1531 static void
   1532 service_publisher_get_mesh_local_address_callback(void *context, const char *address_string, cti_status_t status)
   1533 {
   1534     service_publisher_t *publisher = context;
   1535 
   1536     if (status == kCTIStatus_Disconnected || status == kCTIStatus_DaemonNotRunning) {
   1537         INFO("disconnected");
   1538         if (publisher->reconnect_callback != NULL) {
   1539             publisher->reconnect_callback(publisher->server_state);
   1540         }
   1541         goto fail;
   1542     }
   1543 
   1544     INFO(PUB_S_SRP " %d", address_string != NULL ? address_string : "<null>", status);
   1545     if (status != kCTIStatus_NoError || address_string == NULL) {
   1546         goto fail;
   1547     }
   1548 
   1549     struct in6_addr new_mesh_local_address;
   1550     if (!inet_pton(AF_INET6, address_string, &new_mesh_local_address)) {
   1551         ERROR("address syntax incorrect: " PRI_S_SRP, address_string);
   1552         goto fail;
   1553     }
   1554 
   1555     if (publisher->have_ml_eid && !in6addr_compare(&new_mesh_local_address, &publisher->thread_mesh_local_address)) {
   1556         INFO("address didn't change");
   1557         return;
   1558     }
   1559     publisher->thread_mesh_local_address = new_mesh_local_address;
   1560     publisher->have_ml_eid = true;
   1561 
   1562     for (thread_service_t *service = service_tracker_services_get(publisher->server_state->service_tracker);
   1563          service != NULL; service = service->next)
   1564     {
   1565         if (service->ignore) {
   1566             continue;
   1567         }
   1568         if (service->service_type == unicast_service) {
   1569             if (publisher->published_unicast_service == NULL) {
   1570                 if (service->rloc16 == publisher->server_state->rloc16 ||
   1571                     (publisher->have_ml_eid &&
   1572                      !in6addr_compare(&service->u.unicast.address, &publisher->thread_mesh_local_address)))
   1573                 {
   1574                     thread_service_note(publisher->id, service,
   1575                                         "is on our ml-eid or rloc16 but we aren't publishing it, so it's stale.");
   1576                     service_publisher_unpublish_stale_service(publisher, service);
   1577                     continue;
   1578                 }
   1579             }
   1580         }
   1581     }
   1582 
   1583     state_machine_event_t *event = state_machine_event_create(state_machine_event_type_ml_eid_changed, NULL);
   1584     if (event == NULL) {
   1585         ERROR("unable to allocate event to deliver");
   1586         return;
   1587     }
   1588     state_machine_event_deliver(&publisher->state_header, event);
   1589     RELEASE_HERE(event, state_machine_event);
   1590     RELEASE_HERE(publisher, service_publisher); // callback held a reference.
   1591     return;
   1592 fail:
   1593     RELEASE_HERE(publisher, service_publisher); // callback held a reference.
   1594     publisher->have_ml_eid = false;
   1595     return;
   1596 }
   1597 
   1598 static void
   1599 service_publisher_active_data_set_changed_callback(void *context, cti_status_t status)
   1600 {
   1601     service_publisher_t *publisher = context;
   1602 
   1603     if (status != kCTIStatus_NoError) {
   1604         ERROR("error %d", status);
   1605         RELEASE_HERE(publisher, service_publisher); // no more callbacks
   1606         cti_events_discontinue(publisher->active_data_set_connection);
   1607         publisher->active_data_set_connection = NULL;
   1608         return;
   1609     }
   1610 
   1611     status = cti_get_mesh_local_address(publisher->server_state, publisher,
   1612                                         service_publisher_get_mesh_local_address_callback, NULL);
   1613     if (status != kCTIStatus_NoError) {
   1614         ERROR("cti_get_mesh_local_address failed with status %d", status);
   1615     } else {
   1616         RETAIN_HERE(publisher, service_publisher); // for mesh-local callback
   1617     }
   1618 }
   1619 
   1620 static void
   1621 service_publisher_tunnel_name_callback(void *context, const char *name, cti_status_t status)
   1622 {
   1623     service_publisher_t *publisher = context;
   1624     if (status == kCTIStatus_Disconnected || status == kCTIStatus_DaemonNotRunning) {
   1625         INFO("disconnected");
   1626         goto out;
   1627     }
   1628 
   1629     if (status != kCTIStatus_NoError) {
   1630         INFO(PUB_S_SRP " %d", name != NULL ? name : "<null>", status);
   1631         goto out;
   1632     }
   1633     publisher->have_thread_interface_name = true;
   1634 
   1635     // Get rid of the old interface name if it's changed.
   1636     bool changed = true;
   1637     if (publisher->thread_interface_name != NULL) {
   1638         if (!strcmp(name, publisher->thread_interface_name)) {
   1639             changed = false;
   1640         } else {
   1641             free(publisher->thread_interface_name);
   1642             publisher->thread_interface_name = NULL;
   1643         }
   1644     }
   1645 
   1646     // Store the new interface name if it's changed.
   1647     if (changed) {
   1648         publisher->thread_interface_name = strdup(name);
   1649 
   1650         INFO("thread interface at " PUB_S_SRP, name);
   1651     }
   1652 
   1653     if (publisher->thread_interface_name == NULL) {
   1654         ERROR("No memory to save thread interface name " PUB_S_SRP, name);
   1655     }
   1656 
   1657     state_machine_event_t *event = state_machine_event_create(state_machine_event_type_thread_interface_changed, NULL);
   1658     if (event == NULL) {
   1659         ERROR("unable to allocate event to deliver");
   1660         goto out;
   1661     }
   1662     state_machine_event_deliver(&publisher->state_header, event);
   1663     RELEASE_HERE(event, state_machine_event);
   1664 out:
   1665     RELEASE_HERE(publisher, service_publisher); // callback held a reference.
   1666 }
   1667 
   1668 static void
   1669 service_publisher_wed_callback(void *context, const char *ext_address, const char *ml_eid, bool added, int status)
   1670 {
   1671     service_publisher_t *publisher = context;
   1672     if (status == kCTIStatus_Disconnected || status == kCTIStatus_DaemonNotRunning) {
   1673         INFO("disconnected");
   1674         goto out;
   1675     }
   1676 
   1677     const char *none = "<none>";
   1678     const char *ea = none;
   1679     if (ext_address != NULL) {
   1680         ea = ext_address;
   1681     }
   1682     const char *mle = none;
   1683     if (ml_eid != NULL) {
   1684         int ret = inet_pton(AF_INET6, ml_eid, &publisher->wed_ml_eid);
   1685         if (ret) {
   1686             mle = ml_eid;
   1687         }
   1688     }
   1689 
   1690     INFO("ext_address: " PRI_S_SRP "  ml_eid: " PRI_S_SRP PUB_S_SRP " %d", ea, mle, added ? " added" : " removed", status);
   1691     if (status != kCTIStatus_NoError) {
   1692         goto out;
   1693     }
   1694 
   1695     if (publisher->wed_ext_address_string != NULL) {
   1696         free(publisher->wed_ext_address_string);
   1697         publisher->wed_ext_address_string = NULL;
   1698     }
   1699 
   1700     if (publisher->wed_ml_eid_string != NULL) {
   1701         free(publisher->wed_ml_eid_string);
   1702         publisher->wed_ml_eid_string = NULL;
   1703     }
   1704 
   1705     // API guarantees addresses are non-NULL if added is true.
   1706     if (added) {
   1707         if (ea != none) {
   1708             publisher->wed_ext_address_string = strdup(ea);
   1709             if (publisher->wed_ext_address_string == NULL) {
   1710                 ERROR("no memory for wed_ext_address string!");
   1711             }
   1712         }
   1713         if (mle != none) {
   1714             publisher->wed_ml_eid_string = strdup(mle);
   1715             if (publisher->wed_ml_eid_string == NULL) {
   1716                 ERROR("no memory for wed_ml_eid string!");
   1717                 memset(&publisher->wed_ml_eid, 0, sizeof(publisher->wed_ml_eid));
   1718             }
   1719         } else {
   1720             memset(&publisher->wed_ml_eid, 0, sizeof(publisher->wed_ml_eid));
   1721         }
   1722     }
   1723     state_machine_event_t *event = state_machine_event_create(state_machine_event_type_wed_ml_eid_changed, NULL);
   1724     if (event == NULL) {
   1725         ERROR("unable to allocate event to deliver");
   1726         goto out;
   1727     }
   1728     state_machine_event_deliver(&publisher->state_header, event);
   1729     RELEASE_HERE(event, state_machine_event);
   1730 out:
   1731     ;
   1732 }
   1733 
   1734 static void
   1735 service_publisher_neighbor_callback(void *context, const char *ml_eid, cti_status_t status)
   1736 {
   1737     service_publisher_t *publisher = context;
   1738     if (status == kCTIStatus_Disconnected || status == kCTIStatus_DaemonNotRunning) {
   1739         INFO("disconnected");
   1740         goto out;
   1741     }
   1742 
   1743     const char *none = "<none>";
   1744     const char *mle = none;
   1745     if (ml_eid != NULL) {
   1746         if (!strcmp(ml_eid, "none")) {
   1747             mle = ml_eid;
   1748             memset(&publisher->neighbor_ml_eid, 0, sizeof(publisher->neighbor_ml_eid));
   1749         } else {
   1750             int ret = inet_pton(AF_INET6, ml_eid, &publisher->neighbor_ml_eid);
   1751             if (ret) {
   1752                 mle = ml_eid;
   1753             }
   1754         }
   1755     }
   1756 
   1757     INFO("ml_eid: " PRI_S_SRP ", status %d", mle, status);
   1758     if (status != kCTIStatus_NoError) {
   1759         goto out;
   1760     }
   1761 
   1762 
   1763     if (publisher->neighbor_ml_eid_string != NULL) {
   1764         free(publisher->neighbor_ml_eid_string);
   1765         publisher->neighbor_ml_eid_string = NULL;
   1766     }
   1767 
   1768     if (mle != none) {
   1769         publisher->neighbor_ml_eid_string = strdup(mle);
   1770         if (publisher->neighbor_ml_eid_string == NULL) {
   1771             ERROR("no memory for neighbor_ml_eid string!");
   1772             memset(&publisher->neighbor_ml_eid, 0, sizeof(publisher->neighbor_ml_eid));
   1773         }
   1774     } else {
   1775         memset(&publisher->neighbor_ml_eid, 0, sizeof(publisher->neighbor_ml_eid));
   1776     }
   1777     state_machine_event_t *event = state_machine_event_create(state_machine_event_type_neighbor_ml_eid_changed, NULL);
   1778     if (event == NULL) {
   1779         ERROR("unable to allocate event to deliver");
   1780         goto out;
   1781     }
   1782     state_machine_event_deliver(&publisher->state_header, event);
   1783     RELEASE_HERE(event, state_machine_event);
   1784 
   1785     if (publisher->sed_timeout != NULL) {
   1786         ioloop_cancel_wake_event(publisher->sed_timeout);
   1787         ioloop_wakeup_release(publisher->sed_timeout);
   1788         publisher->sed_timeout = NULL;
   1789     }
   1790 out:
   1791     ;
   1792 }
   1793 
   1794 void
   1795 service_publisher_start(service_publisher_t *publisher)
   1796 {
   1797     cti_status_t status = cti_track_active_data_set(publisher->server_state, &publisher->active_data_set_connection,
   1798                                                     publisher, service_publisher_active_data_set_changed_callback,
   1799                                                     NULL);
   1800     if (status != kCTIStatus_NoError) {
   1801         ERROR("unable to start tracking active dataset: %d", status);
   1802     } else {
   1803         RETAIN_HERE(publisher, service_publisher); // for active dataset callback
   1804     }
   1805 
   1806     status = cti_get_tunnel_name(publisher->server_state, publisher, service_publisher_tunnel_name_callback, NULL);
   1807     if (status != kCTIStatus_NoError) {
   1808         ERROR("unable to get tunnel name: %d", status);
   1809     } else {
   1810         RETAIN_HERE(publisher, service_publisher); // for tunnel name callback
   1811     }
   1812 
   1813 
   1814     status = cti_track_wed_status(publisher->server_state, &publisher->wed_tracker_connection,
   1815                                   publisher, service_publisher_wed_callback, NULL);
   1816     if (status != kCTIStatus_NoError) {
   1817         FAULT("can't track WED status: %d", status);
   1818     } else {
   1819         RETAIN_HERE(publisher, service_publisher);
   1820     }
   1821 
   1822     status = cti_track_neighbor_ml_eid(publisher->server_state, &publisher->neighbor_tracker_connection,
   1823                                        publisher, service_publisher_neighbor_callback, NULL);
   1824     if (status != kCTIStatus_NoError) {
   1825         FAULT("can't track WED status: %d", status);
   1826     } else {
   1827         RETAIN_HERE(publisher, service_publisher);
   1828     }
   1829 
   1830     service_publisher_active_data_set_changed_callback(publisher, kCTIStatus_NoError); // Get the initial state.
   1831     state_machine_next_state(&publisher->state_header, service_publisher_state_startup);
   1832 }
   1833 
   1834 bool
   1835 service_publisher_get_ml_eid(service_publisher_t *publisher, struct in6_addr *ml_eid)
   1836 {
   1837     if (publisher != NULL && publisher->have_ml_eid) {
   1838         in6addr_copy(ml_eid, &publisher->thread_mesh_local_address);
   1839         return true;
   1840     }
   1841     return false;
   1842 }
   1843 
   1844 // Local Variables:
   1845 // mode: C
   1846 // tab-width: 4
   1847 // c-file-style: "bsd"
   1848 // c-basic-offset: 4
   1849 // fill-column: 120
   1850 // indent-tabs-mode: nil
   1851 // End:
   1852