// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

module netconnector;

import "lib/netstack/fidl/net_address.fidl";

// mDNS service interface.
[ServiceName="netconnector::MdnsService"]
interface MdnsService {
  // Gets the addresses for the specified host name. |host_name| may not end in
  // a '.'.
  ResolveHostName(string host_name, uint32 timeout_ms) =>
    (netstack.SocketAddress? v4_address, netstack.SocketAddress? v6_address);

  // Subscribes to a service. The subscription lasts until |subscription| is
  // unbound. |service_name| must end in '._tcp.' or '._udp.'.
  SubscribeToService(string service_name,
                     MdnsServiceSubscription& subscription);

  // Publishes a service instance available at the specified port. The service
  // is published until it is unpublished via |UnpublishServiceInstance|.
  // |service_name| must end in '._tcp.' or '._udp.'. |instance_name| must not
  // end in a '.'. |port| is host-endian. |text| contains metadata strings that
  // describe the instance. No subtypes are published unless the |SetSubtypes|
  // method is called.
  PublishServiceInstance(string service_name,
                         string instance_name,
                         uint16 port,
                         array<string>? text) => (MdnsResult result);

  // Ends publication started with |PublishServiceInstance|. |service_name| must
  // end in '._tcp.' or '._udp.'. |instance_name| must not end in a '.'.
  UnpublishServiceInstance(string service_name, string instance_name);

  // Publishes a service instance with support for subtypes. |service_name| must
  // end in '._tcp.' or '._udp.'. |instance_name| must not end in a '.'.
  // |responder| is consulted for initial announcements and to answer queries.
  // The service is published until the |responder| channel closes. In addition
  // to announcements and queries for the service type, all queries for subtypes
  // are answered subject to filtering through the |MdnsResponder|. If subtype
  // announcement is desired, a call to |SetSubtypes| is required to set the
  // list of announced subtypes.
  AddResponder(string service_name,
               string instance_name,
               MdnsResponder responder);

  // Sets the subtypes for a service instance currently being published due to
  // a call to |PublishServiceInstance| or |AddResponder|.  |service_name| must
  // end in '._tcp.' or '._udp.'. |instance_name| must not end in a '.'. For an
  // instance published with |PublishServiceInstance|, the specified subtypes
  // will be announced, and queries for the subtypes will be answered. For an
  // instance published with |AddResponder|, the specified subtypes will be
  // announced subject to filtering through the |MdnsResponder|. All subtype
  // queries are forwarded to the |MdnsResponder|, so this method has no effect
  // in that regard.
  SetSubtypes(string service_name,
              string instance_name,
              array<string> subtypes);

  // Initiates announcement of a service instance currently being published due
  // to a call to |PublishServiceInstance| or |AddResponder|. This is generally
  // not needed for the |PublishServiceInstance| case. For instances published
  // with |AddResponder|, this method is typically used when the port or text
  // associated with the instance changes. All announcements are filtered
  // through the |MdnsResponder|, which can reply with the new port and text
  // values.
  ReannounceInstance(string service_name, string instance_name);

  // Specifies whether mDNS traffic should be logged.
  SetVerbose(bool value);
};

// Result values for instance publishing.
enum MdnsResult {
  OK = 0,
  INVALID_SERVICE_NAME = -1,
  INVALID_INSTANCE_NAME = -2,
  ALREADY_PUBLISHED_LOCALLY = -3,
  ALREADY_PUBLISHED_ON_SUBNET = -4
};

// Represents a subscription.
interface MdnsServiceSubscription {
  // Special value for GetInstances version_last_seen parameter to get the
  // current instances immediately.
  const uint64 kInitialInstances = 0;

  // Gets the known service instances. To get the list immediately, call
  // |GetInstances(kInitialInstances)|. To get updates thereafter, pass the
  // version sent in the previous callback.
  GetInstances(uint64 version_last_seen) =>
    (uint64 version, array<MdnsServiceInstance> instances);
};

// Describes a service instance.
struct MdnsServiceInstance {
  string service_name;
  string instance_name;
  netstack.SocketAddress? v4_address;
  netstack.SocketAddress? v6_address;
  array<string>? text;
};

// Client-supplied responder interface.
interface MdnsResponder {
  // Updates the status of the instance publication.
  UpdateStatus(MdnsResult result);

  // Provides instance information for initial announcements and query responses
  // relating to the service instance specified in |MdnsService.AddResponder|.
  // |query| indicates whether data is requested for an initial announcement
  // (false) or in response to a query (true). If the publication relates to a
  // subtype of the service, |subtype| contains the subtype, otherwise it is
  // null. If |publication| is null, no announcement or response is transmitted.
  // Strings in |text| are transmitted in the TXT record.
  GetPublication(bool query, string? subtype) => (MdnsPublication? publication);
};

// Describes an initial instance publication or query response. |port| is host-
// endian.
struct MdnsPublication {
  uint16 port;
  array<string>? text;
  uint32 ptr_ttl_seconds = 4500; // default 75 minutes
  uint32 srv_ttl_seconds = 120; // default 2 minutes
  uint32 txt_ttl_seconds = 4500; // default 75 minutes
};
