////
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
*  KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
////
= Zero configure service discovery

The `Discovery_zeroconf` is implemented based on mDNS, and its operation depends on the mDNS daemon.

The mapping between celix and mdns services is as follows:

|===
|*mDNS service*|*celix service*
|instance name|service name+hash(endpoint uuid)
|service type|"_celix-rpc._udp"+<custom subtype>
|domain name|"local"
|txt record|service properties
|host|"celix_rpc_dumb_host.local."
|port|50009
|===

Because We will perform the mDNS query only using link-local multicast, so we set domain name default value "local".

To reduce the operation of conversion between host name and address info. we set the address info to txt record, and set a dummy value("celix_rpc_dumb_host.local." and "50009") to the host name and port.

According to rfc6763 6.1 and 6.2 section, DNS TXT record can be up to 65535 (0xFFFF) bytes long in mDNS message. and we should keep the size of the TXT record under 1300 bytes(allowing it to fit in a single 1500-byte Ethernet packet). Therefore, `Discovery_zeroconf` announce celix service endpoint using multiple txt records and each txt record max size is 1300 bytes.

== Sequence Diagram
=== Service announce

[plantuml]
----
@startuml

box server process
participant Announcer
control AnnouncerThread
participant Fw
participant mDNS_deamon
end box
Announcer->Fw:register endpoint listener service
create AnnouncerThread
Announcer ->AnnouncerThread:
==setup==
--\Announcer: add endpoint\n (use endpoint listener service)
loop
    alt mDNS server disconnect
        AnnouncerThread->mDNS_deamon:DNSServiceCreateConnection
        return DNSServiceRef
    end alt
    alt Have new endpoint
        AnnouncerThread->AnnouncerThread:Converting endpoint properties to txt records(max 1300 bytes)
        AnnouncerThread->mDNS_deamon:DNSServiceRegister(DNSServiceRef,instanceName, txtRecord ...)
        return registerRef
        loop Have more endpoint properties
            AnnouncerThread->mDNS_deamon:DNSServiceAddRecord(registerRef, txtRecord ...)
        end loop
    end alt
end loop

@enduml
----


=== Service watcher

[plantuml]
----
@startuml

box client process
participant Watcher
control WatcherThread
participant Fw
participant mDNS_deamon
end box
Watcher->Fw:Register endpoint listener service tracker.\n(filter:"(!(DISCOVERY=true))")
create WatcherThread
Watcher ->WatcherThread:
==setup==
loop
    alt mDNS server disconnect
        WatcherThread->mDNS_deamon:DNSServiceCreateConnection
        return DNSServiceRef
    end alt
    alt browser is null
        WatcherThread->mDNS_deamon:DNSServiceBrowse(DNSServiceRef,anyInterface, "_celix-rpc._udp", "local"...)
    end alt
    mDNS_deamon-->WatcherThread:Service instances browsed
    alt Have new service instance \n or resolve service timeout
        WatcherThread->mDNS_deamon:DNSServiceResolve
    end
    mDNS_deamon-->WatcherThread:txt records
    WatcherThread->WatcherThread:Converting txt records to endpoint properties
    alt resolve completed
        WatcherThread->WatcherThread:Inform new endpoints to tpm (use endpoint listener service)
    end alt
    WatcherThread->WatcherThread:Remove expired endpoints(use endpoint listener service)
    note left
        If the service has been deleted for 10 seconds,
        we consider the endpoint to be expired.
    end note
end loop

@enduml
----


== Legacy issues
[caption="Issue 1: "]
.If a network interface restart, discovery_zeroconf_watcher cannot discovery services bound to the interface's again.
====
In mdnsresponder, if an interface restart, the interface object will be change(the interface index remains the same), which will result in services previously bound to the interface's mDNSInterfaceID(a pointer to interface object) will not being discovered again.

We will resolve it in https://github.com/conan-io/conan-center-index/pull/16254
====
