RFC 2614
An API for Service Location
An API for Service Location ๐
okay bestie, this RFC is the spec for an API for Service Location (SLP), and it's giving main character energy ๐ โจ. It was published in June 1999 under the Informational category ๐ธ, which means it shares info with the Internet community but doesn't set a standard. The authors are J. Kempf and E. Guttman from Sun Microsystems ๐ง. Its header doesn't list any document it obsoletes or updates ๐. The RFC number is 2614 and it's part of the Network Working Group stream ๐.
Status of This Memo
this memo is just giving info to the Internet community ๐ซถ. It is NOT a standard of any kind, and it can be shared as much as you want with no limits ๐ฆ.
Abstract
okay so SLP gives clients a brand new way to find network services on their own ๐ฅ. With SLP, it's super simple to offer highly available services that need zero user setup or help from network admins before anyone can use them ๐. This doc describes standardized APIs for SLP in C and Java ๐. The APIs are modular, so implementations only have to offer the features they actually need โจ. It also defines standardized file formats for configuration and serialized registrations, so SLP agents can set network and other parameters in a portable way ๐. The serialized file format lets legacy services get registered with SLP directory agents when changing their program code is hard or impossible ๐ญ, and it lets you swap a registration database between systems too ๐.
Table of Contents โจ
1. Introduction 4
1.1. Goals . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2. Terminology . . . . . . . . . . . . . . . . . . . . . 4
2. File Formats 7
2.1. Configuration File Format . . . . . . . . . . . . . . 8
2.1.1. DA configuration . . . . . . . . . . . . . . 9
2.1.2. Static Scope Configuration . . . . . . . . . . 9
2.1.3. Tracing and Logging . . . . . . . . . . . . . 11
2.1.4. Serialized Proxy Registrations . . . . . . . . 11
2.1.5. Network Configuration Properties . . . . . . . 12
2.1.6. SA Configuration . . . . . . . . . . . . . . . 14
2.1.7. UA Configuration . . . . . . . . . . . . . . . 14
2.1.8. Security . . . . . . . . . . . . . . . . . . 15
2.2. Multihomed Machines. . . . . . . . . . . . . . . . . . 16
2.3. Serialized Registration File . . . . . . . . . . . . . 16
2.4. Processing Serialized Registration and Configuration
Files . . . . . . . . . . . . . . . . . . . . . . . . 18
3. Binding Independent Implementation Considerations 18
3.1. Multithreading . . . . . . . . . . . . . . . . . . . . 18
3.2. Asynchronous and Incremental . . . . . . . . . . . . . 19
3.3. Type Checking for Service Types. . . . . . . . . . . . 19
3.4. Refreshing Registrations . . . . . . . . . . . . . . . 19
3.5. Configuration File Processing . . . . . . . . . . . . 19
3.6. Attribute Types . . . . . . . . . . . . . . . . . . . 20
3.7. Removal of Duplicates . . . . . . . . . . . . . . . . 20
3.8. Character Set Encoding . . . . . . . . . . . . . . . . 20
3.9. Error Semantics . . . . . . . . . . . . . . . . . . . 20
3.10. Modular Implementations . . . . . . . . . . . . . . . 24
3.11. Handling Special Service Types . . . . . . . . . . . . 24
3.12. Scope Discovery and Handling . . . . . . . . . . . . . 24
4. C Language Binding 25
4.1. Constant Types . . . . . . . . . . . . . . . . . . . . 26
4.1.1. URL Lifetimes. . . . . . . . . . . . . . . . . 26
4.1.2. Error Codes. . . . . . . . . . . . . . . . . . 26
4.1.3. SLPBoolean . . . . . . . . . . . . . . . . . . 27
4.2. Struct Types . . . . . . . . . . . . . . . . . . . . 28
4.2.1. SLPSrvURL . . . . . . . . . . . . . . . . . . 28
4.2.2. SLPHandle . . . . . . . . . . . . . . . . . . 29
4.3. Callbacks . . . . . . . . . . . . . . . . . . . . . . 29
4.3.1. SLPRegReport . . . . . . . . . . . . . . . . 30
4.3.2. SLPSrvTypeCallback . . . . . . . . . . . . . . 30
4.3.3. SLPSrvURLCallback . . . . . . . . . . . . . . 31
4.3.4. SLPAttrCallback . . . . . . . . . . . . . . . 33
4.4. Opening and Closing an SLPHandle . . . . . . . . . . . 34
4.4.1. SLPOpen. . . . . . . . . . . . . . . . . . . . 34
4.4.2. SLPClose . . . . . . . . . . . . . . . . . . . 35
4.5. Protocol API . . . . . . . . . . . . . . . . . . . . 36
4.5.1. SLPReg . . . . . . . . . . . . . . . . . . . . 36
4.5.2. SLPDereg . . . . . . . . . . . . . . . . . . . 37
4.5.3. SLPDelAttrs . . . . . . . . . . . . . . . . . 38
4.5.4. SLPFindSrvTypes. . . . . . . . . . . . . . . . 39
4.5.5. SLPFindSrvs . . . . . . . . . . . . . . . . . 41
4.5.6. SLPFindAttrs . . . . . . . . . . . . . . . . . 42
4.6. Miscellaneous Functions . . . . . . . . . . . . . . . 43
4.6.1. SLPGetRefreshInterval . . . . . . . . . . . . 44
4.6.2. SLPFindScopes . . . . . . . . . . . . . . . . 44
4.6.3. SLPParseSrvURL . . . . . . . . . . . . . . . . 45
4.6.4. SLPEscape . . . . . . . . . . . . . . . . . . 46
4.6.5. SLPUnescape . . . . . . . . . . . . . . . . . 47
4.6.6. SLPFree . . . . . . . . . . . . . . . . . . . 48
4.6.7. SLPGetProperty . . . . . . . . . . . . . . . . 48
4.6.8. SLPSetProperty . . . . . . . . . . . . . . . . 49
4.7. Implementation Notes . . . . . . . . . . . . . . . . 49
4.7.1. Refreshing Registrations . . . . . . . . . . . 49
4.7.2. Syntax for String Parameters . . . . . . . . . 49
4.7.3. Client Side Syntax Checking . . . . . . . . . 50
4.7.4. System Properties . . . . . . . . . . . . . . 50
4.7.5. Memory Management . . . . . . . . . . . . . . 51
4.7.6. Asynchronous and Incremental Return Semantics. 51
4.8. Example. . . . . . . . . . . . . . . . . . . . . . . . 52
5. Java Language Binding 56
5.1. Introduction . . . . . . . . . . . . . . . . . . . . . 56
5.2. Exceptions and Errors . . . . . . . . . . . . . . . . 56
5.2.1. Class ServiceLocationException . . . . . . . . 57
5.3. Basic Data Structures . . . . . . . . . . . . . . . . 58
5.3.1. Interface ServiceLocationEnumeration . . . . . 58
5.3.2. Class ServiceLocationAttribute . . . . . . . 58
5.3.3. Class ServiceType . . . . . . . . . . . . . . 61
5.3.4. Class ServiceURL . . . . . . . . . . . . . . 63
5.4. SLP Access Interfaces . . . . . . . . . . . . . . . . 67
5.4.1. Interface Advertiser . . . . . . . . . . . . . 67
5.4.2. Interface Locator . . . . . . . . . . . . . . 69
5.5. The Service Location Manager . . . . . . . . . . . . . 72
5.5.1. Class ServiceLocationManager . . . . . . . . . 72
5.6. Service Template Introspection . . . . . . . . . . . . 74
5.6.1. Abstract Class TemplateRegistry . . . . . . . 74
5.6.2. Interface ServiceLocationAttributeVerifier . . 77
5.6.3. Interface ServiceLocationAttributeDescriptor . 79
5.7. Implementation Notes . . . . . . . . . . . . . . . . . 81
5.7.1. Refreshing Registrations . . . . . . . . . . . 81
5.7.2. Parsing Alternate Transports in ServiceURL . . 81
5.7.3. String Attribute Values . . . . . . . . . . . 82
5.7.4. Client Side Syntax Checking. . . . . . . . . . 82
5.7.5. Language Locale Handling . . . . . . . . . . . 82
5.7.6. Setting SLP System Properties. . . . . . . . . 83
5.7.7. Multithreading . . . . . . . . . . . . . . . . 83
5.7.8. Modular Implementations . . . . . . . . . . . 83
5.7.9. Asynchronous and Incremental Return Semantics. 84
5.8. Example. . . . . . . . . . . . . . . . . . . . . . . . 85
6. Internationalization Considerations 87
6.1. service URL. . . . . . . . . . . . . . . . . . . . . . 87
6.2. Character Set Encoding . . . . . . . . . . . . . . . . 87
6.3. Language Tagging . . . . . . . . . . . . . . . . . . 88
7. Security Considerations 88
8. Acknowledgements 88
9. References 89
10. Authors' Addresses 90
11. Full Copyright Statement 91
1. Introduction ๐ฆ
okay so the Service Location API is built for standardized access to the Service Location Protocol (SLP) ๐ . It makes it way easier for client and service programs to be written or modified so they can do dynamic service discovery and selection ๐ธ. This document defines bindings for the C and Java languages ๐. It also presents standardized formats for configuration files and serialized registration files ๐. These files let SLP agents configure network parameters โ๏ธ, register legacy services that aren't SLP enabled yet ๐ญ, and swap registration databases between systems ๐.
1.1. Goals ๐ฏ
the big goal of the API is source portability ๐: apps that use the API should be able to move between different SLP implementations with minimal fuss โจ. That makes it easier to adopt SLP and to convert clients and service programs over to it ๐ซถ.
the C binding is all about being minimal but still complete when it comes to the SLP protocol ๐ง. It keeps memory management simple and the code size small ๐.
the Java API is the fancier one ๐. It supports modular implementations, so you can leave out features you don't need, and it gives you an object oriented interface to the full set of SLP data and functionality ๐ฅ.
last thing: the standardized configuration and serialized file formats are simple to read but still cover the whole protocol ๐. They just don't include system dependent properties or secure information ๐.
1.2. Terminology ๐
okay bestie, here's the glossary, and it's giving "learn these or get lost" ๐ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 [1].
Service Location Protocol (SLP) ๐ธ
This is the underlying protocol that allows dynamic and scalable service discovery. It's specified in the Service Location Protocol Version 2 [7], so go read that if you're obsessed (I am) ๐ค
SLP framework ๐ฆ
When someone says "Service Location framework," they mean both the SLP implementation and the interface implementation. Basically, whatever gives user-level programs their SLP functionality. This includes remote agents โจ
Directory Agent (DA) ๐
A service that automatically gathers service advertisements from SAs so it can hand them out to UAs. Main character energy, no cap ๐
User Agent (UA) ๐ง
This is the Service Location process or library that makes SLP requests on behalf of a client process. UAs automatically send requests to DAs when they exist. When there aren't any, UAs make requests to SAs instead ๐ซถ
Service Agent (SA) ๐
This is the Service Location process or library that lets service software register and deregister itself with the SLP framework. SAs respond to UA service requests, detect DAs, and register service advertisements with them. literally the hardest-working one ๐ญ
SA Server ๐ฅ
Okay, this one's a plot twist. Many operating system platforms only allow a single process to listen on a particular port number. Since SAs are required to listen on a multicast address for SLP service requests, implementations of the SLP framework on those platforms that want to support multiple SAs on one machine need to arrange for a single process to do the listening, while the advertising SAs talk to that process through another mechanism. That single listening process is called an SA server. SA servers share many characteristics with DAs, but they are not the same ๐
Service Advertisement ๐
A URL, possibly combined with service attributes. SAs make these available to UAs, either directly or via a DA โจ
Locale ๐
The language localization that applies to strings passed into or returned from the SLP API. The Locale is expressed using a Language Tag [6]. All attribute strings are associated with a particular locale. The locale is completely orthogonal to the ANSI C locale (not the same thing, bestie, don't mix them up ๐). The SLP locale is mapped into the Java locale in the Java API.
Service Template ๐
A document that describes the syntax of the URL for a given service type, plus a definition of all service attributes, including their meaning, defaults, and the constraints on the values they can take. See [8] for more information on service templates ๐
The service: URL ๐
A service of a particular type announces its availability with a service: URL. That URL includes its service access point (a domain name or IP address, and possibly its port number) and optionally some basic configuration parameters. The syntax of the service: URL is defined in the service template. Other URLs can be used in service advertisements if desired ๐ฆ
Service Attributes ๐ธ
The attributes associated with a given service. The values that can be assigned to service attributes are defined by the service template โจ
Scope ๐
A string used to control the availability of service advertisements. Every SLP Agent is configured with one or more scope strings. Site administrators assign scopes to group services for many purposes, but chiefly as a means of scalability. DAs store only services advertised with a scope string that matches the scopes they're configured with ๐ฅ
Naming Authority (NA) ๐
This is a "suffix" to the service type string, and it completely changes the meaning of the service type. NAs are used for private definitions of well-known Service Types and for experimental Service Type extensions. The default NA is "IANA", which must not be explicitly included. Service types with the IANA naming authority are registered with the Internet Assigned Numbers Authority (see [8] for more information on the registration procedure) ๐
2. File Formats ๐๏ธ
This section describes the configuration and serialized registration file formats. Both files are defined in the UTF-8 character set [3] ๐
Attribute tags and values in the serialized registration file require SLP reserved characters to be escaped. The SLP reserved characters are (, ), ,, \, !, <, =, >, ~ and control characters (characters with UTF codes less than 0x0020 and the character 0x007f, which is US-ASCII DEL). The escapes are formed exactly as they are for the wire protocol, i.e. a backslash followed by two hex digits representing the character. For example, the escape for , is \2c. In addition, the characters \n, \r, \t, and _ are prohibited from attribute tags by the SLP wire syntax grammar. [7] ๐ง
In serialized registration files, escaped strings beginning with \ff, an encoding for a nonUTF-8 character, are treated as opaques. Exactly as in the wire protocol, syntactically correct opaque encodings consist of a string beginning with \ff and containing only escaped characters that are transformed to bytes. Such strings are only syntactically correct in the serialized registration file as attribute values. In other cases, whenever an escape is encountered and the character is not an SLP reserved character, an error is signaled ๐จ
Escaped characters in URLs in serialized registration files use the URL escape convention. [2] ๐ธ
Property names and values in the configuration file have a few reserved characters that are involved in the file's lexical definition. The characters . and = are reserved in property names and must be escape. The characters ,, (, and ) are reserved in property values and must be escaped. In addition, scope names in the net.slp.useScopes property use the SLP wire format escape convention for SLP reserved characters. This simplifies implementation, since the same code can be used to unescape scope names as is used when processing the serialized registration file or formatting wire messages ๐
On platforms that only support US-ASCII and not UTF-8, the upper bit of bytes incoming from the configuration and registration files determines whether the character is US-ASCII or not US-ASCII. According to the standard UTF-8 encoding, the upper bit is zero if the character is US-ASCII and one if the character is multibyte and thus not US-ASCII. Platforms without intrinsic UTF-8 support are required to parse the multibyte character and store it in an appropriate internal format. Support for UTF-8 is required to implement the SLP protocol (see [7]), and can therefore be used in file processing as well ๐
The location and name of the configuration file is system-dependent, but implementations of the API are encouraged to locate it together with other configuration files and name it consistently โจ
2.1. Configuration File Format โ๏ธ
The configuration file format consists of a newline-delimited list of zero or more property definitions. Each property definition corresponds to a particular configurable SLP, network, or other parameter in one or more of the three SLP agents. The file format grammar in ABNF [5] syntax is:
config-file = line-list
line-list = line / line line-list
line = property-line / comment-line
comment-line = ( "#" / ";" ) 1*allchar newline
property-line = property newline
property = tag "=" value-list
tag = prop / prop "." tag
prop = 1*tagchar
value-list = value / value "," value-list
value = int / bool /
"(" value-list ")" / string
int = 1*DIGIT
bool = "true" / "false" / "TRUE" / "FALSE"
newline = CR / ( CRLF )
string = 1*stringchar
tagchar = DIGIT / ALPHA / tother / escape
tother = %x21-%x2d / %x2f /
%x3a / %x3c-%x40 /
%x5b-%x60 / %7b-%7e
; i.e., all characters except `.',
; and `='.
stringchar = DIGIT / ALPHA / sother / escape
sother = %x21-%x29 / %x2a-%x2b /
%x2d-%x2f / %x3a-%x40 /
%x5b-%x60 / %7b-%7e
; i.e., all characters except `,'
allchar = DIGIT / ALPHA / HTAB / SP
escape = "\" HEXDIG HEXDIG
; Used for reserved characters
With the exception of net.slp.useScopes, net.slp.DAAddresses, and net.slp.isBroadcastOnly, all other properties can be changed through property accessors in the C and Java APIs. The property accessors only change the property values in the running agent program and do not affect the values in the configuration file. The net.slp.useScopes and net.slp.DAAddresses properties are read-only, because they control the agent's view of the scopes and DAs and are therefore critical to the function of the API scope discovery algorithm. Attempts to modify them are unlikely to yield productive results, and could harm the ability of the agent to find scopes and use DAs. The net.slp.isBroadcastOnly property is read-only because the API library needs to configure networking upon start up, and changing this property might invalidate the configuration. Whether the local network uses broadcast or multicast is not likely to change during the course of the program's execution ๐
The properties break down into the following subsections, each describing an area and its properties ๐งฉ
2.1.1. DA configuration ๐
Important configuration properties for DAs are included in this section. These are:
net.slp.isDA ๐
A boolean indicating if the SLP server is to act as a DA. If false, it does not run as a DA. Default is false.
net.slp.DAHeartBeat ๐
A 32 bit integer giving the number of seconds for the DA heartbeat. Default is 3 hours (10800 seconds). This property corresponds to the protocol specification parameter CONFIG_DA_BEAT [7]. Ignored if isDA is false โฐ
net.slp.DAAttributes ๐ธ
A comma-separated list of parenthesized attribute/value list pairs that the DA must advertise in DAAdverts. The property must be in the SLP attribute list wire format, including escapes for reserved characters. [7]
2.1.2. Static Scope Configuration โจ
okay so these properties let you tweak how scopes get handled ๐
net.slp.useScopes
This is a value-list of strings saying which scopes a UA or SA is allowed to use when it makes requests or registers, or which scopes a DA has to support. If it's not there for a DA or SA, then with no scope info from DHCP, the default scope "DEFAULT" gets used. If it's not there for a UA and DHCP has no scope info either, the user scoping model is in force ๐ Active and passive DA discovery or SA discovery handle scope discovery, and "DEFAULT" is the fallback if nothing else is available.
Now the spicy part ๐ฅ If a DA or SA gets a different scope in a request, it should return a SCOPE_NOT_SUPPORTED error, unless the request was multicast, in which case it should just drop it. If a DA gets another scope in a registration, it must return a SCOPE_NOT_SUPPORTED error. This property is "read-only" (no changing it after the config file has been read, those changes get ignored ๐ โโ๏ธ). See Section 3.12 for the algorithm the API uses to decide what scope info to present.
net.slp.DAAddresses
This is a value-list of IP addresses or DNS resolvable host names giving the SLPv2 DAs to use for statically configured UAs and SAs. DAs ignore it (unless the DA is also an SA server). The default is none. It's "read-only" too, so changes after the config file is read get ignored.
Here's the grammar for it ๐ง
addr-list = addr / addr "," addr-list
addr = fqdn / hostnumber
fqdn = ALPHA / ALPHA *[ anum / "-" ] anum
anum = ALPHA / DIGIT
hostnumber = 1*3DIGIT 3("." 1*3DIGIT)
And an example:
sawah,mandi,sambal
IP addresses work where DNS isn't deployed, but network admins, be warned ๐ using IP addresses makes renumbering machines a headache, since the SLP config property files in statically configured networks will have to be changed. And if you use host names, implementors must be careful that a name service is up before SLP starts. In other words, SLP can't be used to find the name service. Bestie, that's a chicken-and-egg situation ๐
2.1.3. Tracing and Logging ๐ฆ
This section lets the various agents print tracing and logging info.
net.slp.traceDATraffic
A boolean that controls printing of messages about traffic with DAs. Default is false.
net.slp.traceMsg
A boolean that controls printing of details on SLP messages. All fields in incoming messages and outgoing replies get printed. Default is false.
net.slp.traceDrop
A boolean that controls printing details when an SLP message gets dropped for any reason. Default is false.
net.slp.traceReg
A boolean that controls dumps of all registered services upon registration and deregistration. If true, the contents of the DA or SA server get dumped after a registration or deregistration happens. Default is false.
2.1.4. Serialized Proxy Registrations ๐ธ
These properties control reading and writing serialized registrations.
net.slp.serializedRegURL
A string containing a URL that points to a document with serialized registrations, which should be processed when the DA or SA server starts up. Default is none.
2.1.5. Network Configuration Properties ๐
The properties in this section let you set various network configuration properties.
net.slp.isBroadcastOnly
A boolean saying whether broadcast should be used instead of multicast. Like net.slp.useScopes and net.slp.DAAddresses, this one is "read-only", so changes after the config file has been read get ignored. Default is false.
net.slp.passiveDADetection
A boolean saying whether passive DA detection should be used. Default is true.
net.slp.multicastTTL
A positive integer less than or equal to 255, giving the multicast TTL. Default is 255.
net.slp.DAActiveDiscoveryInterval
A 16 bit positive integer giving the number of seconds between DA active discovery queries. Default is 900 seconds (15 minutes). This property corresponds to the protocol specification parameter CONFIG_DA_FIND [7]. If it's set to zero, active discovery is turned off. That's useful when the DAs available are explicitly restricted to those obtained from DHCP or the net.slp.DAAddresses property ๐ฏ
net.slp.multicastMaximumWait
A 32 bit integer giving the maximum amount of time to perform multicast, in milliseconds. Default is 15000 ms (15 sec.). This property corresponds to the CONFIG_MC_MAX parameter in the protocol specification [7].
net.slp.multicastTimeouts
A value-list of 32 bit integers used as timeouts, in milliseconds, to implement the multicast convergence algorithm. Each value is the time to wait before sending the next request, or until nothing new has been learned from two successive requests. Default is:
3000,3000,3000,3000,3000
In a fast network, the aggressive values of
1000,1250,1500,2000,4000
allow better performance โก This property corresponds to the CONFIG_MC_RETRY parameter in the protocol specification [7]. Note that the net.slp.DADiscoveryTimeouts property must be used for active DA discovery.
net.slp.DADiscoveryTimeouts
A value-list of 32 bit integers used as timeouts, in milliseconds, to implement the multicast convergence algorithm during active DA discovery. Each value is the time to wait before sending the next request, or until nothing new has been learned from two successive requests. This property corresponds to the protocol specification parameter CONFIG_RETRY [7]. Default is:
2000,2000,2000,2000,3000,4000
net.slp.datagramTimeouts
A value-list of 32 bit integers used as timeouts, in milliseconds, to implement unicast datagram transmission to DAs. The nth value is the time to block waiting for a reply on the nth try to contact the DA. The sum of these values is the protocol specification property CONFIG_RETRY_MAX [7].
net.slp.randomWaitBound
A 32 bit integer giving the maximum value for all random wait parameters, in milliseconds. Default is 1000 (1 sec.). This value corresponds to the protocol specification parameters CONFIG_START_WAIT, CONFIG_REG_PASSIVE, and CONFIG_REG_ACTIVE [7].
net.slp.MTU
A 16 bit integer giving the network packet MTU, in bytes. This is the maximum size of any datagram to send, but the implementation might receive a larger datagram. The maximum size includes IP, and UDP or TCP headers. Default is 1400.
net.slp.interfaces
A value-list of strings giving the IP addresses of network interfaces that the DA or SA should listen on, on port 427, for multicast, unicast UDP, and TCP messages. Default is empty, i.e. use the default network interface. The grammar for this property is:
addr-list = hostnumber / hostnumber "," addr-list
hostnumber = 1*3DIGIT 3("." 1*3DIGIT)
An example is:
195.42.42.42,195.42.142.1,195.42.120.1
The example machine has three interfaces the DA should listen on. Since this property only takes IP addresses, it'll need to be changed if the network gets renumbered ๐
2.1.6. SA Configuration ๐ง
This section has the configuration properties for the SA. These are typically set programmatically by the SA, since they're specific to each SA.
net.slp.SAAttributes
A comma-separated list of parenthesized attribute/value list pairs that the SA must advertise in SAAdverts. The property must be in the SLP attribute list wire format, including escapes for reserved characters. [7]
2.1.7. UA Configuration ๐
This section has the configuration properties for the UA. These can be set either programmatically by the UA or in the configuration file.
net.slp.locale
A RFC 1766 Language Tag [6] for the language locale. Setting this property makes its value the default locale for SLP messages. Default is "en". This property is also used for SA and DA configuration.
net.slp.maxResults
A 32 bit integer giving the maximum number of results to accumulate and return for a synchronous request before the timeout, or the maximum number of results to return through a callback if the request results are reported asynchronously.
Positive integers and -1 are legal values. If it's -1, that means all results should be returned. Default value is -1.
DAs and SAs always return all results that match the request. This config value only applies to UAs, which filter incoming results and only return as many values as net.slp.maxResults indicates ๐
net.slp.typeHint
A value-list of service type names. Without any DAs, UAs perform SA discovery to find scopes. These SA discovery requests may contain a request for service types as an attribute.
The API implementation will use the service type names supplied by this property to discover only those SAs (and their scopes) that support the desired service type or types. For example, if net.slp.typeHint is set to "service:imap,service:pop3", then SA discovery requests will include the search filter:
(|(service-type=service:imap)(service-type=service:pop3))
The API library can also use unicast to contact the discovered SAs for later requests for these service types, to optimize network access ๐
2.1.8. Security ๐
The property in this section turns security for all agents on or off. When it's true, the agent must include security information on all SLP messages it transacts. Since security policy has to be set network wide to work, a single property controls security for all agents. Key management and management of SLP SPI strings [7] are implementation and policy dependent, so that's on you ๐ซถ
net.slp.securityEnabled
A boolean saying whether the agent should enable security for URLs, attribute lists, DAAdverts, and SAAdverts. Each agent is responsible for interpreting the property appropriately. Default is false.
2.2. Multihomed Machines ๐โจ
okay so on multihomed machines (aka boxes with more than one network interface, bestie ๐ป), each interface can have totally different bandwidth and latency, so one set of settings might not be the best fit for all of them ๐ฅบ that's why net.slp.interfaces exists. It tells you which interfaces are SLP enabled ๐ An API library can even customise things per interface by adding the interface IP address onto the end of a property name. When it does that, the value only applies to that one interface, and the generic property (or the defaults, if there's no generic one) covers everything else ๐
here's an example so you can see the vibe:
net.slp.interfaces=125.196.42.41,125.196.42.42,125.196.42.43
net.slp.multicastTTL.125.196.42.42=1
so the interface on subnet 42 gets locked to a TTL of 1 ๐ฆ while the interfaces on the other subnets keep the default multicast radius, which is 255 ๐
now the big rules ๐ net.slp.interfaces should only be set if there's no routing between the interfaces. if it is set, the DA (if there is one) and the SAs should advertise using the IP address or host name that matches the interface they're on, for every interface in the list ๐ธ but if packets get routed between the interfaces, then the DA and SAs should only advertise on the default interface. the property should also be set if broadcast is used instead of multicast on the subnets attached to those interfaces ๐
and here's the tea โ even if unicast packets aren't routed between the interfaces, multicast might still get routed through some other router ๐ the danger of listening for multicast on several interfaces when multicast gets routed is that the DA or SA could receive the same multicast request through more than one interface. since the IP address is different on each interface, the DA or SA can't tell that the request was already answered via the previous responder's list ๐ญ so the requesting agent ends up with URLs that point at the same DA or service, but with different addresses or host names. not it ๐
2.3. Serialized Registration File ๐๐ซถ
the serialized registration file holds a group of registrations that a DA or SA server (if one exists) registers when it starts up ๐ง these are mainly for older service programs that don't support SLP internally and can't be converted, and for swapping registrations between SLP implementations in a portable way ๐ the character encoding of the registrations is required to be UTF-8 ๐
here's the ABNF grammar (ABNF format [5]) for the file, so you know exactly what's allowed:
ser-file = reg-list
reg-list = reg / reg reg-list
reg = creg / ser-reg
creg = comment-line ser-reg
comment-line = ( "#" / ";" ) 1*allchar newline
ser-reg = url-props [slist] [attr-list] newline
url-props = surl "," lang "," ltime [ "," type ] newline
surl = ;The registration's URL. See
; [8] for syntax.
lang = 1*8ALPHA [ "-" 1*8ALPHA ]
;RFC 1766 Language Tag see [6].
ltime = 1*5DIGIT
; A positive 16-bit integer
; giving the lifetime
; of the registration.
type = ; The service type name, see [7]
; and [8] for syntax.
slist = "scopes" "=" scope-list newline
scope-list = scope-name / scope-name "," scope-list
scope = ; See grammar of [7] for
; scope-name syntax.
attr-list = attr-def / attr-def attr-list
attr-def = ( attr / keyword ) newline
keyword = attr-id
attr = attr-id "=" attr-val-list
attr-id = ;Attribute id, see [7] for syntax.
attr-val-list = attr-val / attr-val "," attr-val-list
attr-val = ;Attribute value, see [7] for syntax.
allchar = char / WSP
char = DIGIT / ALPHA / other
other = %x21-%x2f / %x3a-%x40 /
%x5b-%x60 / %7b-%7e
; All printable, nonwhitespace US-ASCII
; characters.
newline = CR / ( CRLF )
the syntax for scope names, attribute tags and attribute values needs escapes for special characters, as specified in [7] ๐ DAs and SA servers that process serialized registrations have to handle them exactly as if an SA had registered them ๐ฆ in the url-props production, the type token is optional ๐ธ if the type token is there for a service: URL, a warning gets signalled and the type name gets ignored โ ๏ธ if the maximum lifetime is given (65535 sec.), the registration counts as permanent, and the DA or SA server keeps refreshing it until it exits ๐
scopes can be added to a registration by including an attribute definition with the tag "scopes", followed by a comma separated list of scope names right after the url-props production โจ if that optional scope list is there, the registrations get made in the scopes listed; otherwise they go into the scopes the DA or SA server was configured with through the net.slp.useScopes property ๐
one more thing ๐ if the scope list has scopes that aren't in the net.slp.useScopes property (assuming that property is set), or aren't specified by DHCP, the API library should reject the registration and issue a warning message ๐ซ
2.4. Processing Serialized Registration and Configuration Files โ๏ธ๐ท
implementations are encouraged to make processing of configuration and serialized files as transparent as possible to API clients ๐ซถ errors must be caught at the latest when the relevant configuration item gets used ๐ฐ๏ธ and they may be caught at the earliest when the relevant file is loaded into the executing agent โจ errors should be reported by logging to the appropriate platform logging file, error output, or log device, and the default value gets substituted ๐ serialized registration file entries should be caught and reported when the file is loaded ๐
configuration file loading must be complete before the first networking connection is started ๐ and serialized registration must be complete before the DA accepts the first network request ๐ฅ
3. Binding Independent Implementation Considerations ๐งฉ๐
this section talks about a bunch of implementation considerations that don't depend on the language binding, with notes for specific languages where they apply ๐ฆ
3.1. Multithreading ๐งต
implementations of both the C and Java APIs are required to make API calls thread-safe ๐ access to data structures shared between threads has to be coordinated so nothing gets corrupted or accessed invalidly ๐ญ one way to get there is to allow only one thread at a time in the implementing library, but performance in that kind of implementation takes a hit ๐ข so wherever possible, implementations are encouraged to allow multiple threads inside the SLP API library ๐
3.2. Asynchronous and Incremental ๐
the APIs are designed to encourage implementations that support asynchronous and incremental client interaction โจ the goal is to let big numbers of returned service URLs, service types and attributes come back without having to allocate huge chunks of memory ๐ง the particular design features that support this differ between the two language bindings ๐
3.3. Type Checking for Service Types ๐
service templates [8] let SLP registrations be type checked for correctness ๐ implementations of the API are free to use service type information for type checking, but they aren't required to ๐ if a type error does happen, the registration should terminate with TYPE_ERROR โ
3.4. Refreshing Registrations ๐๐ซ
SLP advertisements carry an explicit lifetime with them ๐ฐ๏ธ once the lifetime runs out, the DA flushes the registration from its cache ๐งน sometimes an application wants its URL to stay registered for the whole time it's running, so the API has a way for clients to say whether they want URLs refreshed automatically ๐ implementations of the SA API must provide this automatic refreshing capability ๐ซถ a client using this feature should explicitly deregister the service URL before exiting ๐ช the reason is that the API implementation may not be able to make sure the URL gets deregistered when the application exits, though it will eventually time out in the DA ๐
3.5. Configuration File Processing ๐ ๏ธ
DAs, SAs and UAs that process the configuration file, and DAs and SA servers that process the serialized registration file, are required to log any errors using whatever underlying error mechanism is appropriate for the platform ๐ examples include writing error messages to standard output, writing to a system logging device, or showing the errors in a logging window ๐ช after the error is reported, the offending property must be set to the default and program execution continued ๐ An agent MUST NOT fail if a file format error occurs. ๐ซ ๐
3.6. Attribute Types ๐ท๏ธ
string encoded attribute values don't include explicit type information ๐คท all UA implementations, and those SA and DA implementations that choose to support type checking, should use the type rules described in [8] to convert from the string representation on the wire into an object with the appropriate type ๐
3.7. Removal of Duplicates ๐ฏโโ๏ธ
the UA implementation SHOULD always collate results to remove duplicates during synchronous operations and for the Java API ๐งน during asynchronous operation in C, the UA implementation SHOULD forgo duplicate elimination to reduce memory requirements in the library ๐ง this lets the API library just take the returned attribute value list strings, URL strings or service type list strings and call the callback function with them, with no extra processing ๐ naturally, the burden of duplicate elimination then falls on the client ๐
3.8. Character Set Encoding ๐ค๐
character string parameters in the Java API are all represented in Unicode internally, because that's the character set Java supports ๐ character buffer parameters in the C API are represented in UTF-8, so they stay maximally compatible on platforms that only support US-ASCII and not UTF-8 ๐ธ API functions still have to handle the full range of UTF-8 characters because the SLP protocol requires it, but the API implementation can store the characters internally in any convenient way ๐ง on the wire, all characters are converted to UTF-8 ๐ก inside URLs, characters that URL syntax [2] doesn't allow must be escaped according to the URL escape character convention ๐ strings included in SLP messages may contain SLP reserved characters, and clients can escape them through convenience functions the API provides ๐ the character encoding used in escapes is UTF-8 ๐
due to constraints in SLP, no string parameter passed to the C or Java API may exceed 64K bytes in length ๐๐
3.9. Error Semantics โจ
Okay so, every error that pops up while processing SLP messages should get logged ๐. That's non-negotiable bestie.
For synchronous calls, an error only gets reported on a call if no successful replies came back from any SLP framework entity. If one error showed up among several successful replies, log it and still return the good replies ๐ (the vibe is "the tea is logged, but the wins still count").
For asynchronous calls, an error that happens while talking to a particular remote SLP agent gets reported through the first callback (C API) or enumeration method invocation (Java API) after the error happens, which is usually where the results of that conversation get reported too. That way the callback or client code can decide whether to terminate or keep going ๐ฆ. Some errors from the SLP framework are fatal (SLP_PARSE_ERROR, etc.) and in those cases the API library terminates the operation ๐.
Both the Java and C APIs have language-specific error code mechanisms for returning error info ๐. The names of the error codes match between the two implementations though, so that's one less thing to memorize ๐ซถ.
The following error codes are returned from a remote agent (DA or SA server):
LANGUAGE_NOT_SUPPORTED: No DA or SA has service advertisement or attribute information in the language requested, but at least one DA or SA indicated, via theLANGUAGE_NOT_SUPPORTEDerror code, that it might have information for that service in another language.PARSE_ERROR: The SLP message was rejected by a remote SLP agent. The API returns this error only when no information was retrieved, and at least one SA or DA indicated a protocol error. The data supplied through the API may be malformed or may have been damaged in transit.INVALID_REGISTRATION: The API may return this error if an attempt to register a service was rejected by all DAs because of a malformed URL or attributes. SLP does not return the error if at least one DA accepted the registration.AUTHENTICATION_ABSENT: If the SLP framework supports authentication, this error arises when the UA or SA failed to send an authenticator for requests or registrations in a protected scope.INVALID_UPDATE: An update for a non-existing registration was issued, or the update includes a service type or scope different than that in the initial registration, etc.
The following errors result from interactions with remote agents or can occur locally:
AUTHENTICATION_FAILED: If the SLP framework supports authentication, this error arises when an authentication on an SLP message failed.SCOPE_NOT_SUPPORTED: The API returns this error if the SA has been configured with thenet.slp.useScopesvalue-list of scopes and the SA request did not specify one or more of these allowable scopes, and no others. It may be returned by a DA or SA if the scope included in a request is not supported by the DA or SA.REFRESH_REJECTED: The SA attempted to refresh a registration more frequently than the minimum refresh interval. The SA should call the appropriate API function to obtain the minimum refresh interval to use.
The following errors are generated through a program interacting with the API implementation. They do not involve a remote SLP agent.
NOT_IMPLEMENTED: If an unimplemented feature is used, this error is returned.NETWORK_INIT_FAILED: If the network cannot initialize properly, this error is returned.NETWORK_TIMED_OUT: When no reply can be obtained in the time specified by the configured timeout interval for a unicast request, this error is returned.NETWORK_ERROR: The failure of networking during normal operations causes this error to be returned.BUFFER_OVERFLOW: An outgoing request overflowed the maximum network MTU size. The request should be reduced in size or broken into pieces and tried again.MEMORY_ALLOC_FAILED: If the API fails to allocate memory, the operation is aborted and returns this.PARAMETER_BAD: If a parameter passed into an interface is bad, this error is returned.INTERNAL_SYSTEM_ERROR: A basic failure of the API causes this error to be returned. This occurs when a system call or library fails. The operation could not recover.HANDLE_IN_USE: In the C API, callback functions are not permitted to recursively call into the API on the sameSLPHandle, either directly or indirectly. If an attempt is made to do so, this error is returned from the called API function.TYPE_ERROR: If the API supports type checking of registrations against service type templates, this error can arise if the attributes in a registration do not match the service type template for the service.
Some error codes are handled differently in the Java API. These differences are discussed in Section 5.
The SLP protocol errors OPTION_NOT_UNDERSTOOD, VERSION_NOT_SUPPORTED, INTERNAL_ERROR, MSG_NOT_SUPPORTED, AUTHENTICATON_UNKNOWN, and DA_BUSY_NOW should be handled internally and not surfaced to clients through the API ๐.
3.10. Modular Implementations ๐งฉ
Okay, subset implementations that don't support the full range of functionality are required to still support every interface ๐ซถ. Why? Because it keeps link compatibility between compliant API implementations and applications intact. So if a particular operation isn't supported, a NOT_IMPLEMENTED error should be returned.
The Java API has some extra conventions for handling subsets. And applications that are expected to run on a wide variety of platforms should be prepared for subset API implementations by checking the error codes they get back ๐.
3.11. Handling Special Service Types ๐ต๏ธโโ๏ธ
The service types service:directory-agent and service:service-agent are used internally in the SLP framework to discover DAs and SAs. Normally the API client never sees this discovery mechanism ๐. BUT the client might still care about discovering DAs and SAs on their own, separate from their role in finding other services. For example, a network management app might want to figure out which machines are running SLP DAs ๐. So API implementations must handle requests to find services and attributes for these two service types, so that API clients get the info they expect โจ.
Here's the catch: if the UA is using a DA, SrvRqst and AttrRqst for these service types must be multicast and not unicast to the DA, unlike other service types ๐. If the requests aren't multicast, the DA will respond with an empty reply to a request for services of type service:service-agent, and with its URL only to a request for services of type service:directory-agent. So the UA wouldn't get the full picture of the available DAs and SAs. Not a vibe ๐ญ.
3.12. Scope Discovery and Handling ๐บ๏ธ
Both APIs have an operation to get a list of currently known scope names ๐. That scope info comes from a bunch of places: DHCP, the net.slp.useScopes property, unicast to DAs configured via DHCP or the net.slp.DAAddresses property, and active and passive discovery.
The API is required to be implemented in a way that re-enforces the administrative and user scoping models described in [7]. SA clients only support the administrative scoping model. SAs must know a priori what DAs they need to register with, since there's typically no human intervention in scope selection for SAs ๐ค. UAs must support both administrative and user scoping, because an application may require human intervention in scope selection ๐.
API implementations are required to support administrative scoping in the following way. Scopes configured by DHCP and scopes of DAs configured by DHCP have first priority (in that order) and must be returned if they're available. The net.slp.useScopes property has second priority, and scopes discovered through the net.slp.useScopes property must be returned if this property is set and there are no scopes available from DHCP. If scopes aren't available from either of these sources and the net.slp.DAAddresses property is set, then the scopes available from the configured DAs must be returned. Note that if both DAs and scopes are configured, the scopes of the configured DAs must match the configured scope list; otherwise an error is signaled and agent execution is terminated ๐จ. If no configured scope information is available, then an SA client has default scope, "DEFAULT", and a UA client employs user scoping.
User scoping is supported in the following way. Scopes discovered from active DA discovery, and from passive DA discovery, all must be returned. If no information is available from active and passive DA discovery, then the API library may perform SA discovery, using the service types in the net.slp.typeHint property to limit the search to SAs supporting particular service types. If no net.slp.typeHint property is set, the UA may perform SA discovery without any service type query. In the absence of any of the above sources of information, the API must return the default scope, "DEFAULT". Note that the API must always return some scope information ๐ซง.
SLP requires that SAs must perform their operations in all scopes currently known to them. [7]. The API enforces this constraint by not requiring the API client to supply any scopes as parameters to API operations. The API library must obtain all currently known scopes and use them in SA operations. UA API clients should use a scope obtained through one of the API operations for finding scopes. Any other scope name may result in a SCOPE_NOT_SUPPORTED error from a remote agent. The UA API library can optionally check the scope and return the error without contacting a remote agent ๐ฆ.
4. C Language Binding ๐ป
The C language binding is a minimal overhead implementation that maps directly into the protocol ๐. There's one C language function per protocol request, with the exception of the SLPDereg() and SLPDelAttrs() functions, which map into different uses of the SLP deregister request. Parameters are mostly character buffers. Memory management is kept simple by having the client allocate most of the memory, and requiring that client callback functions copy incoming parameters into memory allocated by the client code. Any memory returned directly from the API functions is deallocated using the SLPFree() function ๐งน.
To conform with standard C practice, all character strings passed to and returned through the API are null terminated, even though the SLP protocol doesn't use null terminated strings ๐ค. Strings passed as parameters are UTF-8, but they may still be passed as a C string (a null terminated sequence of bytes). Escaped characters must be encoded by the API client as UTF-8. In the common case of US-ASCII, the usual one byte per character C strings work. API functions help with escaping and unescaping strings ๐.
Unless otherwise noted, parameters to API functions and callbacks are non-NULL. Some parameters may have other restrictions. If any parameter fails to satisfy the restrictions on its value, the operation returns a PARAMETER_BAD error ๐ซ.
4.1. Constant Types ๐ธ
4.1.1. URL Lifetimes ๐ฐ๏ธ
4.1.1.1. Synopsis
typedef enum {
SLP_LIFETIME_DEFAULT = 10800,
SLP_LIFETIME_MAXIMUM = 65535
} SLPURLLifetime;
4.1.1.2. Description
Okay bestie, the SLPURLLifetime enum holds the URL lifetime values (in seconds) that everyone keeps reaching for โฐโจ. SLP_LIFETIME_DEFAULT is 3 hours, and SLP_LIFETIME_MAXIMUM is about 18 hours. That max is the biggest number the lifetime field can hold in SLP messages, so it's basically the ceiling ๐๐
4.1.2. Error Codes
4.1.2.1. Synopsis
typedef enum {
SLP_LAST_CALL = 1,
SLP_OK = 0,
SLP_LANGUAGE_NOT_SUPPORTED = -1,
SLP_PARSE_ERROR = -2,
SLP_INVALID_REGISTRATION = -3,
SLP_SCOPE_NOT_SUPPORTED = -4,
SLP_AUTHENTICATION_ABSENT = -6,
SLP_AUTHENTICATION_FAILED = -7,
SLP_INVALID_UPDATE = -13,
SLP_REFRESH_REJECTED = -15,
SLP_NOT_IMPLEMENTED = -17,
SLP_BUFFER_OVERFLOW = -18,
SLP_NETWORK_TIMED_OUT = -19,
SLP_NETWORK_INIT_FAILED = -20,
SLP_MEMORY_ALLOC_FAILED = -21,
SLP_PARAMETER_BAD = -22,
SLP_NETWORK_ERROR = -23,
SLP_INTERNAL_SYSTEM_ERROR = -24,
SLP_HANDLE_IN_USE = -25,
SLP_TYPE_ERROR = -26
} SLPError ;
4.1.2.2. Description
The SLPError enum is the list of error codes that API functions hand back to you ๐จ
SLP_OK means that no error happened during the operation. Yay, all good ๐
SLP_LAST_CALL is the one that gets passed to callback functions when the API library has run out of data for them. After that, no more calls will come in on the operation that's still outstanding ๐ The callback can use this as a signal to tell the main client code that more data isn't coming, so the main body can break out of its data-collection loops. During both a synchronous and an asynchronous call, the last callback call has the error code parameter set to SLP_LAST_CALL, and all the other parameters are NULL. If an API operation returns no results, then there's only one call, and its error parameter is SLP_LAST_CALL ๐
4.1.3. SLPBoolean
4.1.3.1. Synopsis
typedef enum {
SLP_FALSE = 0,
SLP_TRUE = 1
} SLPBoolean;
4.1.3.2. Description
SLPBoolean is the enum you use as a true-or-false flag โ
โ
4.2. Struct Types
4.2.1. SLPSrvURL
4.2.1.1. Synopsis
typedef struct srvurl {
char *s_pcSrvType;
char *s_pcHost;
int s_iPort;
char *s_pcNetFamily;
char *s_pcSrvPart;
} SLPSrvURL;
4.2.1.2. Description
SLPSrvURL is filled in by the SLPParseSrvURL() function. It takes information parsed out of a character buffer that holds a service URL, and each field matches a different part of that URL ๐งฉ Fun fact: this struct follows the standard Berkeley sockets struct servent, with one twist. The pointer to an array of characters for aliases (the s_aliases field) gets swapped out for a pointer to the host name (the s_pcHost field) ๐ธ
s_pcSrvTypeA pointer to a character string with the service type name, including the naming authority. The service type name includes the "service:" if the URL uses the service: scheme. [7]s_pcHostA pointer to a character string with the host identification information.s_iPortThe port number, or zero if there isn't one. The port only exists if the transport is IP.s_pcNetFamilyA pointer to a character string with the network address family identifier. The possible values are "ipx" for the IPX family, "at" for the Appletalk family, and "" (that's the empty string) for the IP address family ๐ฆs_pcSrvPartWhatever is left of the URL after the host identification.
The host and port should be enough to open a socket to the machine hosting the service. The rest of the URL should let you tell the service apart from others ๐ซถ
4.2.2. SLPHandle
4.2.2.1. Synopsis
typedef void* SLPHandle;
SLPHandle is what SLPOpen() gives you back, and it's a parameter for every SLP function โจ It works like a handle for all the resources the SLP library allocates on behalf of the process. The type is opaque, because what it actually is depends on the implementation ๐
4.3. Callbacks
When you call an API function, you include a function pointer to a callback that's specific to that operation in the parameter list. The callback gets called with the results of the operation in both the synchronous and asynchronous cases ๐ The memory in the callback parameters belongs to the API library. So if the client code in the callback wants to keep that info around for longer than the current callback call, it must copy it out ๐
Every callback parameter list also has an error code parameter and a cookie parameter. The error code reports the error status of the ongoing operation (for asynchronous) or the completed operation (for synchronous) ๐ฆ The cookie lets the client code that starts the operation pass info down to the callback without needing global variables, which is so clean ๐ The callback returns an SLPBoolean to say whether the API library should keep processing the operation. If the callback returns SLP_TRUE, asynchronous operations get terminated. Synchronous operations ignore the return value, since they're already complete ๐
4.3.1. SLPRegReport
4.3.1.1. Synopsis
typedef void SLPRegReport(SLPHandle hSLP,
SLPError errCode,
void *pvCookie);
4.3.1.2. Description
SLPRegReport is the callback type for SLPReg(), SLPDereg(), and SLPDelAttrs() ๐
4.3.1.3. Parameters
hSLPTheSLPHandlethat started the operation.errCodeAn error code that tells you if something went wrong during the operation.pvCookieMemory the client code passed down from the original API function call that started the operation. It may be NULL.
4.3.2. SLPSrvTypeCallback
4.3.2.1. Synopsis
typedef SLPBoolean SLPSrvTypeCallback(SLPHandle hSLP,
const char* pcSrvTypes,
SLPError errCode,
void *pvCookie);
4.3.2.2. Description
SLPSrvTypeCallback is the callback type you pass to the SLPFindSrvTypes() function ๐ If the hSLP handle was opened asynchronously, the results that come back through the callback MAY be uncollated ๐ If it was opened synchronously, then the results must be collated and the duplicates have to be eliminated ๐งน
4.3.2.3. Parameters
hSLPTheSLPHandlethat started the operation.pcSrvTypesA character buffer with a comma-separated, null-terminated list of service types ๐errCodeAn error code that tells you if something went wrong during the operation. The callback should check this error code before it processes the parameters. If the error code is anything other thanSLP_OK, then the API library may choose to end the outstanding operation ๐pvCookieMemory the client code passed down from the original API function call that started the operation. It may be NULL.
4.3.2.4. Returns
The client code should return SLP_TRUE if it wants more data. Otherwise, it returns SLP_FALSE ๐โโ๏ธ
4.3.3. SLPSrvURLCallback
4.3.3.1. Synopsis
typedef SLPBoolean SLPSrvURLCallback(SLPHandle hSLP,
const char* pcSrvURL,
unsigned short sLifetime,
SLPError errCode,
void *pvCookie);
4.3.3.2. Description
SLPSrvURLCallback is the callback type you pass to the SLPFindSrvs() function ๐ง If the hSLP handle was opened asynchronously, the results that come back through the callback MAY be uncollated ๐ธ If it was opened synchronously, the results must be collated and the duplicates eliminated ๐
4.3.3.3. Parameters
hSLPTheSLPHandlethat started the operation.pcSrvURLA character buffer with the returned service URL ๐sLifetimeAn unsigned short with the lifetime of the service advertisement, in seconds. The value must be an unsigned integer that is less than or equal toSLP_LIFETIME_MAXIMUMโณerrCodeAn error code that tells you if something went wrong during the operation. The callback should check this error code before it processes the parameters. If the error code is anything other thanSLP_OK, then the API library may choose to end the outstanding operation ๐จpvCookieMemory the client code passed down from the original API function call that started the operation. It may be NULL.
4.3.3.4. Returns
The client code should return SLP_TRUE if it wants more data. Otherwise, it returns SLP_FALSE ๐
4.3.4. SLPAttrCallback
4.3.4.1. Synopsis
typedef SLPBoolean SLPAttrCallback(SLPHandle hSLP,
const char* pcAttrList,
SLPError errCode,
void *pvCookie);
4.3.4.2. Description
SLPAttrCallback is the callback type you pass to the SLPFindAttrs() function ๐ฆ How the callback behaves depends on whether you asked for attributes by URL or by service type, so pay attention here, bestie ๐
If you called SLPFindAttrs() with a URL, the callback gets called once, no matter whether the handle was opened asynchronously or synchronously. The pcAttrList parameter holds the requested attributes as a comma-separated list. If no attributes matched your original tag list, it's empty ๐ซง
If you called SLPFindAttrs() with a service type, the value of pcAttrList and how often the callback runs depend on whether the handle was opened asynchronously or synchronously. If it was opened asynchronously, the callback gets called every time the API library has results from a remote agent. The pcAttrList parameter MAY be uncollated between calls. Each call has a comma-separated list with the results from whichever agent just returned results ๐ If the handle was opened synchronously, the results must be collated from all the returning agents, and the callback is called once, with pcAttrList set to the collated result ๐
4.3.4.3. Parameters ๐
hSLP: The SLPHandle used to initiate the operation.pcAttrList: A character buffer containing a comma separated, null terminated list of attribute id/value assignments, in SLP wire format; i.e."(attr-id=attr-value-list)"[7] ๐errCode: An error code indicating if an error occurred during the operation. The callback should check this error code before processing the parameters. If the error code is other thanSLP_OK, then the API library may choose to terminate the outstanding operation. ๐จpvCookie: Memory passed down from the client code that called the original API function, starting the operation. May be NULL. ๐
4.3.4.4. Returns
Okay so the client code should return SLP_TRUE if more data is desired, otherwise SLP_FALSE. Simple as that, bestie ๐
4.4. Opening and Closing an SLPHandle ๐ฆ
4.4.1. SLPOpen
4.4.1.1. Synopsis
SLPError SLPOpen(const char *pcLang, SLPBoolean isAsync, SLPHandle
*phSLP);
4.4.1.2. Description
Okay so SLPOpen hands you back a shiny SLPHandle in phSLP for whatever language locale you pass in as pcLang ๐ธ. You tell it with isAsync whether ops on that handle are synchronous or asynchronous. The handle wraps up the language locale for requests going through it, plus any other resources the implementation needs. BUT SLP properties are NOT wrapped up in the handle, they're global ๐. The function returns an SLPError code for how things went, and if it fails, phSLP comes back NULL ๐ญ
Now the handle is one-operation-at-a-time only ๐
โโ๏ธ If the first op was started asynchronously and you try to start another one on that same handle while it's still pending, you get an SLP_HANDLE_IN_USE error back from the API function. SLPClose cancels any outstanding calls on the handle. And if an implementation can't support async (or sync, the other way around) because of memory constraints or no threading support, the SLP_NOT_IMPLEMENTED flag may be returned when isAsync is SLP_TRUE (or SLP_FALSE, respectively) ๐ฅบ
4.4.1.3. Parameters
pcLang: A pointer to an array of characters containing the RFC 1766 Language Tag [6] for the natural language locale of requests and registrations issued on the handle. ๐ฃ๏ธisAsync: An SLPBoolean indicating whether the SLPHandle should be opened for asynchronous operation or not. โณphSLP: A pointer to an SLPHandle, in which the open SLPHandle is returned. If an error occurs, the value upon return is NULL. ๐ซถ
4.4.2. SLPClose
4.4.2.1. Synopsis
void SLPClose(SLPHandle hSLP);
4.4.2.2. Description
SLPClose frees all the resources tied to the handle ๐งน If the handle was invalid, the function just returns silently, no drama ๐คซ Any outstanding synchronous or asynchronous operations get cancelled, so their callback functions will not be called any further. ๐
4.4.2.3. Parameters
SLPHandle: A SLPHandle handle returned from a call to SLPOpen(). ๐
4.5. Protocol API ๐
4.5.1. SLPReg
4.5.1.1. Synopsis
SLPError SLPReg(SLPHandle hSLP,
const char *pcSrvURL,
const unsigned short usLifetime,
const char *pcSrvType,
const char *pcAttrs
SLPBoolean fresh,
SLPRegReport callback,
void *pvCookie);
4.5.1.2. Description
SLPReg registers the URL in pcSrvURL with the lifetime usLifetime and the attribute list in pcAttrs ๐ The pcAttrs list is a comma separated list of attribute assignments in wire format (including escaping of reserved characters). The usLifetime parameter must be nonzero and less than or equal to SLP_LIFETIME_MAXIMUM. If fresh is SLP_TRUE, the registration is brand new (the SLP protocol FRESH flag is set) and it replaces any existing registrations. pcSrvType is a service type name, and it can be included for service URLs that are not in the service: scheme. If the URL is in the service: scheme, pcSrvType is ignored. If fresh is SLP_FALSE, then an existing registration gets updated. Rules for new and updated registrations, plus the format for pcAttrs and pcScopeList, can be found in [7]. Registrations and updates take place in the language locale of the hSLP handle. ๐
The API library is required to perform the operation in all scopes obtained through configuration. โ๏ธ
4.5.1.3. Parameters
hSLP: The language specific SLPHandle on which to register the advertisement. ๐pcSrvURL: The URL to register. May not be the empty string. ๐usLifetime: An unsigned short giving the life time of the service advertisement, in seconds. The value must be an unsigned integer less than or equal toSLP_LIFETIME_MAXIMUMand greater than zero. โฐpcSrvType: The service type. If pURL is a service: URL, then this parameter is ignored. ๐งpcAttrs: A comma separated list of attribute assignment expressions for the attributes of the advertisement. Use empty string,""for no attributes. ๐fresh: An SLPBoolean that isSLP_TRUEif the registration is new orSLP_FALSEif a reregistration. ๐ธcallback: A callback to report the operation completion status. ๐ฃpvCookie: Memory passed to the callback code from the client. May be NULL. ๐ฌ
4.5.1.4. Returns
If an error occurs in starting the operation, one of the SLPError codes is returned. ๐
4.5.2. SLPDereg
4.5.2.1. Synopsis
SLPError SLPDereg(SLPHandle hSLP,
const char *pcURL,
SLPRegReport callback,
void *pvCookie);
4.5.2.2. Description
SLPDereg deregisters the advertisement for URL pcURL in all scopes where the service is registered and in all language locales. The deregistration is not just confined to the locale of the SLPHandle, it's in all locales. Iconic behavior ๐ The API library is required to perform the operation in all scopes obtained through configuration. ๐ซถ
4.5.2.3. Parameters
hSLP: The language specific SLPHandle to use for deregistering. ๐pcURL: The URL to deregister. May not be the empty string. ๐callback: A callback to report the operation completion status. ๐ฃpvCookie: Memory passed to the callback code from the client. May be NULL. ๐ฌ
4.5.2.4. Returns
If an error occurs in starting the operation, one of the SLPError codes is returned. ๐
4.5.3. SLPDelAttrs
4.5.3.1. Synopsis
SLPError SLPDelAttrs(SLPHandle hSLP,
const char *pcURL,
const char *pcAttrs,
SLPRegReport callback,
void *pvCookie);
4.5.3.2. Description
SLPDelAttrs deletes the selected attributes in the locale of the SLPHandle. โ๏ธ The API library is required to perform the operation in all scopes obtained through configuration. ๐
4.5.3.3. Parameters
hSLP: The language specific SLPHandle to use for deleting attributes. ๐งฝpcURL: The URL of the advertisement from which the attributes should be deleted. May not be the empty string. ๐pcAttrs: A comma separated list of attribute ids for the attributes to deregister. See Section 9.8 in [7] for a description of the list format. May not be the empty string. ๐callback: A callback to report the operation completion status. ๐ฃpvCookie: Memory passed to the callback code from the client. May be NULL. ๐ฌ
4.5.3.4. Returns
If an error occurs in starting the operation, one of the SLPError codes is returned. ๐
4.5.4. SLPFindSrvTypes
4.5.4.1. Synopsis
SLPError SLPFindSrvTypes(SLPHandle hSLP,
const char *pcNamingAuthority,
const char *pcScopeList,
SLPSrvTypeCallback callback,
void *pvCookie);
Heads up, bestie: the text below saysSLPFindSrvType()but the synopsis above saysSLPFindSrvTypes. I'm keeping both spellings exactly as the RFC wrote them ๐
The SLPFindSrvType() function issues an SLP service type request for service types in the scopes indicated by the pcScopeList. ๐ The results come back through the callback parameter. The service types are independent of language locale, but only for services registered in one of the scopes and for the indicated naming authority. ๐ท
If the naming authority is "*", then results come back for all naming authorities. If the naming authority is the empty string, i.e. "", then the default naming authority, "IANA", is used. "IANA" is not a valid naming authority name, and it is a PARAMETER_BAD error to include it explicitly. ๐
โโ๏ธ
The service type names come back with the naming authority intact. If the naming authority is the default (i.e. empty string), then it's omitted, and so is the separating ".". Service type names from URLs of the service: scheme come back with the "service:" prefix intact. [7] See [8] for more information on the syntax of service type names. ๐ง
4.5.4.2. Parameters
hSLP: The SLPHandle on which to search for types. ๐ฏpcNamingAuthority: The naming authority to search. Use"*"for all naming authorities and the empty string,"", for the default naming authority. ๐๏ธpcScopeList: A pointer to a char containing comma separated list of scope names to search for service types. May not be the empty string,"". ๐callback: A callback function through which the results of the operation are reported. ๐ฃpvCookie: Memory passed to the callback code from the client. May be NULL. ๐ฌ
4.5.4.3. Returns
If an error occurs in starting the operation, one of the SLPError codes is returned. ๐
4.5.5. SLPFindSrvs
4.5.5.1. Synopsis
SLPError SLPFindSrvs(SLPHandle hSLP,
const char *pcServiceType,
const char *pcScopeList,
const char *pcSearchFilter,
SLPSrvURLCallback callback,
void *pvCookie);
4.5.5.2. Description
Okay so SLPFindSrvs fires off the query for services on the language specific SLPHandle and sends the results back through the callback. The parameters determine the results ๐ฆ
4.5.5.3. Parameters
hSLP: The language specific SLPHandle on which to search for services. ๐pcServiceType: The Service Type String, including authority string if any, for the request, such as can be discovered using SLPSrvTypes(). This could be, for example"service:printer:lpr"or"service:nfs". May not be the empty string. ๐จ๏ธpcScopeList: A pointer to a char containing comma separated list of scope names. May not be the empty string,"". ๐pcSearchFilter: A query formulated of attribute pattern matching expressions in the form of a LDAPv3 Search Filter, see [4]. If this filter is empty, i.e."", all services of the requested type in the specified scopes are returned. โจcallback: A callback function through which the results of the operation are reported. ๐ฃpvCookie: Memory passed to the callback code from the client. May be NULL. ๐ฌ
4.5.5.4. Returns
If an error occurs in starting the operation, one of the SLPError codes is returned. ๐
4.5.6. SLPFindAttrs ๐
4.5.6.1. Synopsis
SLPError SLPFindAttrs(SLPHandle hSLP,
const char *pcURLOrServiceType,
const char *pcScopeList,
const char *pcAttrIds,
SLPAttrCallback callback,
void *pvCookie);
4.5.6.2. Description
okay so SLPFindAttrs() is the function that gets you the attributes for a service, matched against the attribute ids you ask for โจ. You give it either a service URL or a service type, and it hands back the attributes through the callback ๐. If you pass a service URL, you get the attributes for that one particular advertisement, in the language locale of your SLPHandle ๐.
If you pass a service type (naming authority included, if there is one), you get the attributes for every advertisement of that type, no matter what language they were registered in ๐. Again, the results come back through the callback ๐ฆ.
You can also filter the results with an SLP attribute request filter string, and the syntax for that lives in [7] ๐
. If the filter string is the empty string, i.e. "", you get all the attributes back, no notes ๐ซถ.
4.5.6.3. Parameters
hSLP
The language specific SLPHandle you want to search for attributes on ๐ง.
pcURLOrServiceType
The service URL or the service type. Check [7] for the URL and service type syntax ๐. This one MAY NOT be the empty string.
Heads up: "MAY NOT" here is just the plain English way of saying it can't be empty, so it's not a capitalised BCP 14 key word in this version. Don't pass "" ๐ญ.
pcScopeList
A pointer to a char holding a comma separated list of scope names ๐. It may not be the empty string, "".
pcAttrIds
The filter string that says which attribute values you want back โจ. Use the empty string, "", to ask for all of them. Wildcards are also a thing: you can match every attribute id with a particular prefix or suffix ๐ธ. For the exact format of the filter string, go check [7] ๐ฅ.
callback
The callback function where the results of the whole operation get reported ๐ฆ.
pvCookie
Memory that gets passed from the client over to the callback code. It's allowed to be NULL ๐.
4.5.6.4. Returns
If something goes wrong while starting the operation, you get back one of the SLPError codes ๐.
4.6. Miscellaneous Functions
4.6.1. SLPGetRefreshInterval
4.6.1.1. Synopsis
unsigned short SLPGetRefreshInterval();
4.6.1.2. Description
This one returns the biggest min-refresh-interval attribute across all DAs ๐. That number works for the advertised refresh interval bounds of every DA, and if the SA uses it, no refresh registration gets rejected ๐ซถ. If no DA advertises a min-refresh-interval attribute, you get a value of 0 ๐ฅบ.
4.6.1.3. Returns
If there's no error, you get the maximum refresh interval value that all DAs allow (a positive integer) โจ. If no DA advertises a min-refresh-interval attribute, it returns 0. If an error happens, it returns an SLP error code ๐ .
4.6.2. SLPFindScopes
4.6.2.1. Synopsis
SLPError SLPFindScopes(SLPHandle hSLP,
char** ppcScopeList);
4.6.2.2. Description
This sets the ppcScopeList parameter to point at a comma separated list with every available scope value in it ๐. The scopes come from a bunch of places: the configuration file's net.slp.useScopes property, unicast to DAs on the net.slp.DAAddresses property, DHCP, or the DA discovery process ๐ง. If the scopes have any order to them, the preferred ones are listed before the less desirable ones ๐. There is always at least one name in the list, which is the default scope, "DEFAULT" ๐.
4.6.2.3. Parameters
hSLP
The SLPHandle you want to search for scopes on ๐ฆ.
ppcScopeList
A pointer to a char pointer. When the function returns, the buffer pointer gets placed into it ๐. The buffer is null terminated. You should free the memory by calling SLPFree() ๐ซถ.
4.6.2.4. Returns
If nothing goes wrong, it returns SLP_OK. Otherwise you get the right error code ๐ .
4.6.3. SLPParseSrvURL
4.6.3.1. Synopsis
SLPError SLPParseSrvURL(char *pcSrvURL
SLPSrvURL** ppSrvURL);
4.6.3.2. Description
This takes the URL you pass in and parses it into a service URL structure, which it returns through the ppSrvURL pointer ๐ฅ. If a parse error happens, it returns SLP_PARSE_ERROR ๐. The input buffer pcSrvURL gets destructively modified during the parse, and it's used to fill in the fields of the structure you get back ๐. You should free that returned structure with SLPFreeURL() ๐.
If the URL has no service part, the s_pcSrvPart string is the empty string, "", and not NULL ๐ธ. If pcSrvURL is not a service: URL, then the s_pcSrvType field in the returned structure is the URL's scheme. That might not be the same as the service type it was registered under ๐. If the transport is IP, the s_pcTransport field is the empty string ๐ฆ. If the transport is not IP, or there's no port number, the s_iPort field is zero ๐.
4.6.3.3. Parameters
pcSrvURL
A pointer to a character buffer holding the null terminated URL string you want to parse ๐ง. It gets destructively modified to produce the output structure.
ppSrvURL
A pointer to a pointer for the SLPSrvURL structure that will receive the parsed URL ๐. Free the memory with a call to SLPFree() once you're done with it ๐ซถ.
4.6.3.4. Returns
If no error occurs, the return value is SLP_OK โจ. Otherwise, you get the appropriate error code ๐ .
4.6.4. SLPEscape
4.6.4.1. Synopsis
SLPError SLPEscape(const char* pcInbuf,
char** ppcOutBuf,
SLPBoolean isTag);
4.6.4.2. Description
This processes the input string in pcInbuf and escapes any SLP reserved characters ๐. If the isTag parameter is SLPTrue, it looks for bad tag characters, and if it finds any, it signals an error by returning the SLP_PARSE_ERROR code ๐. The results go into a buffer that the API library allocates, and it comes back in the ppcOutBuf parameter ๐. Deallocate that buffer with SLPFree() once you don't need the memory anymore ๐ .
4.6.4.3. Parameters
pcInbuf
Pointer to he input buffer to process for escape characters ๐ง.
ppcOutBuf
Pointer to a pointer for the output buffer, with the SLP reserved characters escaped ๐ฆ. It must be freed using SLPFree() when the memory isn't needed anymore.
isTag
When true, the input buffer is checked for bad tag characters ๐.
4.6.4.4. Returns
It returns SLP_PARSE_ERROR if any characters are bad tag characters and the isTag flag is true ๐. Otherwise it returns SLP_OK, or the appropriate error code if some other error happens ๐.
4.6.5. SLPUnescape
4.6.5.1. Synopsis
SLPError SLPUnescape(const char* pcInbuf,
char** ppcOutBuf,
SLPBoolean isTag);
4.6.5.2. Description
This processes the input string in pcInbuf and unescapes any SLP reserved characters ๐ธ. If the isTag parameter is SLPTrue, it looks for bad tag characters, and if it finds any, it signals an error with the SLP_PARSE_ERROR code ๐. No transformation happens if the input string is an opaque ๐ซถ. The results go into a buffer that the API library allocates, and that comes back in the ppcOutBuf parameter ๐. Deallocate it with SLPFree() when you don't need it anymore ๐ .
4.6.5.3. Parameters
pcInbuf
Pointer to he input buffer to process for escape characters ๐ง.
ppcOutBuf
Pointer to a pointer for the output buffer with the SLP reserved characters escaped ๐ฆ. It must be freed using SLPFree() when the memory isn't needed anymore.
isTag
When true, the input buffer is checked for bad tag characters ๐.
4.6.5.4. Returns
It returns SLP_PARSE_ERROR if any characters are bad tag characters and the isTag flag is true ๐. Otherwise it returns SLP_OK, or the appropriate error code if another error happens ๐.
4.6.6. SLPFree
4.6.6.1. Synopsis
void SLPFree(void* pvMem);
4.6.6.2. Description
This frees memory that came back from SLPParseSrvURL(), SLPFindScopes(), SLPEscape(), and SLPUnescape() ๐งนโจ.
4.6.6.3. Parameters
pvMem
A pointer to the storage allocated by SLPParseSrvURL(), SLPEscape(), SLPUnescape(), or SLPFindScopes() ๐. If it's NULL, it gets ignored ๐.
4.6.7. SLPGetProperty
4.6.7.1. Synopsis
const char* SLPGetProperty(const char* pcName);
4.6.7.2. Description
This returns the value of the matching SLP property name ๐. The string that comes back is owned by the library, and you MUST NOT free it ๐ซ.
4.6.7.3. Parameters
pcName
Null terminated string with the property name, from Section 2.1 ๐ฆ.
4.6.7.4. Returns
If there's no error, it returns a pointer to a character buffer holding the property value ๐. If the property wasn't set, you get the default value ๐ซถ. If an error happens, it returns NULL. The returned string MUST NOT be freed ๐ซ.
4.6.8. SLPSetProperty
4.6.8.1. Synopsis
void SLPSetProperty(const char *pcName,
const char *pcValue);
4.6.8.2. Description
This sets the SLP property to the new value ๐ธ. The pcValue parameter should be the property value as a string โจ.
4.6.8.3. Parameters
pcName
Null terminated string with the property name, from Section 2.1 ๐ง.
pcValue
Null terminated string with the property value, in UTF-8 character encoding ๐.
4.7. Implementation Notes
4.7.1. Refreshing Registrations
okay this one is so good ๐ญ. Clients say they want URLs to be automatically refreshed by setting the usLifetime parameter in the SLPReg() function call to SLP_LIFETIME_MAXIMUM ๐. That makes the API implementation refresh the URL before it times out ๐. Yes, using SLP_LIFETIME_MAXIMUM for automatic reregistration means a transient URL can't be registered for the maximum lifetime ๐. But honestly, little hardship is likely to happen, since service URL lifetimes are measured in seconds, and the client can just use a lifetime of SLP_LIFETIME_MAXIMUM - 1 if it wants a transient URL near the maximum lifetime ๐ซถ. API implementations MUST provide this facility ๐.
4.7.2. Syntax for String Parameters
this section is giving rules, bestie ๐ . Query strings, attribute registration lists, attribute deregistration lists, scope lists, and attribute selection lists all follow the syntax in [7] for the appropriate requests ๐. The API directly reflects the strings clients pass in into protocol requests, and it directly reflects the out strings from protocol replies back to clients ๐ฆ. So clients are responsible for formatting request strings, including escaping and converting opaque values to escaped byte encoded strings ๐ง . On the way out, clients are required to unescape strings and convert escaped string encoded opaques to binary ๐ซถ. SLPEscape() and SLPUnescape() can help with escaping SLP reserved characters, but they don't do any opaque processing ๐ธ.
Opaque values are a character buffer holding a UTF-8-encoded string. The first characters are the nonUTF-8 encoding '\ff' ๐ฅ. After that come the escaped values for the original bytes in the opaque ๐. The escape convention is pretty simple: an escape is a backslash followed by the two hexadecimal digits that encode the byte ๐. For example, '\2c' is the byte 0x2c โจ. Clients handle opaque processing themselves, since the algorithm is relatively simple and uniform ๐.
4.7.3. Client Side Syntax Checking ๐
Okay so, client side API implementations are allowed to do syntax checking on scope names, naming authority names, and service type names, but they're not required to ๐ซถ. The C API is basically a thin layer over the protocol, so some low memory SA implementations might find heavy client side checking kinda burdensome ๐ญ. If syntax checking catches an error in a parameter, the SLP_PARAMETER_BAD error must be returned. And if any parameter is NULL when it's required to be nonNULL, SLP_PARAMETER_BAD gets returned too ๐
.
4.7.4. System Properties โ๏ธ
The system properties set up in the configuration file are reachable through SLPGetProperty() and SLPSetProperty() ๐ง. SLPSetProperty() only changes properties in the running process, not in the configuration file, so it's not a sneaky way to rewrite the config ๐
โโ๏ธ.
Properties are global to the whole process, so they affect all threads and all handles created with SLPOpen ๐งต. Errors get checked when a property is actually used and, same as parsing the configuration file, they get logged ๐. The program keeps going without interruption by swapping in the default for the erroneous parameter ๐.
With the exception of net.slp.locale, net.slp.typeHint, and net.slp.maxResults, clients of the API should rarely have to override these, since they describe properties of the SLP network that individual agents don't really need to care about ๐. If changes are required, system administrators should modify the configuration file.
4.7.5. Memory Management ๐งน
The only API functions that return memory clients actually have to deallocate are SLPParseSrvURL(), SLPFindScopes(), SLPEscape(), and SLPUnescape() ๐๏ธ. That memory should be freed with SLPFree() once you're done with it. Character strings returned from SLPGetProperty() should NOT be freed, since they're owned by the SLP library, so hands off ๐๏ธ.
๐จ Memory passed to callbacks belongs to the library and MUST NOT be retained by client code. Otherwise, crashes are possible ๐. Clients are required to copy data out of the callback parameters. No other use of the parameter memory in callback parameters is allowed.
4.7.6. Asynchronous and Incremental Return Semantics ๐
If a handle parameter to an API function was opened asynchronously, the API function call checks the other parameters, opens the appropriate operation, and returns immediately. If an error occurs while starting the operation, an error code is returned โก. If the handle parameter was opened synchronously, the API function call blocks until all results are available, and it only returns after the results have been reported through the callback function. The return code tells you whether any errors happened both while starting and during the operation ๐.
The callback function gets called whenever the API library has results to report ๐ฃ. The callback code is required to check the error code parameter before looking at the other parameters. If the error code is not SLP_OK, the other parameters may be invalid, so be careful bestie ๐ฌ. The API library has the option of terminating any outstanding operation on which an error occurs. The callback code can similarly indicate that the operation should be terminated by passing back SLP_FALSE.
Callback functions are not permitted to recursively call into the API on the same SLPHandle. If an attempt is made to recursively call into the API, the API function returns SLP_HANDLE_IN_USE ๐ซ. Why no recursion? Because banning it makes thread safe code way simpler, since locks held on the handle won't be in place during a second outcall on the handle ๐. The tradeoff is that handle creation should be fairly lightweight, so a client program can easily support multiple outstanding calls ๐ฆ.
The total number of results received can be controlled by setting the net.slp.maxResults parameter ๐ฏ.
On the last call to a callback, whether it's asynchronous or synchronous, the status code passed to the callback has value SLP_LAST_CALL ๐. There are four reasons why the call can terminate:
- DA reply received
- A reply from a DA has been received and therefore nothing more is expected.
- Multicast terminated
- The multicast convergence time has elapsed and the API library multicast code is giving up.
- Multicast null results
- Nothing new has been received during multicast for a while and the API library multicast code is giving up on that (as an optimization).
- Maximum results
- The user has set the
net.slp.maxResultsproperty and that number of replies has been collected and returned.
- The user has set the
4.8. Example ๐ฌ
This example illustrates how to discover a mailbox, and it's giving main character energy ๐.
A POP3 server registers itself with the SLP framework. The attributes it registers are "USER", a list of all users whose mail is available through the POP3 server ๐.
The POP3 server code is the following:
SLPHandle slph;
SLPRegReport errCallback = POPRegErrCallback;
/* Create an English SLPHandle, asynchronous processing. */
SLPError err = SLPOpen("en", SLP_TRUE, &slph);
if( err != SLP_OK ) {
/* Deal with error. */
}
/* Create the service: URL and attribute parameters. */
const char* surl = "service:pop3://mail.netsurf.de"; /* the URL */
const char *pcAttrs = "(user=zaphod,trillian,roger,marvin)"
/* Perform the registration. */
err = SLPReg(slph,
surl,
SLP_LIFETIME_DEFAULT,
ppcAttrs,
errCallback,
NULL);
if (err != SLP_OK ) {
/*Deal with error.*/
}
The errCallback reports any errors ๐จ:
void
POPRegErrCallback(SLPHandle hSLP,
SLPError errCode,
unsigned short usLifetime,
void* pvCookie) {
if( errCode != SLP_OK ) {
/* Report error through a dialog, message, etc. */
}
/*Use lifetime interval to update periodically. */
}
The POP3 client locates the server for the user with the following code ๐:
/*
* The client calls SLPOpen(), exactly as above.
*/
const char *pcSrvType = "service:pop3"; /* the service type */
const char *pcScopeList = "default"; /* the scope */
const char *pcFilter = "(user=roger)"; /* the search filter */
SLPSrvURLCallback srvCallback = /* the callback */
POPSrvURLCallback;
err = SLPFindSrvs(slph,
pcSrvType, pcScopeList, pcFilter,
srvCallback, NULL);
if( err != SLP_OK ) {
/* Deal with error. */
}
Within the callback, the client code can use the returned POP service ๐:
SLPBoolean
POPSrvURLCallback(SLPHandle hSLP,
const char* pcSrvURL,
unsigned short sLifetime,
SLPError errCode,
void* pvCookie) {
if( errCode != SLP_OK ) {
/* Deal with error. */
}
SLPSrvURL* pSrvURL;
errCode = SLPParseSrvURL(pcSrvURL, &pSrvURL);
if (err != SLP_OK ) {
/* Deal with error. */
} else {
/* get the server's address */
struct hostent *phe = gethostbyname(pSrvURL.s_pcHost);
/* use hostname in pSrvURL to connect to the POP3 server
* . . .
*/
SLPFreeSrvURL((void*)pSrvURL); /* Free the pSrvURL storage */
}
return SLP_FALSE; /* Done! */
}
A client that wanted to discover all the users receiving mail at the server uses the following query ๐ฅ:
/*
* The client calls SLPOpen(), exactly as above. We assume the
* service: URL was retrieved into surl.
*/
const char *pcScopeList = "default"; /* the scope */
const char *pcAttrFilter = "use"; /* the attribute filter */
SLPAttrCallback attrCallBack = /* the callback */
POPUsersCallback
err =
SLPFindAttrs(slph,
surl,
pcScopeList, pcAttrFilter,
attrCallBack, NULL);
if( err != SLP_OK ) {
/* Deal with error. */
}
The callback processes the attributes ๐งพ:
SLPBoolean
POPUsersCallback(const char* pcAttrList,
SLPError errCode,
void* pvCookie) {
if( errCode != SLP_OK ) {
/* Deal with error. */
} else {
/* Parse attributes. */
}
return SLP_FALSE; /* Done! */
}
5. Java Language Binding โ
5.1. Introduction ๐ธ
The Java API is designed to model the various SLP entities in classes and objects ๐ง. APIs are provided for SA, UA, and service type template access capabilities. The ServiceLocationManager class contains methods that return instances of objects implementing SA and UA capability. Each of these is modeled in an interface. The Locator interface provides UA capability and the Advertiser interface provides SA capability. The TemplateRegistry abstract class contains methods that return objects for template introspection and attribute type checking. The ServiceURL, ServiceType, and ServiceLocationAttribute classes model the basic SLP concepts. A concrete subclass instance of TemplateRegistry is returned by a class method โจ.
All SLP classes and interfaces are located within a single package. The package name should begin with the name of the implementation and conclude with the suffix "slp". Thus, the name for a hypothetical implementation from the University of Michigan would look like:
edu.umich.slp
This follows the Java convention of prepending the top level DNS domain name for the organization implementing the package onto the organization's name and using that as the package prefix ๐.
5.2. Exceptions and Errors ๐
Most parameters to API methods are required to be non-null. The API description indicates if a null parameter is acceptable, or if other restrictions constrain a parameter. When parameters are checked for validity (such as not being null) or their syntax is checked, an error results in the RuntimeException subclass IllegalArgumentException being thrown. Clients of the API are reminded that IllegalArgumentException, derived from RuntimeException, is unchecked by the compiler. Clients should thus be careful to include try/catch blocks for it if the relevant parameters could be erroneous ๐ซ .
Standard Java practice is to encode every exceptional condition as a separate subclass of Exception. Because of the relatively high cost in code size of Exception subclasses, the API contains only a single Exception subclass, with different conditions being determined by an integer error code property ๐งฎ. A subset, appropriate to Java, of the error codes described in Section 3 are available as constants on the ServiceLocationException class. The subset excludes error codes such as MEMORY_ALLOC_FAILED ๐ซ.
5.2.1. Class ServiceLocationException ๐
5.2.1.1. Synopsis
public class ServiceLocationException
extends Exception
5.2.1.2. Description
The ServiceLocationException class is thrown by all methods when exceptional conditions occur in the SLP framework ๐จ. The error code property determines the exact nature of the condition, and an optional message may provide more information ๐
.
5.2.1.3. Fields โจ
Okay so these are the error codes, bestie, and each one is a static field on the class ๐ Here they are, all lined up:
public static final short LANGUAGE_NOT_SUPPORTED = 1
public static final short PARSE_ERROR = 2
public static final short INVALID_REGISTRATION = 3
public static final short SCOPE_NOT_SUPPORTED = 4
public static final short AUTHENTICATION_ABSENT = 6
public static final short AUTHENTICATION_FAILED = 7
public static final short INVALID_UPDATE = 13
public static final short REFRESH_REJECTED = 15
public static final short NOT_IMPLEMENTED = 16
public static final short NETWORK_INIT_FAILED 17
public static final short NETWORK_TIMED_OUT = 18
public static final short NETWORK_ERROR = 19
public static final short INTERNAL_SYSTEM_ERROR = 20
public static final short TYPE_ERROR = 21
public static final short BUFFER_OVERFLOW = 22
5.2.1.4. Instance Methods ๐
Here's the one method you'll reach for, getErrorCode() ๐ฆ
public short getErrorCode()
It just hands back the error code, and that code is always one of the static field values up above. Iconic, honestly ๐
5.3. Basic Data Structures ๐ธ
5.3.1. Interface ServiceLocationEnumeration ๐ง
public interface ServiceLocationEnumeration
extends Enumeration
5.3.1.1. Description
Okay, so ServiceLocationEnumeration is the return type for every single Locator SLP operation ๐ The Java API library is allowed to make it block until results show up, which means the client can go async by pulling results out of the enumeration on a separate thread. โจ If a client doesn't care about SLP exceptions, it can just use the superclass nextElement() method instead ๐
5.3.1.2. Instance Methods
public abstract Object next() throws ServiceLocationException
This returns the next value, or blocks until one is ready ๐ซถ
Throws:
ServiceLocationException: thrown if the SLP operation runs into an error.NoSuchElementException: thrown if there are no more elements to return.
5.3.2. Class ServiceLocationAttribute ๐
5.3.2.1. Synopsis
public class ServiceLocationAttribute
extends Object implements Serializable
5.3.2.2. Description
This class models SLP attributes, and it's giving main character energy ๐ฆ You get instances back from Locator.findAttributes(), and they also travel along with register and deregister requests ๐
5.3.2.3. Constructors
public ServiceLocationAttribute(String id,Vector values)
This builds a service location attribute. Any errors in the id or values vector result in an IllegalArgumentException ๐ญ
Parameters:
id: the attribute name. The String can be made of any Unicode character ๐values: a Vector holding one or more attribute values. The contents must all be the same type, and that type has to be one of Integer, String, Boolean, or byte[]. If the attribute is a keyword attribute, the parameter should be null. String values can be made of any Unicode character too ๐
5.3.2.4. Class Methods
public static String escapeId(String id)
This returns an escaped version of the id parameter, ready to drop into a query โจ Any reserved characters from [7] get escaped using UTF-8 encoding. If any characters in the tag are illegal, it throws an IllegalArgumentException. ๐
Parameters:
id: the attribute id you want to escape. AServiceLocationExceptionis thrown if any characters are illegal for an attribute tag.
public static String escapeValue(Object value)
This returns a String with the escaped value parameter, also ready for a query ๐ซถ If the parameter is a string, any reserved characters from [7] get escaped using UTF-8 encoding. If the parameter is a byte array, the escaped string starts with the nonUTF-8 sequence \ff, and the rest of the string is the escaped bytes, which is the encoding for opaques ๐ฅ If the value parameter is a Boolean or Integer, the returned string is just that object converted into a string. If the value is any type other than String, Integer, Boolean or byte[], you get an IllegalArgumentException ๐
โโ๏ธ
Parameters:
value: the attribute value to be converted into a string and escaped.
5.3.2.5. Instance Methods
public Vector getValues()
This returns a cloned vector of attribute values, or null if the attribute is a keyword attribute ๐ If the attribute is single-valued, the vector only contains one object.
public String getId()
This returns the attribute's name ๐ธ
public boolean equals(Object o)
This overrides Object.equals(). Two attributes are equal if their identifiers are equal and their value vectors contain the same number of equal values, as judged by the Object equals() method. Byte[] values count as equal if the contents of all the byte arrays in both attribute vectors match. โญ Heads up, though: the SLP string matching algorithm [7] MUST NOT be used for comparing attribute identifiers or string values. That's a hard no ๐
โโ๏ธ
public String toString()
This overrides Object.toString(). The string it returns has a formatted representation of the attribute, showing its id, its values, and the Java type of those values ๐ง It's great for debugging, but it is not in SLP wire format, so don't go sending it over the wire ๐ญ
public int hashCode()
This overrides Object.hashCode(), and it hashes on the attribute's identifier ๐ฆ
5.3.3. Class ServiceType ๐
5.3.3.1. Synopsis
public class ServiceType extends Object implements Serializable
5.3.3.2. Description
The ServiceType object models the SLP service type ๐ It takes a string-based service type specifier and breaks it into its components, and then it gives you property accessors to get those components back. URL schemes, protocol service types, and abstract service types are all handled ๐
5.3.3.3. Constructors
public ServiceType(String type)
This constructs a service type object from the service type specifier. It throws an IllegalArgumentException if the type name is syntactically incorrect ๐
Parameters:
type: the service type name as a String. If the service type comes from aservice:URL, the"service:"prefix has to stay intact ๐ซถ
5.3.3.4. Methods
public boolean isServiceURL()
This returns true if the type name contains the "service:" prefix ๐
public boolean isAbstractType()
This returns true if the type name is for an abstract type ๐
public boolean isNADefault()
This returns true if the naming authority is the default, i.e. is the empty string โจ
public String getConcreteTypeName()
This returns the concrete type name in an abstract type, or the empty string if the service type isn't abstract ๐ธ For example, if the type name is "service:printing:ipp", the method returns "ipp". If the type name is "service:ftp", the method returns "". ๐ง
public String getPrincipleTypeName()
This returns the abstract type name for an abstract type, the protocol name in a protocol type, or the URL scheme for a generic URL ๐ For example, in the abstract type name "service:printing:ipp", the method returns "printing". In the protocol type name "service:ftp", the method returns "ftp". ๐ฆ
public String getAbstractTypeName()
If the type is an abstract type, this returns the fully formatted abstract type name, including the "service:" and the naming authority, but without the concrete type name or the intervening colon ๐ฅ If it isn't an abstract type, it returns the empty string. For example, in the abstract type name "service:printing:ipp", the method returns "service:printing". ๐
public String getNamingAuthority()
This returns the naming authority name, or the empty string if the naming authority is the default ๐
public boolean equals(Object obj)
This overrides Object.equals(). The two objects are equal if they are both ServiceType objects and all of their components match ๐ซถ
public String toString()
This returns the fully formatted type name, including the "service:" if the type was originally from a service: URL ๐
public int hashCode()
This overrides Object.hashCode(). It hashes on the string value of the "service" prefix, the naming authority (if any), the abstract and concrete type names for abstract types, the protocol type name for protocol types, and the URL scheme for generic URLs ๐
5.3.4. Class ServiceURL ๐ง
5.3.4.1. Synopsis
public class ServiceURL extends Object implements Serializable
5.3.4.2. Description
The ServiceURL object models the advertised SLP service URL ๐ฆ It can be either a service: URL or a regular URL. You get these objects back from service lookup requests, and they describe the registered services ๐ธ This class ought to be a subclass of java.net.URL, but it can't be, because that class is final ๐ญ
5.3.4.3. Class Variables
public static final int NO_PORT = 0
This means no port information is required, or none was returned for this URL ๐
public static final int LIFETIME_NONE = 0
This means the URL has a zero lifetime ๐ The API never actually returns this value, but you can use it to build a ServiceURL object for deregistering, deleting attributes, or finding attributes โจ
public static final int LIFETIME_DEFAULT = 10800
This is the default URL lifetime, which is 3 hours in seconds ๐
public static final int LIFETIME_MAXIMUM = 65535
This is the maximum URL lifetime, which is about 18 hours in seconds ๐
public static final int LIFETIME_PERMANENT = -1
This means the API implementation should keep re-registering the URL continuously until the application exits ๐ฅ
5.3.4.4. Constructors
public ServiceURL(String URL,int lifetime)
This constructs a service URL object with the lifetime you specify ๐
Parameters:
URL: the URL as a string. It must be either aservice:URL or a valid generic URL according to RFC 2396 [2] ๐ซถlifetime: the service advertisement lifetime in seconds. This value may be betweenLIFETIME_NONEandLIFETIME_MAXIMUM๐
5.3.4.5. Methods
public ServiceType getServiceType()
This returns the service type object representing the service type name of the URL ๐ง
public final void setServiceType(ServiceType type)
throws ServiceLocationException
This sets the service type name on the object. It's ignored if the URL is a service: URL ๐
Parameters:
type: the service type object.
public String getTransport()
This gets the network layer transport identifier. If the transport is IP, an empty string, "", is returned ๐ฆ
public String getHost()
This returns the host identifier. For IP, this is the machine name or IP address ๐ธ
public int getPort()
This returns the port number, if there is one. For non-IP transports, it always returns NO_PORT ๐
public String getURLPath()
This returns the URL path description, if there is one ๐
public int getLifetime()
This returns the service advertisement lifetime. It will be a positive int between LIFETIME_NONE and LIFETIME_MAXIMUM โญ
public boolean equals(Object obj)
This compares the object to the ServiceURL and returns true if the two are the same. Two ServiceURL objects are equal if their current service types match and they have the same host, port, transport, and URL path ๐ซถ
public String toString()
This returns a formatted string with the URL, overriding Object.toString(). The returned URL carries the original service type or URL scheme, not the current service type ๐
public int hashCode()
This overrides Object.hashCode(). It hashes on the current service type, transport, host, port, and URL part ๐ง
5.4. SLP Access Interfaces ๐
5.4.1. Interface Advertiser ๐
5.4.1.1. Synopsis
public interface Advertiser
5.4.1.2. Description ๐
okay bestie, the Advertiser is the SA interface ๐ so this is where clients sign up new service instances with SLP, tweak the attributes of services that already exist, and take services off the list when they're done ๐ซถ new registrations and attribute changes happen in the language locale the Advertiser was created with ๐ธ but deregistrations hit every locale ๐ no cap, that's a big difference.
5.4.1.3. Instance Methods โจ
public abstract Locale getLocale()
Returns the language locale this object was created with ๐
public abstract void register(ServiceURL URL,
Vector attributes)
throws ServiceLocationException
Registers a new service with SLP, using the attributes you hand it ๐ฆ
The API library is required to do this in every scope it gets from configuration ๐
Parameters:
URL: the URL for the service.attributes: a vector of ServiceLocationAttribute objects that describe the service.
public abstract void deregister(ServiceURL URL)
throws ServiceLocationException
Takes a service off SLP entirely ๐ this deregisters it from every language locale, not just one ๐ญ The API library is required to do this in all scopes obtained through configuration.
Parameters:
URL: the URL for the service.
public abstract void
addAttributes(ServiceURL URL,
Vector attributes)
throws ServiceLocationException
Updates an existing registration by adding new attributes โจ The API library is required to do this in all scopes obtained through configuration.
Parameters:
URL: the URL for the service.attributes: a Vector of ServiceLocationAttribute objects to add to the existing registration. Pass an empty vector if you only want to update the URL on its own. It may not be null ๐
public abstract void
deleteAttributes(ServiceURL URL,
Vector attributeIds)
throws ServiceLocationException
Removes attributes from a URL, but only for the locale the Advertiser was created with ๐ The API library is required to do this in all scopes obtained through configuration.
Parameters:
URL: the URL for the service.attributeIds: a vector of Strings naming the ids of the attributes to remove. Each string can be an attribute id or a wildcard pattern that matches ids, and the syntax for those patterns is in [7] ๐ง The strings can include SLP reserved characters, and the API escapes them before they go over the wire. It may not be the empty vector or null.
5.4.2. Interface Locator ๐ฆ
5.4.2.1. Synopsis
public interface Locator
5.4.2.2. Description
the Locator is the UA interface, and it's the one clients use to ask SLP questions ๐ what service types exist, which service instances are around, and what attributes an instance or a service type has ๐ queries for services and attributes run in the locale the Locator was created with ๐ธ queries for service types don't care about locale at all, so they work the same everywhere ๐ซถ
5.4.2.3. Instance Methods ๐
public abstract Locale getLocale()
Returns the language locale this object was created with ๐
public abstract ServiceLocationEnumeration
findServiceTypes(String namingAuthority,
Vector scopes)
throws ServiceLocationException
Gives back an enumeration of ServiceType objects for the given scopes and naming authority ๐ฅ If nothing matches, you get an empty enumeration, which is totally fine ๐
Parameters:
namingAuthority: the naming authority. Use""for the default naming authority and"*"for all naming authorities.scopes: a Vector of scope names. Pick these from what a findScopes() call gives you. Use"DEFAULT"for the default scope.
public abstract ServiceLocationEnumeration
findServices(ServiceType type,
Vector scopes,
String searchFilter)
throws ServiceLocationException
Returns a vector of ServiceURL objects for services that match the query and have a matching type in the given scopes โจ If nothing is found, you get an empty enumeration ๐ง
Parameters:
type: the SLP service type of the service.scopes: a Vector of scope names. Pick these from what a findScopes() call gives you. Use"DEFAULT"for the default scope.searchFilter: an LDAPv3 [4] string encoded query. If the filter is empty, meaning"", every service of the requested type in the specified scopes comes back ๐ SLP reserved characters must be escaped in the query. Use ServiceLocationAttribute.escapeId() and ServiceLocationAttribute.escapeValue() to build the query.
public abstract ServiceLocationEnumeration
findAttributes(ServiceURL URL,
Vector scopes,
Vector attributeIds)
throws ServiceLocationException
For the URL and scope, you get back a Vector of ServiceLocationAttribute objects whose ids match the String patterns in attributeIds ๐ฆ The request goes out in the Locator's locale ๐ธ If no attributes match, you get an empty enumeration.
Parameters:
URL: the URL you want the attributes for.scopes: a Vector of scope names. Pick these from what a findScopes() call gives you. Use"DEFAULT"for the default scope.attributeIds: a Vector of String patterns that identify the attributes you want. An empty vector means return all attributes ๐ As described in [7], the patterns can use wildcards to match substrings. The strings can include SLP reserved characters, and the API escapes them before transmission.
public abstract ServiceLocationEnumeration
findAttributes(ServiceType type,
Vector scopes,
Vector attributeIds)
throws ServiceLocationException
For the type and scope, you get back a Vector of every ServiceLocationAttribute object whose ids match the String patterns in attributeIds, no matter what the Locator's locale is ๐ The request ignores language locale completely ๐ If no attributes are found, you get an empty vector.
Parameters:
serviceType: the service type.scopes: a Vector of scope names. Pick these from what a findScopes() call gives you. Use"DEFAULT"for the default scope.attributeIds: a Vector of String patterns that identify the attributes you want. An empty vector means return all attributes. As described in [7], the patterns can use wildcards to match all prefixes or suffixes. The patterns can include SLP reserved characters, and the API escapes them before transmission ๐
5.5. The Service Location Manager ๐
5.5.1. Class ServiceLocationManager
5.5.1.1. Synopsis
public class ServiceLocationManager
extends Object
5.5.1.2. Description
the ServiceLocationManager is the gatekeeper for the whole service location framework ๐ง clients get their Locator and Advertiser objects (for UA and SA) from it, and they get the Vector of known scope names from it too ๐
5.5.1.3. Class Methods ๐ฅ
public static int getRefreshInterval()
throws ServiceLocationException
Returns the maximum min-refresh-interval attribute value across all DAs ๐ That value satisfies the advertised refresh interval bounds for every DA, and if the SA uses it, no refresh registration will get rejected ๐ซถ If no DA advertises a min-refresh-interval attribute, you get back 0.
public static Vector findScopes()
throws ServiceLocationException
Returns a Vector of strings with every available scope name ๐ธ The list pulls from a bunch of different sources, and Section 2.1 has the scope discovery algorithm if you want the details ๐ฆ There is always at least one string in the Vector, and that's the default scope, "DEFAULT" โจ
public static Locator
getLocator(Locale locale)
throws ServiceLocationException
Returns a Locator object for the given language Locale ๐ If the implementation doesn't support UA functionality, it returns null ๐ญ
Parameters:
locale: the language locale of the Locator. The default SLP locale is used if this is null.
public static Advertiser
getAdvertiser(Locale locale)
throws ServiceLocationException
Returns an Advertiser object for the given language locale ๐ If the implementation doesn't support SA functionality, it returns null.
Parameters:
locale: the language locale of the Advertiser. The default SLP locale is used if this is null.
5.6. Service Template Introspection ๐ง
5.6.1. Abstract Class TemplateRegistry
5.6.1.1. Synopsis
public abstract class TemplateRegistry
5.6.1.2. Description
Subclasses of the TemplateRegistry abstract class give you access to service location templates [8] ๐ TemplateRegistry classes do a few jobs ๐ they manage how service type template documents get registered and accessed, and they build attribute verifiers out of service templates so you can verify attributes and introspect template documents ๐ฅ Heads up, though: clients of the Advertiser don't have to verify attributes before registering ๐ (you might still get a TYPE_ERROR if the implementation supports type checking and something doesn't match the template) ๐
5.6.1.3. Class Methods ๐
public static TemplateRegistry getTemplateRegistry();
Returns the distinguished TemplateRegistry object for doing operations on and with service templates ๐ If the implementation doesn't support TemplateRegistry functionality, it returns null ๐ฅบ
5.6.1.4. Instance Methods โจ
Okay bestie, here are the instance methods on the template registry, and they're the main event ๐
public abstract void
registerServiceTemplate(ServiceType type,
String documentURL,
Locale locale,
String version)
throws ServiceLocationException
This one registers the service template with the template registry ๐
type: the service type.documentURL: aStringwith the URL of the template document. Itmay notbe the empty string ๐locale: aLocaleobject with the language locale of the template ๐ธversion: the version number identifier of the template document ๐ฅ
public abstract void
deregisterServiceTemplate(ServiceType type,
Locale locale,
String version)
throws ServiceLocationException
This one deregisters the template for the service type ๐ฆ
type: the service type.locale: aLocaleobject with the language locale of the template.version: aStringwith the version number. Passnullto mean the latest version ๐
public abstract
String findTemplateURL(ServiceType type,
Locale locale,
String version)
throws ServiceLocationException
This one returns the URL for the template document ๐ง
type: the service type.locale: aLocaleobject with the language locale of the template.version: aStringwith the version number. Passnullto mean the latest version โจ
public abstract
ServiceLocationAttributeVerifier
attributeVerifier(String documentURL)
throws ServiceLocationException
This one reads the template document URL and hands back an attribute verifier for the service type. Main character energy ๐ The verifier can be used to check that registration attributes match the template, and to introspect on the template definition ๐
documentURL: aStringwith the template document's URL. Itmay notbe the empty string.
5.6.2. Interface ServiceLocationAttributeVerifier ๐ฆ
5.6.2.1. Synopsis
public interface ServiceLocationAttributeVerifier
5.6.2.2. Description
Okay so the ServiceLocationAttributeVerifier is basically your access pass to service templates ๐ Classes that implement it parse SLP template definitions, give you info on attribute definitions for service types, and check whether a ServiceLocationAttribute object matches a template for a particular service type. Clients get their ServiceLocationAttributeVerifier objects for specific SLP service types through the TemplateRegistry ๐
5.6.2.3. Instance Methods
public abstract ServiceType getServiceType()
Returns the SLP service type this verifier is for ๐
public abstract Locale getLocale()
Returns the language locale of the template ๐ธ
public abstract String getVersion()
Returns the template version number identifier ๐ฅ
public abstract String getURLSyntax()
Returns the URL syntax expression for the service: URL ๐
public abstract String getDescription()
Returns the descriptive help text for the template ๐
public abstract ServiceLocationAttributeDescriptor
getAttributeDescriptor(String attrId)
Returns the ServiceLocationAttributeDescriptor for the attribute with the given id. If there's no such attribute in this template, it returns null. This one is mostly for GUI tools that want to show attribute info ๐ง If you're checking attributes in code, use the verifyAttribute() method instead, bestie ๐ซถ
public abstract Enumeration
getAttributeDescriptors()
Returns an Enumeration that lets you introspect on the attribute definitions in the service template. It hands back ServiceLocationAttributeDescriptor objects for the attributes โจ Same deal as above: this is mostly for GUI tools to display attribute info, and programmatic checks should use verifyAttribute() ๐
public abstract void
verifyAttribute(
ServiceLocationAttribute attribute)
throws ServiceLocationException
Verifies that the attribute matches the template definition. If it doesn't match, a ServiceLocationException is thrown with the error code ServiceLocationException.PARSE_ERROR ๐ญ
attribute: theServiceLocationAttributeobject to be verified.
public abstract void
verifyRegistration(
Vector attributeVector)
throws ServiceLocationException
Verifies that the Vector of ServiceLocationAttribute objects matches the template for this service type ๐ The vector MUST contain all the required attributes, and all attributes MUST match their template definitions. If the attributes don't match, a ServiceLocationException is thrown with the error code ServiceLocationException.PARSE_ERROR ๐
attributeVector: aVectorofServiceLocationAttributeobjects for the registration.
Heads up: the vector has to hit every required attribute. Missing one is a no-go, no cap ๐
5.6.3. Interface ServiceLocationAttributeDescriptor ๐ง
5.6.3.1. Synopsis
public interface
ServiceLocationAttributeDescriptor
5.6.3.2. Description
This interface gives you introspection on a template attribute definition ๐ฆ Classes that implement ServiceLocationAttributeDescriptor return info about one particular service location attribute definition from the service template. It's mostly for GUI tools ๐ธ For programmatic attribute verification, you should go through the ServiceLocationAttributeVerifier instead ๐
5.6.3.3. Instance Methods
public abstract String getId()
Returns a String with the attribute's id ๐
public abstract String getValueType()
Returns a String with the fully package-qualified Java type of the attribute. SLP types get translated into Java types like this:
STRING:"java.lang.String"INTEGER:"java.lang.Integer"BOOLEAN:"java.lang.Boolean"OPAQUE:"[B"(i.e. array of byte,byte[])KEYWORD: empty string,""
public abstract String getDescription()
Returns a String with the attribute's help text ๐ฅ
public abstract Enumeration
getAllowedValues()
Returns an Enumeration of the allowed values for the attribute type. For keyword attributes it returns null. For no allowed values (i.e. unrestricted) it returns an empty Enumeration ๐
public abstract Enumeration
getDefaultValues()
Returns an Enumeration of the default values for the attribute type. For keyword attributes it returns null. For no allowed values (i.e. unrestricted) it returns an empty Enumeration โจ
public abstract boolean
getRequiresExplicitMatch()
Returns true if the "X"" flag is set. That means the attribute should be included in any Locator.findServices() request search filter ๐
public abstract boolean getIsMultivalued()
Returns true if the "M" flag is set ๐
public abstract boolean getIsOptional()
Returns true if the "O"" flag is set ๐ง
public abstract boolean getIsLiteral()
Returns true if the "L" flag is set ๐
public abstract boolean getIsKeyword()
Returns true if the attribute is a keyword attribute ๐ธ
5.7. Implementation Notes ๐
5.7.1. Refreshing Registrations
There's a special lifetime constant, ServiceURL.LIFETIME_PERMANENT, that clients use to say the URL should get automatically refreshed until the application exits ๐ฅ The API implementation should read this as meaning the URL lifetime is ServiceURL.LIFETIME_MAXIMUM, and it MUST arrange for automatic refresh to happen ๐ซถ
5.7.2. Parsing Alternate Transports in ServiceURL
The ServiceURL class is built to handle multiple transports ๐ฆ The standard API does no extra processing on transports other than IP, except to split out the host identifier and the URL path. Implementations are free to subclass ServiceURL and add methods for more detailed parsing of alternate transport info ๐ For IP transport, the port number (if there is one) comes back from the getPort() method. For non-IP transports, getPort() returns NO_PORT ๐
5.7.3. String Attribute Values
Generally, translating Java types for attribute values into the SLP on-the-wire string is pretty straightforward ๐
But there are two corner cases, and they're lowkey tricky ๐ If the Java attribute value type is String and the string has an on-the-wire representation that SLP infers as an integer, the registered value might not be what the API client meant ๐ญ A similar problem happens if the Java attribute value is the string "true" or "false", because then the on-the-wire representation gets inferred as boolean. To handle these, the Java API adds a space to the front of the string. So if the string attribute value is "123", the Java API changes it to "123 ", and SLP infers that as a string โจ Since leading and trailing spaces have no effect on query handling, this shouldn't cause any problems with queries ๐ API clients do need to know the transformation is happening, though ๐ซถ
5.7.4. Client Side Syntax Checking
The syntax of scope names, service type names, naming authority names, and URLs is described in [7] and [8] ๐ The various methods and classes that take String parameters for these entities SHOULD type check the parameters for syntax errors on the client side, and throw an IllegalArgumentException if there's an error ๐ Also, character escaping SHOULD be implemented before network transmission for escapable characters in attribute ids and String values ๐ธ This cuts down on the number of error messages sent over the wire ๐ฅ The ServiceLocationAttribute class has methods that let clients grab escaped attribute id and value strings to make query construction easier ๐ง
5.7.5. Language Locale Handling
The Locator and Advertiser interfaces are created with a Locale parameter ๐ The language locale they're created with gets used in all SLP requests issued through that object. If the Locale parameter is null, the default SLP locale is used ๐ To find the default SLP locale, it first checks the net.slp.locale System property ๐
If that's unset, the default SLP locale [7] is used, which is "en" ๐ Heads up: the default SLP locale might not be the same as the default Java locale ๐
5.7.6. Setting SLP System Properties โจ
okay so SLP system properties that get set in the configuration file can be overridden inside API clients, and it's honestly so easy ๐
You just call System.getProperties() to grab a copy of the system properties, then modify or add the SLP property you want, and finally use System.setProperties() to set things to that modified Property object. Program execution keeps going without interruption, and if a parameter is erroneous, the default gets substituted in its place ๐ซถ Errors are checked when the property is actually used, and they get logged.
bestie, the SLP configuration file can't be read with the java.util.Properties file reader ๐ The reason is that there are some syntactic differences. The SLP configuration file defines a different escape convention for non-ASCII characters than the Java syntax does. Once the file has been read, though, the properties get stored and retrieved from java.util.Properties objects, so it all works out in the end ๐
Properties are global for a process, which means they affect all threads and all Locator and Advertiser objects obtained through the ServiceLocationManager ๐ธ With the exception of the net.slp.locale, net.slp.typeHint, and net.slp.maxResults properties, clients should rarely need to override these, since they reflect properties of the SLP network that aren't really the concern of individual agents. If changes are required, system administrators should modify the configuration file. That's the vibe โจ
5.7.7. Multithreading ๐ฆ
Thread-safe operation is relatively easy to achieve in Java, and it's giving very doable energy ๐ By making each method in the classes that implement the Locator and Advertiser interfaces synchronized, and by synchronizing access to any shared data structures within the class, the Locator and Advertiser interfaces are made safe. Alternatively, finer grained synchronization is also possible within the classes implementing Advertiser and Locator, if you're feeling extra ๐
5.7.8. Modular Implementations ๐ง
ngl, at first glance the API may look rather heavyweight ๐ But the design has been carefully arranged so that modular implementations are possible. You can have implementations that provide only SA, only UA, or only service template access capability, or any combination of the three. Iconic, right? ๐
Because the objects returned from ServiceLocationManager.getLocator() and ServiceLocationManager.getAdvertiser() are interfaces, and because the objects returned through those interfaces are in the set of base data structures, an implementation is free to omit either UA or SA capability. It does this by simply returning null from the instance creation operation if the classes implementing the missing function cannot be dynamically linked. API clients are encouraged to check for this contingency and to signal an exception if it occurs ๐ Similarly, the TemplateRegistry concrete subclass can simply be omitted from an implementation that only supports UA and/or SA clients, and the TemplateRegistry.getRegistry() method can return null. That way, the API implementation can be tailored for the particular memory requirements at hand ๐
In addition, if an implementation only supports the minimal subset of SLP [7], the unsupported Locator and Advertiser interface operations can throw an exception with ServiceLocationException.NOT_IMPLEMENTED as the error code. This supports better source portability between low and high memory platforms, which is such a clean move ๐ซถ
5.7.9. Asynchronous and Incremental Return Semantics โญ
The Java API contains no specific support for asynchronous operation, bestie ๐ Incremental return isn't needed for the Advertiser, because service registrations can be broken up into pieces when they're large. Asynchronous return isn't needed either, because clients can always issue the Advertiser operation in a separate thread if the calling thread can't block.
The Locator can be implemented either synchronously or asynchronously. Since the return type for Locator calls is ServiceLocationEnumeration, a Java API implementation that supports asynchronous semantics can implement ServiceLocationEnumeration to dole results out as they come in, blocking when no results are available. If the client code needs to support other processing while the results are trickling in, the call into the enumeration to retrieve the results can be done in a separate thread ๐ฆ
Unlike the C case, collation semantics for return of attributes, when an attribute request by service type is made, require that the API collate returned values. This means only one attribute, having a collation of all returned values, appears to the API client. In practice, this may limit the amount of asynchronous processing possible with the findAttributes() method ๐ญ This requirement is imposed because memory management is much easier in Java, so implementing collation as part of the API shouldn't be as difficult as in C. It also saves the client from having to do the collation itself, which is a whole mood ๐
5.8. Example ๐
In this example, a printer server advertises its availability to clients. Additionally, the server advertises a service template for use by client software in validating service requests. Let's gooo ๐ฅ
//Get the Advertiser and TemplateRegistry.
Advertiser adv = null;
TemplateRegistry tr = null
try {
adv = ServiceLocationManager.getAdvertiser("en");
tr = TemplateRegistry.getTemplateRegistry();
} catch( ServiceLocationException ex ) { } //Deal with error.
if( adv == null ) {
//Serious error as printer can't be registered
// if the implementation doesn't support SA
// functionality.
}
//Get the printer's attributes, from a file or
// otherwise. We assume that the attributes
// conform to the template, otherwise, we
// could register the template here and verify
// them.
Vector attributes = getPrinterAttributes();
//Create the service: URL for the printer.
ServiceURL printerURL =
new ServiceURL(
"service:printer:lpr://printshop/color2",
ServiceURL.LIFETIME_MAXIMUM);
try {
//Register the printer.
adv.register(printerURL, attributes);
//If the template registry is available,
// register the printer's template.
if( tr != null ) {
tr.registerServiceTemplate(
new ServiceType("service:printer:lpr"),
"http://shop.arv/printer/printer-lpr.slp",
new Locale("en",""),
"1.0");
}
} catch( ServiceLocationException ex ) { } //Deal with error.
Suppose a client is looking for a color printer. The following code is used to issue a request for printer advertisements ๐จ๏ธ๐
Locator loc = null;
TemplateRegistry tr = null;
try {
loc = ServiceLocationManager.getLocator("en");
} catch( ServiceLocationException ex ) { } //Deal with error.
if( loc == null ) {
//Serious error as client can't be located
// if the implementation doesn't support
// UA functionality.
}
//We want a color printer that does CMYK
// and prints at least 600 dpi.
String query = "(&(marker-type=CMYK)(resolution=600))";
//Get scopes.
Vector scopes = ServiceLocationManager.findScopes();
Enumeration services;
try {
services =
loc.findServices(new ServiceType("service:printer"),scopes,query);
} catch { } //Deal with error.
if (services.hasMoreElements() ) {
//Printers can now be used.
ServiceURL surl = (ServiceURL) services.next();
Socket sock = new Socket(surl.getHost, surl.getPort());
// Use the Socket...
}
6. Internationalization Considerations ๐
6.1. service URL ๐
The service URL itself must be encoded using the rules set forth in [2]. The character set encoding is limited to specific ranges within the UTF-8 character set [3].
The attribute information associated with the service URL must be expressed in UTF-8. See [8] for attribute internationalization guidelines ๐
6.2. Character Set Encoding ๐ค
Configuration and serialized registration files are encoded in the UTF-8 character set [3]. This is fully compatible with US-ASCII character values. C platforms that do not support UTF-8 are required to check the top bit of input bytes to determine whether the incoming character is multibyte. If it is, the character should be dealt with accordingly. This should require no additional implementation effort, since the SLP wire protocol requires that strings are encoded as UTF-8. C platforms without UTF-8 support need to supply their own support, if only in the form of multibyte string handling ๐ซถ
At the API level, the character encoding is specified to be Unicode for Java and UTF-8 for C. Unicode is the default in Java. For C, the standard US-ASCII 8 bits per character, null terminated C strings are a subset of the UTF-8 character set, and so work in the API. Because the C API is very simple, the API library needs to do a minimum of processing on UTF-8 strings. The strings primarily just need to be reflected into the outgoing SLP messages, and reflected out of the API from incoming SLP messages โจ
6.3. Language Tagging ๐ณ๏ธโ๐
All SLP requests and registrations are tagged to indicate in which language the strings included are encoded. This allows multiple languages to be supported. It also presents the possibility that error conditions result when a request is made in a language that is not supported. In this case, an error is only returned when there is data available, but not obtainable in the language requested.
The dialect portion of the Language Tag is used on a 'best effort' basis for matching strings by SLP. Dialects that match are preferred over those which don't. Dialects that do not match will not prevent string matching or comparisons from occurring ๐ฆ
7. Security Considerations ๐
Security is handled within the API library and is not exposed to API clients except in the form of exceptions. The net.slp.securityEnabled property determines whether an SA client's messages are signed, but a UA client should be prepared for an authentication exception at any time, because it may contact a DA with authenticated advertisements.
An adversary could delete valid service advertisements, provide false service information, and deny UAs knowledge of existing services unless the mechanisms in SLP for authenticating SLP messages are used. These mechanisms allow DAAdverts, SAAdverts, Service URLs and Service Attributes to be verified using digital cryptography. For this reason, all SLP agents should be configured to use SLP SPIs. See [7] for a description of how this mechanism works. This part is seriously important, bestie, so please don't skip it ๐๐ฅ
8. Acknowledgements ๐
The authors would like to thank Don Provan for his pioneering work during the initial stages of API definition ๐
9. References ๐
- [1] Bradner, S., "Key Words for Use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
- [2] Berners-Lee, T., Fielding, R. and L. Masinter, "Uniform Resource Identifiers (URI): Generic Syntax", RFC 2396, August 1998.
- [3] Yergeau, F., "UTF-8, a transformation format of ISO 10646", RFC 2279, January 1998.
- [4] Howes, T., "The String Representation of LDAP Search Filters", RFC 2254 December 1997.
- [5] Crocker, D. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", RFC 2234, November 1997.
- [6] Alvestrand, H., "Tags for the Identification of Languages", RFC 1766, March 1995.
- [7] Guttman, E., Perkins, C., Veizades, J. and M. Day, "Service Location Protocol, Version 2", RFC 2608, June 1999.
- [8] Guttman, E., Perkins, C. and J. Kempf, "Service Templates and Service: Schemes", RFC 2609, June 1999.
10. Authors' Addresses โจ
okay bestie, if you have questions about this memo, these are the two people to ask ๐
James Kempf ๐ Sun Microsystems 901 San Antonio Rd. Palo Alto, CA, 94303 USA
Phone: +1 650 786 5890 Fax: +1 650 786 6445 EMail: james.kempf@sun.com
Erik Guttman ๐ฆ Sun Microsystems Bahnstr. 2 74915 Waibstadt Germany
Phone: +49 7263 911 701 EMail: erik.guttman@sun.com
11. Full Copyright Statement ๐
Copyright (C) The Internet Society (1999). All Rights Reserved. ๐ธ
okay so this document and translations of it can be copied and shared with others ๐ซถ and people can write derivative works that comment on it, explain it, or help people implement it. they can be prepared, copied, published, and distributed, in whole or in part, without restriction of any kind, as long as the above copyright notice and this paragraph are included on all of those copies and derivative works โจ
BUT, and this is important bestie ๐, this document itself may not be modified in any way. that means you can't remove the copyright notice or the references to the Internet Society or other Internet organizations. the exceptions are when it's needed for developing Internet standards, in which case the copyright procedures in the Internet Standards process must be followed, or when it's needed to translate it into languages other than English ๐
the limited permissions above are perpetual, meaning they will never be revoked by the Internet Society or its successors or assigns ๐
and the whole document and the information in it is provided on an "AS IS" basis. THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT USING THE INFORMATION WILL NOT INFRINGE ANY RIGHTS, AND ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. no cap, that's a lot of legal energy ๐ญ
Acknowledgement ๐
Funding for the RFC Editor function is currently provided by the Internet Society. ๐
๐ฆ where this page comes from
- ietf: rfc2614 1999-06
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms