Lines Matching defs:publisher
1 /* service-publisher.c
95 #include "service-publisher.h"
153 static void service_publisher_queue_run(service_publisher_t *publisher);
156 service_publisher_unadvertise_all(service_publisher_t *publisher)
158 srp_server_t *server_state = publisher->server_state;
160 publisher->cached_services_published = false;
336 service_publisher_re_advertise_matching(service_publisher_t *publisher)
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.");
343 srp_server_t *server_state = publisher->server_state;
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)))
387 publisher->cached_services_published = true;
391 service_publisher_is_address_mesh_local(service_publisher_t *publisher, addr_t *address)
421 if (!publisher->have_ml_eid) {
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)) {
432 SEGMENTED_IPv6_ADDR_PARAM_SRP(&publisher->thread_mesh_local_address, mle_buf));
437 SEGMENTED_IPv6_ADDR_PARAM_SRP(&publisher->thread_mesh_local_address, mle_buf));
442 service_publisher_finalize(service_publisher_t *publisher)
444 thread_service_release(publisher->published_unicast_service);
445 thread_service_release(publisher->published_anycast_service);
446 thread_service_list_release(&publisher->publication_queue);
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);
462 service_publisher_t *publisher = context;
463 RELEASE_HERE(publisher, service_publisher);
469 service_publisher_t *publisher = context;
470 thread_service_t *service = publisher->publication_queue;
472 if (publisher->canceled) {
473 RELEASE_HERE(publisher, service_publisher);
484 thread_service_note(publisher->id, service, status_buf);
498 publisher->publication_queue = service->next;
500 if (!publisher->canceled) {
501 service_publisher_queue_run(publisher);
503 RELEASE_HERE(publisher, service_publisher);
507 service_publisher_service_update(service_publisher_t *publisher, thread_service_t *service, bool add)
533 return cti_add_service(publisher->server_state, publisher, service_publisher_update_callback, NULL,
536 return cti_remove_service(publisher->server_state, publisher, service_publisher_update_callback, NULL,
542 service_publisher_queue_run(service_publisher_t *publisher)
544 thread_service_t *service = publisher->publication_queue;
554 cti_status_t status = service_publisher_service_update(publisher, service, false);
560 RETAIN_HERE(publisher, service_publisher); // for the callback
563 cti_status_t status = service_publisher_service_update(publisher, service, true);
566 publisher->publication_queue = service->next;
570 RETAIN_HERE(publisher, service_publisher); // for the callback
576 thread_service_note(publisher->id, service, status_buf);
577 publisher->publication_queue = service->next;
583 service_publisher_queue_update(service_publisher_t *publisher, thread_service_t *service,
590 p_published = &publisher->published_unicast_service;
592 p_published = &publisher->published_unicast_service;
606 for (ppref = &publisher->publication_queue; *ppref != NULL; ppref = &(*ppref)->next)
611 service_publisher_queue_run(publisher);
632 service_publisher_service_publish(service_publisher_t *publisher, thread_service_t *service)
634 service_publisher_queue_update(publisher, service, want_add);
638 service_publisher_service_unpublish(service_publisher_t *publisher, thread_service_type_t service_type, bool enqueue)
643 service = publisher->published_unicast_service;
644 publisher->published_unicast_service = NULL;
646 service = publisher->published_anycast_service;
647 publisher->published_anycast_service = NULL;
659 service_publisher_queue_update(publisher, to_delete, want_delete);
666 service_publisher_unpublish_stale_service(service_publisher_t *publisher, thread_service_t *service)
670 publisher->seen_service_list = false;
675 thread_service_note(publisher->id, service, "no memory for service to delete");
677 service_publisher_queue_update(publisher, to_delete, want_delete);
686 service_publisher_t *publisher = context;
692 state_machine_event_deliver(&publisher->state_header, event);
697 service_publisher_start_wait(service_publisher_t *publisher, int32_t milliseconds)
699 ioloop_add_wake_event(publisher->wakeup_timer, publisher, service_publisher_wait_expired,
701 RETAIN_HERE(publisher, service_publisher); // For wakeup
705 service_publisher_have_competing_unicast_service(service_publisher_t *publisher, bool want_stale_service_timeout)
707 thread_service_t *NULLABLE published_service = publisher->published_unicast_service;
710 for (thread_service_t *service = service_tracker_services_get(publisher->server_state->service_tracker);
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)))
722 thread_service_note(publisher->id, service,
724 service_publisher_unpublish_stale_service(publisher, service);
727 !publisher->cached_services_published && !publisher->started_stale_service_timeout)
730 publisher->started_stale_service_timeout = true;
731 service_publisher_start_wait(publisher, 2000);
735 thread_service_note(publisher->id, service, "is not ours and we aren't publishing.");
740 thread_service_note(publisher->id, service, "is a competing service.");
751 thread_service_note(publisher->id, service,
753 service_publisher_unpublish_stale_service(publisher, service);
756 thread_service_note(publisher->id, service, "is the one we are publishing.");
760 if (service->rloc16 == publisher->server_state->rloc16) {
761 publisher->id, service,
763 service_publisher_unpublish_stale_service(publisher, service);
767 thread_service_note(publisher->id, service, "is not ours and wins against ours.");
769 thread_service_note(publisher->id, service, "is not ours and loses against ours.");
779 service_publisher_have_anycast_service(service_publisher_t *publisher)
783 for (thread_service_t *service = service_tracker_services_get(publisher->server_state->service_tracker);
790 thread_service_note(publisher->id, service, "is present and supersedes our unicast service");
798 service_publisher_wanted_service_added(service_publisher_t *publisher)
805 state_machine_event_deliver(&publisher->state_header, event);
812 service_publisher_t *publisher = context;
814 if (publisher->sed_timeout != NULL) {
815 ioloop_wakeup_release(publisher->sed_timeout);
816 publisher->sed_timeout = NULL;
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));
826 state_machine_event_deliver(&publisher->state_header, event);
834 service_publisher_t *publisher = context;
838 if (thread_tracker_associated_get(publisher->server_state->thread_tracker, false)) {
840 publisher->seen_service_list = true;
848 state_machine_event_deliver(&publisher->state_header, event);
855 service_publisher_t *publisher = context;
863 if (!thread_tracker_associated_get(publisher->server_state->thread_tracker, false)) {
864 service_tracker_stop(publisher->server_state->service_tracker);
866 service_tracker_start(publisher->server_state->service_tracker);
874 state_machine_event_deliver(&publisher->state_header, event);
881 service_publisher_t *publisher = context;
887 state_machine_event_deliver(&publisher->state_header, event);
891 // Service publisher states
945 service_publisher_t *publisher = state_header->state_object
953 BR_STATE_ANNOUNCE(publisher, event);
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
975 BR_UNEXPECTED_EVENT(publisher, event);
979 service_publisher_can_publish(service_publisher_t *publisher)
995 if (service_publisher_have_competing_unicast_service(publisher, false)) {
999 if (service_publisher_have_anycast_service(publisher)) {
1003 srp_server_t *server_state = publisher->server_state;
1008 publisher->seen_service_list = false;
1036 if (!publisher->have_ml_eid) {
1040 if (!publisher->have_thread_interface_name) {
1044 if (!publisher->seen_service_list) {
1047 if (publisher->stopped) {
1050 if (publisher->wed_ml_eid_string == NULL) {
1056 if (publisher->neighbor_ml_eid_string == NULL) {
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,
1064 RETAIN_HERE(publisher, service_publisher);
1073 publisher->seen_service_list ? "" : " have not seen service list",
1085 publisher->stopped ? " stopped" : "");
1089 // This function tells the caller whether the service publisher could publish a service. This will be the case either
1094 service_publisher_could_publish(service_publisher_t *publisher)
1096 if (publisher == NULL) {
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)
1110 service_publisher_stop_publishing(service_publisher_t *publisher)
1112 publisher->stopped = true;
1118 state_machine_event_deliver(&publisher->state_header, event);
1131 BR_STATE_ANNOUNCE(publisher, event);
1134 if (service_publisher_can_publish(publisher)) {
1135 ioloop_cancel_wake_event(publisher->wakeup_timer);
1136 publisher->started_stale_service_timeout = false;
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;
1145 if (event != NULL && event->type == state_machine_event_type_timeout && !publisher->cached_services_published) {
1146 service_publisher_re_advertise_matching(publisher);
1157 BR_STATE_ANNOUNCE(publisher, event);
1160 if (publisher->published_unicast_service != NULL) {
1161 service_publisher_service_unpublish(publisher, unicast_service, true);
1167 if (service_publisher_can_publish(publisher)) {
1168 publisher->startup_delay_range = SERVICE_PUBLISHER_LOST_WAIT;
1178 service_publisher_t *publisher = server_state->service_publisher;
1179 if (publisher != NULL) {
1185 state_machine_event_deliver(&publisher->state_header, event);
1191 service_publisher_listener_cancel(service_publisher_t *publisher)
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;
1198 publisher->have_srp_listener = false;
1199 service_publisher_unadvertise_all(publisher);
1206 service_publisher_t *publisher = server_state->service_publisher;
1207 if (publisher != NULL) {
1213 publisher->have_srp_listener = true;
1214 publisher->srp_listener_port = port;
1215 state_machine_event_deliver(&publisher->state_header, event);
1221 service_publisher_listener_start(service_publisher_t *publisher)
1223 if (publisher->srp_listener) {
1225 service_publisher_listener_cancel(publisher);
1227 publisher->srp_listener = srp_proxy_listen(NULL, 0, publisher->thread_interface_name, service_publisher_listener_ready,
1229 NULL, publisher->server_state);
1230 if (publisher->srp_listener == NULL) {
1233 service_publisher_re_advertise_matching(publisher);
1242 BR_STATE_ANNOUNCE(publisher, event);
1245 if (publisher->have_srp_listener) {
1246 if (publisher->srp_listener != NULL) {
1250 publisher->have_srp_listener = false;
1252 service_publisher_listener_start(publisher);
1258 if (!service_publisher_can_publish(publisher)) {
1259 service_publisher_listener_cancel(publisher);
1272 service_publisher_published_services_seen(service_publisher_t *publisher)
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));
1279 service_publisher_wanted_service_missing(service_publisher_t *publisher)
1281 srp_server_t *server_state = publisher->server_state;
1310 &publisher->thread_mesh_local_address, 8))
1344 BR_STATE_ANNOUNCE(publisher, event);
1349 if (publisher->published_unicast_service != NULL) {
1355 service_publisher_service_unpublish(publisher, unicast_service, event == NULL);
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,
1364 service_publisher_service_publish(publisher, service);
1369 publisher->retry_interval = 5; // First retry after five seconds
1372 service_tracker_start(publisher->server_state->service_tracker);
1375 if (publisher->retry_interval < 3600) {
1376 publisher->retry_interval *= 2;
1379 service_publisher_start_wait(publisher, (publisher->retry_interval * MSEC_PER_SEC +
1380 srp_random32() % (publisher->retry_interval * MSEC_PER_SEC) / 2));
1388 service_publisher_service_unpublish(publisher, unicast_service, true);
1389 publisher->startup_delay_range = SERVICE_PUBLISHER_LISTENER_RESTART_WAIT;
1395 service_publisher_listener_cancel(publisher);
1396 service_publisher_service_unpublish(publisher, unicast_service, true);
1400 if (!service_publisher_can_publish(publisher)) {
1401 service_publisher_listener_cancel(publisher);
1402 service_publisher_service_unpublish(publisher, unicast_service, true);
1408 !service_publisher_published_services_seen(publisher))
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);
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))
1420 publisher->have_unicast_in_net_data = true;
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)
1427 publisher->have_anycast_in_net_data = true;
1432 if (service_publisher_published_services_seen(publisher)) {
1433 ioloop_cancel_wake_event(publisher->wakeup_timer);
1441 service_publisher_cancel(service_publisher_t *publisher)
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);
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);
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);
1463 state_machine_cancel(&publisher->state_header);
1469 service_publisher_t *ret = NULL, *publisher = calloc(1, sizeof(*publisher));
1470 if (publisher == NULL) {
1471 return publisher;
1473 RETAIN_HERE(publisher, service_publisher);
1474 publisher->wakeup_timer = ioloop_wakeup_create();
1475 if (publisher->wakeup_timer == NULL) {
1482 publisher->id = strdup(server_id_buf);
1483 if (publisher->id == NULL) {
1488 publisher->state_header,
1489 publisher, publisher->id,
1497 publisher->server_state = server_state;
1499 service_publisher_context_release, publisher))
1503 RETAIN_HERE(publisher, service_publisher); // for service tracker
1506 service_publisher_context_release, publisher))
1510 RETAIN_HERE(publisher, service_publisher); // for thread network state tracker
1513 service_publisher_context_release, publisher))
1517 RETAIN_HERE(publisher, service_publisher); // for thread network state tracker
1520 publisher->first_time = true;
1521 publisher->startup_delay_range = SERVICE_PUBLISHER_START_WAIT;
1522 ret = publisher;
1523 publisher = NULL;
1525 if (publisher != NULL) {
1526 RELEASE_HERE(publisher, service_publisher);
1534 service_publisher_t *publisher = context;
1538 if (publisher->reconnect_callback != NULL) {
1539 publisher->reconnect_callback(publisher->server_state);
1555 if (publisher->have_ml_eid && !in6addr_compare(&new_mesh_local_address, &publisher->thread_mesh_local_address)) {
1559 publisher->thread_mesh_local_address = new_mesh_local_address;
1560 publisher->have_ml_eid = true;
1562 for (thread_service_t *service = service_tracker_services_get(publisher->server_state->service_tracker);
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)))
1574 thread_service_note(publisher->id, service,
1576 service_publisher_unpublish_stale_service(publisher, service);
1588 state_machine_event_deliver(&publisher->state_header, event);
1590 RELEASE_HERE(publisher, service_publisher); // callback held a reference.
1593 RELEASE_HERE(publisher, service_publisher); // callback held a reference.
1594 publisher->have_ml_eid = false;
1601 service_publisher_t *publisher = context;
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;
1611 status = cti_get_mesh_local_address(publisher->server_state, publisher,
1616 RETAIN_HERE(publisher, service_publisher); // for mesh-local callback
1623 service_publisher_t *publisher = context;
1633 publisher->have_thread_interface_name = true;
1637 if (publisher->thread_interface_name != NULL) {
1638 if (!strcmp(name, publisher->thread_interface_name)) {
1641 free(publisher->thread_interface_name);
1642 publisher->thread_interface_name = NULL;
1648 publisher->thread_interface_name = strdup(name);
1653 if (publisher->thread_interface_name == NULL) {
1662 state_machine_event_deliver(&publisher->state_header, event);
1665 RELEASE_HERE(publisher, service_publisher); // callback held a reference.
1671 service_publisher_t *publisher = context;
1684 int ret = inet_pton(AF_INET6, ml_eid, &publisher->wed_ml_eid);
1695 if (publisher->wed_ext_address_string != NULL) {
1696 free(publisher->wed_ext_address_string);
1697 publisher->wed_ext_address_string = NULL;
1700 if (publisher->wed_ml_eid_string != NULL) {
1701 free(publisher->wed_ml_eid_string);
1702 publisher->wed_ml_eid_string = NULL;
1708 publisher->wed_ext_address_string = strdup(ea);
1709 if (publisher->wed_ext_address_string == NULL) {
1714 publisher->wed_ml_eid_string = strdup(mle);
1715 if (publisher->wed_ml_eid_string == NULL) {
1717 memset(&publisher->wed_ml_eid, 0, sizeof(publisher->wed_ml_eid));
1720 memset(&publisher->wed_ml_eid, 0, sizeof(publisher->wed_ml_eid));
1728 state_machine_event_deliver(&publisher->state_header, event);
1737 service_publisher_t *publisher = context;
1748 memset(&publisher->neighbor_ml_eid, 0, sizeof(publisher->neighbor_ml_eid));
1750 int ret = inet_pton(AF_INET6, ml_eid, &publisher->neighbor_ml_eid);
1763 if (publisher->neighbor_ml_eid_string != NULL) {
1764 free(publisher->neighbor_ml_eid_string);
1765 publisher->neighbor_ml_eid_string = NULL;
1769 publisher->neighbor_ml_eid_string = strdup(mle);
1770 if (publisher->neighbor_ml_eid_string == NULL) {
1772 memset(&publisher->neighbor_ml_eid, 0, sizeof(publisher->neighbor_ml_eid));
1775 memset(&publisher->neighbor_ml_eid, 0, sizeof(publisher->neighbor_ml_eid));
1782 state_machine_event_deliver(&publisher->state_header, event);
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;
1795 service_publisher_start(service_publisher_t *publisher)
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,
1803 RETAIN_HERE(publisher, service_publisher); // for active dataset callback
1806 status = cti_get_tunnel_name(publisher->server_state, publisher, service_publisher_tunnel_name_callback, NULL);
1810 RETAIN_HERE(publisher, service_publisher); // for tunnel name callback
1814 status = cti_track_wed_status(publisher->server_state, &publisher->wed_tracker_connection,
1815 publisher, service_publisher_wed_callback, NULL);
1819 RETAIN_HERE(publisher, service_publisher);
1822 status = cti_track_neighbor_ml_eid(publisher->server_state, &publisher->neighbor_tracker_connection,
1823 publisher, service_publisher_neighbor_callback, NULL);
1827 RETAIN_HERE(publisher, service_publisher);
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);
1835 service_publisher_get_ml_eid(service_publisher_t *publisher, struct in6_addr *ml_eid)
1837 if (publisher != NULL && publisher->have_ml_eid) {
1838 in6addr_copy(ml_eid, &publisher->thread_mesh_local_address);