+sw_result sw_salt_lock(sw_salt self) {
+ AVAHI_WARN_LINKAGE;
+
+ assert(self);
+ ASSERT_SUCCESS(pthread_mutex_lock(&((sw_discovery) self)->salt_mutex));
+
+ return SW_OKAY;
+}
+
+sw_result sw_salt_unlock(sw_salt self) {
+ assert(self);
+
+ AVAHI_WARN_LINKAGE;
+
+ ASSERT_SUCCESS(pthread_mutex_unlock(&((sw_discovery) self)->salt_mutex));
+
+ return SW_OKAY;
+}
+
+static void reg_report_status(oid_data *data, sw_discovery_publish_status status) {
+ sw_discovery_publish_reply reply;
+
+ assert(data);
+
+ reply = (sw_discovery_publish_reply) data->reply;
+
+ reply(data->discovery,
+ OID_GET_INDEX(data),
+ status,
+ data->extra);
+}
+
+static int reg_create_service(oid_data *data) {
+ int ret;
+ const char *real_type;
+
+ assert(data);
+
+ real_type = avahi_get_type_from_subtype(data->service_data->regtype);
+
+ if ((ret = avahi_entry_group_add_service_strlst(
+ data->object,
+ data->service_data->interface,
+ AVAHI_PROTO_INET,
+ 0,
+ data->service_data->name,
+ real_type ? real_type : data->service_data->regtype,
+ data->service_data->domain,
+ data->service_data->host,
+ data->service_data->port,
+ data->service_data->txt)) < 0)
+ return ret;
+
+ if (real_type) {
+ /* Create a subtype entry */
+
+ if (avahi_entry_group_add_service_subtype(
+ data->object,
+ data->service_data->interface,
+ AVAHI_PROTO_INET,
+ 0,
+ data->service_data->name,
+ real_type,
+ data->service_data->domain,
+ data->service_data->regtype) < 0)
+ return ret;
+
+ }
+
+ if ((ret = avahi_entry_group_commit(data->object)) < 0)
+ return ret;
+
+ return 0;
+}
+
+static void reg_client_callback(oid_data *data, AvahiClientState state) {
+ assert(data);
+
+ /* We've not been setup completely */
+ if (!data->object)
+ return;
+
+ switch (state) {
+ case AVAHI_CLIENT_FAILURE:
+ reg_report_status(data, SW_DISCOVERY_PUBLISH_INVALID);
+ break;
+
+ case AVAHI_CLIENT_S_RUNNING: {
+ int ret;
+
+ /* Register the service */
+ if ((ret = reg_create_service(data)) < 0) {
+ reg_report_status(data, SW_DISCOVERY_PUBLISH_INVALID);
+ return;
+ }
+
+ break;
+ }
+
+ case AVAHI_CLIENT_S_COLLISION:
+
+ /* Remove our entry */
+ avahi_entry_group_reset(data->object);
+ break;
+
+ case AVAHI_CLIENT_CONNECTING:
+ case AVAHI_CLIENT_S_REGISTERING:
+ /* Ignore */
+ break;
+ }
+
+}
+
+static void reg_entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) {
+ oid_data *data = userdata;
+
+ assert(g);
+ assert(data);
+
+ switch (state) {
+ case AVAHI_ENTRY_GROUP_ESTABLISHED:
+
+ reg_report_status(data, SW_DISCOVERY_PUBLISH_STARTED);
+ break;
+
+ case AVAHI_ENTRY_GROUP_COLLISION:
+
+ reg_report_status(data, SW_DISCOVERY_PUBLISH_NAME_COLLISION);
+ break;
+
+ case AVAHI_ENTRY_GROUP_REGISTERING:
+ case AVAHI_ENTRY_GROUP_UNCOMMITED:
+ /* Ignore */
+ break;
+
+ case AVAHI_ENTRY_GROUP_FAILURE:
+ reg_report_status(data, SW_DISCOVERY_PUBLISH_INVALID);
+ break;
+
+ }
+}
+