Sunshine master
Self-hosted game stream host for Moonlight.
publish.cpp File Reference

Definitions for publishing services on Linux. More...

#include <thread>
#include "misc.h"
#include "src/logging.h"
#include "src/network.h"
#include "src/nvhttp.h"
#include "src/platform/common.h"
#include "src/utility.h"
Include dependency graph for publish.cpp:

Classes

class  platf::publish::deinit_t
 RAII helper that runs shutdown cleanup when destroyed. More...
 

Typedefs

typedef char *(* avahi::alternative_service_name_fn) (char *)
 Function pointer used to request an alternative Avahi service name.
 
typedef int(* avahi::client_errno_fn) (Client *)
 Function pointer used to read the last Avahi client error.
 
typedef void(* avahi::client_free_fn) (Client *)
 Function pointer used to destroy an Avahi client.
 
typedef Client *(* avahi::client_new_fn) (const Poll *poll_api, ClientFlags flags, ClientCallback callback, void *userdata, int *error)
 Function pointer used to create an Avahi client.
 
using platf::publish::client_t = util::dyn_safe_ptr<avahi::Client, &avahi::client_free>
 Owning pointer for an Avahi client.
 
typedef void(* avahi::ClientCallback) (Client *, ClientState, void *userdata)
 Avahi client state-change callback signature.
 
typedef int(* avahi::entry_group_add_service_fn) (EntryGroup *group, IfIndex interface, Protocol protocol, PublishFlags flags, const char *name, const char *type, const char *domain, const char *host, uint16_t port,...)
 Function pointer used to add a service to an Avahi entry group.
 
typedef int(* avahi::entry_group_commit_fn) (EntryGroup *)
 Function pointer used to publish an Avahi entry group.
 
typedef Client *(* avahi::entry_group_get_client_fn) (EntryGroup *)
 Function pointer used to get an Avahi client from an entry group.
 
typedef int(* avahi::entry_group_is_empty_fn) (EntryGroup *)
 Function pointer used to test whether an Avahi entry group is empty.
 
typedef EntryGroup *(* avahi::entry_group_new_fn) (Client *, EntryGroupCallback, void *userdata)
 Function pointer used to create an Avahi entry group.
 
typedef int(* avahi::entry_group_reset_fn) (EntryGroup *)
 Function pointer used to reset an Avahi entry group.
 
typedef void(* avahi::EntryGroupCallback) (EntryGroup *g, EntryGroupState state, void *userdata)
 Avahi entry-group state-change callback signature.
 
typedef void(* avahi::free_fn) (void *)
 Function pointer used to free Avahi-allocated memory.
 
using avahi::IfIndex = int
 Network interface index type used by Avahi.
 
using platf::publish::poll_t = util::dyn_safe_ptr<avahi::SimplePoll, &avahi::simple_poll_free>
 Owning pointer for an Avahi simple poll loop.
 
using avahi::Protocol = int
 Avahi protocol/address-family selector type.
 
template<class T >
using platf::publish::ptr_t = util::safe_ptr<T, free<T>>
 Owning pointer for Avahi allocations released with avahi_free.
 
typedef void(* avahi::simple_poll_free_fn) (SimplePoll *)
 Function pointer used to free an Avahi simple-poll instance.
 
typedef Poll *(* avahi::simple_poll_get_fn) (SimplePoll *)
 Function pointer used to get the Avahi simple-poll API.
 
typedef int(* avahi::simple_poll_loop_fn) (SimplePoll *)
 Function pointer used to run the Avahi simple-poll loop.
 
typedef SimplePoll *(* avahi::simple_poll_new_fn) ()
 Function pointer used to allocate an Avahi simple-poll instance.
 
typedef void(* avahi::simple_poll_quit_fn) (SimplePoll *)
 Function pointer used to stop the Avahi simple-poll loop.
 
typedef char *(* avahi::strdup_fn) (const char *)
 Function pointer used to duplicate Avahi strings.
 
typedef char *(* avahi::strerror_fn) (int)
 Function pointer used to format Avahi error codes.
 

Enumerations

enum  avahi::ClientFlags { avahi::CLIENT_IGNORE_USER_CONFIG = 1 , avahi::CLIENT_NO_FAIL = 2 }
 Enumerates supported client flags options. More...
 
enum  avahi::ClientState {
  avahi::CLIENT_S_REGISTERING = SERVER_REGISTERING , avahi::CLIENT_S_RUNNING = SERVER_RUNNING , avahi::CLIENT_S_COLLISION = SERVER_COLLISION , avahi::CLIENT_FAILURE = 100 ,
  avahi::CLIENT_CONNECTING = 101
}
 Enumerates supported client state options. More...
 
enum  avahi::EntryGroupState {
  avahi::ENTRY_GROUP_UNCOMMITED , avahi::ENTRY_GROUP_REGISTERING , avahi::ENTRY_GROUP_ESTABLISHED , avahi::ENTRY_GROUP_COLLISION ,
  avahi::ENTRY_GROUP_FAILURE
}
 Enumerates supported entry group state options. More...
 
enum  avahi::err_e {
  avahi::OK = 0 , avahi::ERR_FAILURE = -1 , avahi::ERR_BAD_STATE = -2 , avahi::ERR_INVALID_HOST_NAME = -3 ,
  avahi::ERR_INVALID_DOMAIN_NAME = -4 , avahi::ERR_NO_NETWORK = -5 , avahi::ERR_INVALID_TTL = -6 , avahi::ERR_IS_PATTERN = -7 ,
  avahi::ERR_COLLISION = -8 , avahi::ERR_INVALID_RECORD = -9 , avahi::ERR_INVALID_SERVICE_NAME = -10 , avahi::ERR_INVALID_SERVICE_TYPE = -11 ,
  avahi::ERR_INVALID_PORT = -12 , avahi::ERR_INVALID_KEY = -13 , avahi::ERR_INVALID_ADDRESS = -14 , avahi::ERR_TIMEOUT = -15 ,
  avahi::ERR_TOO_MANY_CLIENTS = -16 , avahi::ERR_TOO_MANY_OBJECTS = -17 , avahi::ERR_TOO_MANY_ENTRIES = -18 , avahi::ERR_OS = -19 ,
  avahi::ERR_ACCESS_DENIED = -20 , avahi::ERR_INVALID_OPERATION = -21 , avahi::ERR_DBUS_ERROR = -22 , avahi::ERR_DISCONNECTED = -23 ,
  avahi::ERR_NO_MEMORY = -24 , avahi::ERR_INVALID_OBJECT = -25 , avahi::ERR_NO_DAEMON = -26 , avahi::ERR_INVALID_INTERFACE = -27 ,
  avahi::ERR_INVALID_PROTOCOL = -28 , avahi::ERR_INVALID_FLAGS = -29 , avahi::ERR_NOT_FOUND = -30 , avahi::ERR_INVALID_CONFIG = -31 ,
  avahi::ERR_VERSION_MISMATCH = -32 , avahi::ERR_INVALID_SERVICE_SUBTYPE = -33 , avahi::ERR_INVALID_PACKET = -34 , avahi::ERR_INVALID_DNS_ERROR = -35 ,
  avahi::ERR_DNS_FORMERR = -36 , avahi::ERR_DNS_SERVFAIL = -37 , avahi::ERR_DNS_NXDOMAIN = -38 , avahi::ERR_DNS_NOTIMP = -39 ,
  avahi::ERR_DNS_REFUSED = -40 , avahi::ERR_DNS_YXDOMAIN = -41 , avahi::ERR_DNS_YXRRSET = -42 , avahi::ERR_DNS_NXRRSET = -43 ,
  avahi::ERR_DNS_NOTAUTH = -44 , avahi::ERR_DNS_NOTZONE = -45 , avahi::ERR_INVALID_RDATA = -46 , avahi::ERR_INVALID_DNS_CLASS = -47 ,
  avahi::ERR_INVALID_DNS_TYPE = -48 , avahi::ERR_NOT_SUPPORTED = -49 , avahi::ERR_NOT_PERMITTED = -50 , avahi::ERR_INVALID_ARGUMENT = -51 ,
  avahi::ERR_IS_EMPTY = -52 , avahi::ERR_NO_CHANGE = -53 , avahi::ERR_MAX = -54
}
 Error codes used by avahi. More...
 
enum  avahi::proto { avahi::PROTO_INET = 0 , avahi::PROTO_INET6 = 1 , avahi::PROTO_UNSPEC = -1 }
 Enumerates supported proto options. More...
 
enum  avahi::PublishFlags {
  avahi::PUBLISH_UNIQUE = 1 , avahi::PUBLISH_NO_PROBE = 2 , avahi::PUBLISH_NO_ANNOUNCE = 4 , avahi::PUBLISH_ALLOW_MULTIPLE = 8 ,
  avahi::PUBLISH_NO_REVERSE = 16 , avahi::PUBLISH_NO_COOKIE = 32 , avahi::PUBLISH_UPDATE = 64 , avahi::PUBLISH_USE_WIDE_AREA = 128 ,
  avahi::PUBLISH_USE_MULTICAST = 256
}
 Flags for publishing functions. More...
 
enum  avahi::ServerState {
  avahi::SERVER_INVALID , avahi::SERVER_REGISTERING , avahi::SERVER_RUNNING , avahi::SERVER_COLLISION ,
  avahi::SERVER_FAILURE
}
 Enumerates supported server state options. More...
 

Functions

void platf::publish::client_callback (avahi::Client *c, avahi::ClientState state, void *)
 React to Avahi client state changes and register services when ready.
 
void platf::publish::create_services (avahi::Client *c)
 Create or update the Avahi service entry group.
 
void platf::publish::entry_group_callback (avahi::EntryGroup *g, avahi::EntryGroupState state, void *)
 React to Avahi entry-group state changes.
 
template<class T >
void platf::publish::free (T *p)
 Release memory allocated by Avahi.
 
int avahi::init_client ()
 Load Avahi threaded-poll and client function pointers.
 
int avahi::init_common ()
 Load common Avahi client and entry-group function pointers.
 
std::unique_ptr< deinit_tplatf::publish::start ()
 Main entry point for publication of our service on macOS.
 

Variables

alternative_service_name_fn avahi::alternative_service_name
 Alternative service name.
 
client_t platf::publish::client
 Avahi client used to register the Sunshine service.
 
client_errno_fn avahi::client_errno
 Client errno.
 
client_free_fn avahi::client_free
 Client free.
 
client_new_fn avahi::client_new
 Client new.
 
entry_group_add_service_fn avahi::entry_group_add_service
 Entry group add service.
 
entry_group_commit_fn avahi::entry_group_commit
 Entry group commit.
 
entry_group_get_client_fn avahi::entry_group_get_client
 Entry group get client.
 
entry_group_is_empty_fn avahi::entry_group_is_empty
 Entry group is empty.
 
entry_group_new_fn avahi::entry_group_new
 Entry group new.
 
entry_group_reset_fn avahi::entry_group_reset
 Entry group reset.
 
free_fn avahi::free
 Free.
 
avahi::EntryGroup * platf::publish::group = nullptr
 Active Avahi entry group that owns the published service.
 
constexpr auto avahi::IF_UNSPEC = -1
 Protocol or platform constant for if unspec.
 
ptr_t< char > platf::publish::name
 Current service name, updated when Avahi reports a collision.
 
poll_t platf::publish::poll
 Avahi poll loop used while the service is published.
 
simple_poll_free_fn avahi::simple_poll_free
 Simple poll free.
 
simple_poll_get_fn avahi::simple_poll_get
 Simple poll get.
 
simple_poll_loop_fn avahi::simple_poll_loop
 Simple poll loop.
 
simple_poll_new_fn avahi::simple_poll_new
 Simple poll new.
 
simple_poll_quit_fn avahi::simple_poll_quit
 Simple poll quit.
 
strdup_fn avahi::strdup
 Strdup.
 
strerror_fn avahi::strerror
 Strerror.
 

Detailed Description

Definitions for publishing services on Linux.

Note
Adapted from https://www.avahi.org/doxygen/html/client-publish-service_8c-example.html

Enumeration Type Documentation

◆ ClientFlags

Enumerates supported client flags options.

Enumerator
CLIENT_IGNORE_USER_CONFIG 

Don't read user configuration.

CLIENT_NO_FAIL 

Don't fail if the daemon is not available when avahi_client_new() is called, instead enter CLIENT_CONNECTING state and wait for the daemon to appear.

◆ ClientState

Enumerates supported client state options.

Enumerator
CLIENT_S_REGISTERING 

Server state: REGISTERING.

CLIENT_S_RUNNING 

Server state: RUNNING.

CLIENT_S_COLLISION 

Server state: COLLISION.

CLIENT_FAILURE 

Some kind of error happened on the client side.

CLIENT_CONNECTING 

We're still connecting. This state is only entered when AVAHI_CLIENT_NO_FAIL has been passed to avahi_client_new() and the daemon is not yet available.

◆ EntryGroupState

Enumerates supported entry group state options.

Enumerator
ENTRY_GROUP_UNCOMMITED 

The group has not yet been committed, the user must still call avahi_entry_group_commit()

ENTRY_GROUP_REGISTERING 

The entries of the group are currently being registered.

ENTRY_GROUP_ESTABLISHED 

The entries have successfully been established.

ENTRY_GROUP_COLLISION 

A name collision for one of the entries in the group has been detected, the entries have been withdrawn.

ENTRY_GROUP_FAILURE 

Some kind of failure happened, the entries have been withdrawn.

◆ err_e

Error codes used by avahi.

Enumerator
OK 

OK.

ERR_FAILURE 

Generic error code.

ERR_BAD_STATE 

Object was in a bad state.

ERR_INVALID_HOST_NAME 

Invalid host name.

ERR_INVALID_DOMAIN_NAME 

Invalid domain name.

ERR_NO_NETWORK 

No suitable network protocol available.

ERR_INVALID_TTL 

Invalid DNS TTL.

ERR_IS_PATTERN 

RR key is pattern.

ERR_COLLISION 

Name collision.

ERR_INVALID_RECORD 

Invalid RR.

ERR_INVALID_SERVICE_NAME 

Invalid service name.

ERR_INVALID_SERVICE_TYPE 

Invalid service type.

ERR_INVALID_PORT 

Invalid port number.

ERR_INVALID_KEY 

Invalid key.

ERR_INVALID_ADDRESS 

Invalid address.

ERR_TIMEOUT 

Timeout reached.

ERR_TOO_MANY_CLIENTS 

Too many clients.

ERR_TOO_MANY_OBJECTS 

Too many objects.

ERR_TOO_MANY_ENTRIES 

Too many entries.

ERR_OS 

OS error.

ERR_ACCESS_DENIED 

Access denied.

ERR_INVALID_OPERATION 

Invalid operation.

ERR_DBUS_ERROR 

An unexpected D-Bus error occurred.

ERR_DISCONNECTED 

Daemon connection failed.

ERR_NO_MEMORY 

Memory exhausted.

ERR_INVALID_OBJECT 

The object passed to this function was invalid.

ERR_NO_DAEMON 

Daemon not running.

ERR_INVALID_INTERFACE 

Invalid interface.

ERR_INVALID_PROTOCOL 

Invalid protocol.

ERR_INVALID_FLAGS 

Invalid flags.

ERR_NOT_FOUND 

Not found.

ERR_INVALID_CONFIG 

Configuration error.

ERR_VERSION_MISMATCH 

Version mismatch.

ERR_INVALID_SERVICE_SUBTYPE 

Invalid service subtype.

ERR_INVALID_PACKET 

Invalid packet.

ERR_INVALID_DNS_ERROR 

Invalid DNS return code.

ERR_DNS_FORMERR 

DNS Error: Form error.

ERR_DNS_SERVFAIL 

DNS Error: Server Failure.

ERR_DNS_NXDOMAIN 

DNS Error: No such domain.

ERR_DNS_NOTIMP 

DNS Error: Not implemented.

ERR_DNS_REFUSED 

DNS Error: Operation refused.

ERR_DNS_YXDOMAIN 

TODO.

ERR_DNS_YXRRSET 

TODO.

ERR_DNS_NXRRSET 

TODO.

ERR_DNS_NOTAUTH 

DNS Error: Not authorized.

ERR_DNS_NOTZONE 

TODO.

ERR_INVALID_RDATA 

Invalid RDATA.

ERR_INVALID_DNS_CLASS 

Invalid DNS class.

ERR_INVALID_DNS_TYPE 

Invalid DNS type.

ERR_NOT_SUPPORTED 

Not supported.

ERR_NOT_PERMITTED 

Operation not permitted.

ERR_INVALID_ARGUMENT 

Invalid argument.

ERR_IS_EMPTY 

Is empty.

ERR_NO_CHANGE 

The requested operation is invalid because it is redundant.

ERR_MAX 

TODO.

◆ proto

Enumerates supported proto options.

Enumerator
PROTO_INET 

IPv4.

PROTO_INET6 

IPv6.

PROTO_UNSPEC 

Unspecified/all protocol(s)

◆ PublishFlags

Flags for publishing functions.

Enumerator
PUBLISH_UNIQUE 

For raw records: The RRset is intended to be unique.

PUBLISH_NO_PROBE 

For raw records: Though the RRset is intended to be unique no probes shall be sent.

PUBLISH_NO_ANNOUNCE 

For raw records: Do not announce this RR to other hosts.

PUBLISH_ALLOW_MULTIPLE 

For raw records: Allow multiple local records of this type, even if they are intended to be unique.

PUBLISH_NO_REVERSE 

For address records: don't create a reverse (PTR) entry.

PUBLISH_NO_COOKIE 

For service records: do not implicitly add the local service cookie to TXT data.

PUBLISH_UPDATE 

Update existing records instead of adding new ones.

PUBLISH_USE_WIDE_AREA 

Register the record using wide area DNS (i.e. unicast DNS update)

PUBLISH_USE_MULTICAST 

Register the record using multicast DNS.

◆ ServerState

Enumerates supported server state options.

Enumerator
SERVER_INVALID 

Invalid state (initial)

SERVER_REGISTERING 

Host RRs are being registered.

SERVER_RUNNING 

All host RRs have been established.

SERVER_COLLISION 

There is a collision with a host RR. All host RRs have been withdrawn, the user should set a new host name via avahi_server_set_host_name()

SERVER_FAILURE 

Some fatal failure happened, the server is unable to proceed.

Function Documentation

◆ client_callback()

void platf::publish::client_callback ( avahi::Client * c,
avahi::ClientState state,
void *  )

React to Avahi client state changes and register services when ready.

Parameters
cAvahi client that emitted the state change.
stateAvahi client state reported by the callback.

◆ create_services()

void platf::publish::create_services ( avahi::Client * c)

Create or update the Avahi service entry group.

Publish Sunshine's mDNS service through Avahi.

Parameters
cAvahi client used to allocate and commit the service entry group.

◆ entry_group_callback()

void platf::publish::entry_group_callback ( avahi::EntryGroup * g,
avahi::EntryGroupState state,
void *  )

React to Avahi entry-group state changes.

Parameters
gEntry group that emitted the state change.
stateAvahi entry-group state reported by the callback.

◆ free()

template<class T >
void platf::publish::free ( T * p)

Release memory allocated by Avahi.

Parameters
pAvahi-allocated pointer to release.

◆ init_client()

int avahi::init_client ( )

Load Avahi threaded-poll and client function pointers.

Returns
0 when all client functions are available; nonzero otherwise.

◆ init_common()

int avahi::init_common ( )

Load common Avahi client and entry-group function pointers.

Returns
0 when common Avahi functions are available; nonzero otherwise.

◆ start()

std::unique_ptr<::platf::deinit_t > platf::publish::start ( )
nodiscard

Main entry point for publication of our service on macOS.

This function initiates a connection to the macOS mDNS service and requests to register our Sunshine service. Registration will occur asynchronously (unless it fails immediately, which is probably only possible if the host machine is misconfigured).

Returns
Either nullptr (if the registration fails immediately) or a uniqur_ptr<deinit_t>, which will manage polling for a response from the mDNS service, and then, when deconstructed, will deregister the service.