Skip to content
Shiny.NET

Discovery

NuGet package Shiny.AppDeviceBridge.Discovery

The discovery bridge finds and advertises services on the local network over mDNS/Bonjour, SSDP/UPnP and WS-Discovery, backed by Shiny.Net.Discovery.

Terminal window
dotnet add package Shiny.AppDeviceBridge.Discovery
builder.UseAppDeviceBridge(
bridge => bridge.AddDiscoveryBridge(DiscoveryProtocols.All),
webApp => { /* … */ }
);
Client C# TypeScript
IDiscoveryBridge AddDiscoveryBridgeClient() DiscoveryBridge
Topic Details
Searching search returns everything seen during scanMs, 5 s by default and 30 s at most.
Browsing each browse streams results as discovery.mdns, discovery.ssdp or discovery.wsd, so listen to that event first; without a listener it answers 409. At most 8 run at once, and a protocol’s browses stop once nothing listens to its event.
Publishing publications keep advertising until deleted. At most 16.
Platform setup on iOS and Mac Catalyst, list every browsed service type in NSBonjourServices and set NSLocalNetworkUsageDescription. On Android, SSDP and WS-Discovery need CHANGE_WIFI_MULTICAST_STATE.

A search collects answers for scanMs and returns them; a browse keeps going and streams them as events until you stop it or nothing listens any more.

import { DiscoveryBridge } from "@shinyorg/appdevicebridge";
const discovery = new DiscoveryBridge();
// one-shot: every printer that answers within 3 seconds
const printers = await discovery.searchMdns({ serviceType: "_ipp._tcp", resolveServices: true, scanMs: 3000 });
// continuous: services as they come and go
await discovery.onMdns(r => r.status === "Found" ? add(r.service) : remove(r.service));
const browse = await discovery.browseMdns({ serviceType: "_http._tcp" });
// later
await discovery.stopBrowse(browse.id);
POST/_bridge/discovery/mdns/search#

The mDNS services seen during the scan window, less any that went away.

C#IDiscoveryBridge.SearchMdnsAsyncTSDiscoveryBridge.searchMdns
Body
application/json · MdnsSearchRequest
MdnsSearchRequest · 4 fields
serviceTypestringSuch as _http._tcp.
domainstring | nulllocal. when null.
resolveServicesbooleanResolve host, port, addresses and TXT records for each service found.
scanMsnumber | nullA search's window, 250–30,000 ms; 5 seconds when null. Ignored by a browse.
Response
200 MdnsService[]
MdnsService · 9 fields
instanceNamestring
serviceTypestring
domainstring
fullNamestring
hostNamestring | null
portnumber
addressesstring[]
txtRecordsRecord<string, string>
isResolvedboolean
POST/_bridge/discovery/mdns/browse#

Browses for mDNS services; results arrive through onMdns.

C#IDiscoveryBridge.BrowseMdnsAsyncTSDiscoveryBridge.browseMdns
Body
application/json · MdnsSearchRequest
MdnsSearchRequest · 4 fields
serviceTypestringSuch as _http._tcp.
domainstring | nulllocal. when null.
resolveServicesbooleanResolve host, port, addresses and TXT records for each service found.
scanMsnumber | nullA search's window, 250–30,000 ms; 5 seconds when null. Ignored by a browse.
Response
200 DiscoveryBrowse
DiscoveryBrowse · 3 fields
idstring
protocolDiscoveryProtocol
targetstringWhat is being browsed for: a service type, search target or type list.
GET/_bridge/discovery/mdns/resolve#

Resolves one mDNS service. Fails with 404 when it does not answer.

C#IDiscoveryBridge.ResolveMdnsAsyncTSDiscoveryBridge.resolveMdns
ParameterInType
instanceNamequerystringrequired
serviceTypequerystringrequired
timeoutMsquerynumber | nulloptional
Response
200 MdnsService
MdnsService · 9 fields
instanceNamestring
serviceTypestring
domainstring
fullNamestring
hostNamestring | null
portnumber
addressesstring[]
txtRecordsRecord<string, string>
isResolvedboolean
Errors
404Not found
POST/_bridge/discovery/mdns/publications#

Advertises a service over mDNS. On iOS the type must be listed in NSBonjourServices.

C#IDiscoveryBridge.PublishMdnsAsyncTSDiscoveryBridge.publishMdns
Body
application/json · MdnsPublishRequest
MdnsPublishRequest · 5 fields
instanceNamestring
serviceTypestring
portnumber1–65535.
domainstring | null
txtRecordsRecord<string, string> | null
Response
200 DiscoveryPublication
DiscoveryPublication · 3 fields
idstring
protocolDiscoveryProtocol
namestringThe name in use, which mDNS may have changed to settle a conflict on the network.
POST/_bridge/discovery/ssdp/search#

The UPnP devices seen during the scan window, less any that went away.

C#IDiscoveryBridge.SearchSsdpAsyncTSDiscoveryBridge.searchSsdp
Body
application/json · SsdpSearchRequest
SsdpSearchRequest · 3 fields
searchTargetstring | nullssdp:all when null.
scanMsnumber | nullA search's window, 250–30,000 ms; 5 seconds when null. Ignored by a browse.
maxWaitMsnumber | nullHow long devices may wait before answering, 1,000–5,000 ms.
Response
200 SsdpDevice[]
SsdpDevice · 9 fields
udnstring
locationstring | null
serverstring | null
notificationTypesstring[]
sourceAddressstring | null
isRootDeviceboolean
deviceTypestring | null
serviceTypesstring[]
headersRecord<string, string>
POST/_bridge/discovery/ssdp/browse#

Browses for UPnP devices; results arrive through onSsdp.

C#IDiscoveryBridge.BrowseSsdpAsyncTSDiscoveryBridge.browseSsdp
Body
application/json · SsdpSearchRequest
SsdpSearchRequest · 3 fields
searchTargetstring | nullssdp:all when null.
scanMsnumber | nullA search's window, 250–30,000 ms; 5 seconds when null. Ignored by a browse.
maxWaitMsnumber | nullHow long devices may wait before answering, 1,000–5,000 ms.
Response
200 DiscoveryBrowse
DiscoveryBrowse · 3 fields
idstring
protocolDiscoveryProtocol
targetstringWhat is being browsed for: a service type, search target or type list.
GET/_bridge/discovery/ssdp/description#

A device's UPnP description. The device must have been seen by a search or browse first; otherwise 404.

C#IDiscoveryBridge.GetSsdpDescriptionAsyncTSDiscoveryBridge.getSsdpDescription
ParameterInType
udnquerystringrequired
Response
200 UpnpDeviceDescription
UpnpDeviceDescription · 15 fields
udnstring | null
deviceTypestring | null
friendlyNamestring | null
manufacturerstring | null
manufacturerUrlstring | null
modelNamestring | null
modelNumberstring | null
modelDescriptionstring | null
modelUrlstring | null
serialNumberstring | null
upcstring | null
presentationUrlstring | null
iconsUpnpIcon[]
servicesUpnpService[]
devicesUpnpDeviceDescription[]
Errors
404Not found
POST/_bridge/discovery/ssdp/publications#

Advertises a device over SSDP.

C#IDiscoveryBridge.PublishSsdpAsyncTSDiscoveryBridge.publishSsdp
Body
application/json · SsdpPublishRequest
SsdpPublishRequest · 7 fields
udnstring
locationstringThe absolute URL of the device description XML.
deviceTypestring | null
serviceTypesstring[] | null
isRootDeviceboolean
maxAgeSecondsnumber | null
serverstring | null
Response
200 DiscoveryPublication
DiscoveryPublication · 3 fields
idstring
protocolDiscoveryProtocol
namestringThe name in use, which mDNS may have changed to settle a conflict on the network.
POST/_bridge/discovery/wsd/search#

The WS-Discovery targets seen during the scan window, less any that went away.

C#IDiscoveryBridge.SearchWsdAsyncTSDiscoveryBridge.searchWsd
Body
application/json · WsdSearchRequest
WsdSearchRequest · 5 fields
typesWsdQualifiedName[] | null
scopesstring[] | null
scopeMatchBystring | null
profilesWsDiscoveryProfile
scanMsnumber | nullA search's window, 250–30,000 ms; 5 seconds when null. Ignored by a browse.
Response
200 WsdTarget[]
WsdTarget · 9 fields
endpointReferencestring
typesWsdQualifiedName[]
scopesstring[]
addressesstring[]
preferredAddressstring | null
metadataVersionnumber
sourceAddressstring | null
profileWsDiscoveryProfile
isOnvifCameraboolean
POST/_bridge/discovery/wsd/browse#

Browses for WS-Discovery targets; results arrive through onWsd.

C#IDiscoveryBridge.BrowseWsdAsyncTSDiscoveryBridge.browseWsd
Body
application/json · WsdSearchRequest
WsdSearchRequest · 5 fields
typesWsdQualifiedName[] | null
scopesstring[] | null
scopeMatchBystring | null
profilesWsDiscoveryProfile
scanMsnumber | nullA search's window, 250–30,000 ms; 5 seconds when null. Ignored by a browse.
Response
200 DiscoveryBrowse
DiscoveryBrowse · 3 fields
idstring
protocolDiscoveryProtocol
targetstringWhat is being browsed for: a service type, search target or type list.
GET/_bridge/discovery/wsd/resolve#

Resolves one WS-Discovery target. Fails with 404 when it does not answer.

C#IDiscoveryBridge.ResolveWsdAsyncTSDiscoveryBridge.resolveWsd
ParameterInType
endpointReferencequerystringrequired
timeoutMsquerynumber | nulloptional
Response
200 WsdTarget
WsdTarget · 9 fields
endpointReferencestring
typesWsdQualifiedName[]
scopesstring[]
addressesstring[]
preferredAddressstring | null
metadataVersionnumber
sourceAddressstring | null
profileWsDiscoveryProfile
isOnvifCameraboolean
Errors
404Not found
POST/_bridge/discovery/wsd/publications#

Advertises a target over WS-Discovery.

C#IDiscoveryBridge.PublishWsdAsyncTSDiscoveryBridge.publishWsd
Body
application/json · WsdPublishRequest
WsdPublishRequest · 6 fields
endpointReferencestring
typesWsdQualifiedName[] | null
scopesstring[] | null
addressesstring[] | nullAbsolute URLs the target answers at.
metadataVersionnumber
profilesWsDiscoveryProfile
Response
200 DiscoveryPublication
DiscoveryPublication · 3 fields
idstring
protocolDiscoveryProtocol
namestringThe name in use, which mDNS may have changed to settle a conflict on the network.
GET/_bridge/discovery/browses#

The running browses.

C#IDiscoveryBridge.GetBrowsesAsyncTSDiscoveryBridge.getBrowses
Response
200 DiscoveryBrowse[]
DiscoveryBrowse · 3 fields
idstring
protocolDiscoveryProtocol
targetstringWhat is being browsed for: a service type, search target or type list.
DELETE/_bridge/discovery/browses/{id}#

Stops a browse.

C#IDiscoveryBridge.StopBrowseAsyncTSDiscoveryBridge.stopBrowse
ParameterInType
idpathstringrequired
Response
204 No content
GET/_bridge/discovery/publications#

The active publications.

C#IDiscoveryBridge.GetPublicationsAsyncTSDiscoveryBridge.getPublications
Response
200 DiscoveryPublication[]
DiscoveryPublication · 3 fields
idstring
protocolDiscoveryProtocol
namestringThe name in use, which mDNS may have changed to settle a conflict on the network.
DELETE/_bridge/discovery/publications/{id}#

Stops advertising, sending a goodbye so it vanishes from other devices straight away.

C#IDiscoveryBridge.UnpublishAsyncTSDiscoveryBridge.unpublish
ParameterInType
idpathstringrequired
Response
204 No content
EVENTdiscovery.error#

A browse failed; onStopped follows.

C#IDiscoveryBridge.OnErrorAsyncTSDiscoveryBridge.onError
Payload
DiscoveryError
browseIdstring
protocolDiscoveryProtocol
messagestring
EVENTdiscovery.stopped#

A browse ended.

C#IDiscoveryBridge.OnStoppedAsyncTSDiscoveryBridge.onStopped
Payload
DiscoveryBrowse
idstring
protocolDiscoveryProtocol
targetstringWhat is being browsed for: a service type, search target or type list.

JSON property names are camelCase and enums travel as their names. A ? marks a property the payload may omit;| null one that may be null.

MdnsSearchRequestobject#
serviceTypestringSuch as _http._tcp.
domain?string | nulllocal. when null.
resolveServices?booleanResolve host, port, addresses and TXT records for each service found.
scanMs?number | nullA search's window, 250–30,000 ms; 5 seconds when null. Ignored by a browse.
MdnsServiceobject#
instanceNamestring
serviceTypestring
domainstring
fullNamestring
hostNamestring | null
portnumber
addressesstring[]
txtRecordsRecord<string, string>
isResolvedboolean
DiscoveryBrowseobject#
idstring
protocolDiscoveryProtocol
targetstringWhat is being browsed for: a service type, search target or type list.
DiscoveryProtocolenum#
"Mdns""Ssdp""Wsd"
MdnsPublishRequestobject#
instanceNamestring
serviceTypestring
portnumber1–65535.
domain?string | null
txtRecords?Record<string, string> | null
DiscoveryPublicationobject#
idstring
protocolDiscoveryProtocol
namestringThe name in use, which mDNS may have changed to settle a conflict on the network.
SsdpSearchRequestobject#
searchTarget?string | nullssdp:all when null.
scanMs?number | nullA search's window, 250–30,000 ms; 5 seconds when null. Ignored by a browse.
maxWaitMs?number | nullHow long devices may wait before answering, 1,000–5,000 ms.
SsdpDeviceobject#
udnstring
locationstring | null
serverstring | null
notificationTypesstring[]
sourceAddressstring | null
isRootDeviceboolean
deviceTypestring | null
serviceTypesstring[]
headersRecord<string, string>
UpnpDeviceDescriptionobject#

A device's UPnP description, with its embedded devices.

udnstring | null
deviceTypestring | null
friendlyNamestring | null
manufacturerstring | null
manufacturerUrlstring | null
modelNamestring | null
modelNumberstring | null
modelDescriptionstring | null
modelUrlstring | null
serialNumberstring | null
upcstring | null
presentationUrlstring | null
iconsUpnpIcon[]
servicesUpnpService[]
devicesUpnpDeviceDescription[]
UpnpIconobject#
mimeTypestring | null
widthnumber
heightnumber
depthnumber
urlstring | null
UpnpServiceobject#
serviceTypestring | null
serviceIdstring | null
scpdUrlstring | null
controlUrlstring | null
eventSubscriptionUrlstring | null
SsdpPublishRequestobject#
udnstring
locationstringThe absolute URL of the device description XML.
deviceType?string | null
serviceTypes?string[] | null
isRootDevice?boolean
maxAgeSeconds?number | null
server?string | null
WsdSearchRequestobject#
types?WsdQualifiedName[] | null
scopes?string[] | null
scopeMatchBy?string | null
profiles?WsDiscoveryProfile
scanMs?number | nullA search's window, 250–30,000 ms; 5 seconds when null. Ignored by a browse.
WsdQualifiedNameobject#

An XML qualified name, since WS-Discovery types are namespaced XML names.

namestring
namespacestring
WsDiscoveryProfileenum#
"None""Ws2005""Ws2009""All"
WsdTargetobject#
endpointReferencestring
typesWsdQualifiedName[]
scopesstring[]
addressesstring[]
preferredAddressstring | null
metadataVersionnumber
sourceAddressstring | null
profileWsDiscoveryProfile
isOnvifCameraboolean
WsdPublishRequestobject#
endpointReferencestring
types?WsdQualifiedName[] | null
scopes?string[] | null
addresses?string[] | nullAbsolute URLs the target answers at.
metadataVersion?number
profiles?WsDiscoveryProfile
DiscoveryStatusenum#

Whether a browse result is new or went away.

"Found""Lost"

These routes sit under AppDeviceBridgePolicies.Bridges like every other bridge: callers on this device by default. See Security.