Subject: Attribute API

From: Evan Hughes <[email-masked]>
Date: Thu, 31 Aug 2000 16:38:34 -0400 (EDT)

Many moons ago I raised the topic of an attribute API. The reason  is
simple: SLP has a well developed  attribute model, which requires the
application programmar to serialize attributes to be sent on the wire (and
deserialize them when they come in on the wire). In our (DaveM and
myself) experience, the bulk of the time spent making a service SLP-aware
was used creating and serializing attribute lists. The attribute API
encapsulates that behaviour, simplifying the task of the application
programmer. 

 I raise this topic because I feel SLP will be strengthened through the
addition of an attributes API. There are two ways to integrate the
attribute API into SLP:
  1. Extend RFC 2614 to include the added functionality. 
  2. Release a seperate internet draft that describes the attribute
API. This would entail a slp_attr library that would coexist with the
standard slp library. 

 Of the two options, I beleive (1) is preferable. However, if it is the
feeling of this list and the maintainers of SLP API that (2) is a better
approach, I will follow that. 

 The remainder of this email describes the API. The implemented API is
available at http://www.nexus.carleton.ca/~hughes/attr_api.tar.gz 

Note that the following document is a work in progress. It does not
describe iterators. And it's prolly full of typos. =)

e

----------------------

                          Proposed SLP Attribute API
                                       
                                 Introduction
                                       
   The Service Location Protocol provides a strong attribute model for
   use in service discovery. The model consists of five types of
   attribute: keyword, integer, string, boolean and opaque. Using the
   standard SLP API, it is the application programmar's responsibility to
   serialize attribute values for transmission across the network.
   
   In an effort to simplify the task of the application programmer, we
   present the SLP attribute API. The SLP attribute API abstracts away
   attribute manipulation by automatically serializing and deserializing
   attribute values, as well as providing well defined functions for
   querying and setting attributes.
   
Goals

   The attribute API has been designed to speed up and simplify the task
   of making a service SLP aware. It provides a strong interface to SLP's
   attribute model, simplifying the work of the application programmar.
   The API exists above the standard SLP API, providing wrapper functions
   to SLP's attribute registration and querying functions.
   
                             C Attribute Bindings
                                       
   The SLP API is designed to simplify the task of application
   programmars. It defines a number of data types and functions that
   allow both UA and SA programmers to easily create, query, register,
   and iterate across attribute values.
   
Data Types

   The Attribute API requires two data-structures: a container to hold
   the attributes and an iterator to loop over the attributes. The
   container is:
   
  Attributes
  
   typedef void *SLPAttributes;
   
   The SLPAttributes type is either returned (as the result of an
   attributes request), or explicitly allocated (during attribute
   registration). It serves as a handle to an arbitrary number of
   attributes, which can be added to, iterated over, or submitteed to the
   SA/DA. Even though it is possible to associate an instance of
   SLPAttributes with a template, only the values that are explicitly set
   by the application will be sent to the SA/DA on update. The type is
   opaque.
   
  Iterator
  
   Once an attribute object has been acquired, the application may wish
   to iterate across its values. Iterating is made possible with the
   iterator structure:
   
   typedef void *SLPAttrIterator;
   
   The SLPAttrIterator is explicitly allocated to iterate over an
   instance of the SLPAttributes type. It is an opaque type.
   
  Opaque Data
  
   SLP provides an opaque data type. Opaque data is binary data of a
   certain size. To access opaque data, the attribute API provides:
typedef struct {
        size_t len;
        char *data;
} SLPOpaque;

   The len field specifies the length associated with the data field.
   
Values

   In order for proper maintenance of values, a number of named values
   are introduced.
   
  SLP Attribute Types
  
   The type enumeration is:
typedef enum {
        SLP_BOOLEAN = 1,
        SLP_INTEGER = 2,
        SLP_KEYWORD = r, 
        SLP_STRING = 8,
        SLP_OPAQUE = 16
} SLPType;

   Each value corresponds to a type specified in RFC 2609.
   
  Insertion Policies
  
   Since SLP attributes may be stored in lists, the attribute API
   provides two insertion policies:
typedef enum {
        SLP_ADD = 1, 
        SLP_REPLACE = 2 
} SLPInsertionPolicy;

   SLP_ADD causes a value to be added to an existing list, while
   SLP_REPLACE causes a value to clear and replace an existing list.
   
Callbacks

   The SLPFindAttr() function defined in RFC 2614 is used to find the
   attributes associated with a named service. It uses the passed in
   SLPAttrCallback function to return serialized and escaped attribute
   strings. The SLP attribute API provides a similar function
   SLPFindAttrObj(), which passes an attribute object to the passed in
   function of type SLPAttrObjCallback. SLPAttrObjCallback is defined as:
typedef SLPBoolean SLPAttrObjCallback( 
        SLPHandle hslp, 
        const SLPAttributes attr, 
        SLPError errcode, 
        void* cookie 
);

   Where all fields are the same as those in SLPAttrCallback, with the
   exception of the attr field, which now contains a handle to an
   SLPAttributes object.
   
                                 Functionality
                                       
   A set of functions are defined that operate on the above data
   structures.
   
SLPAttributes Functionality

   The SLPAttributes functionality can be broken up into ... .
   
  Creation
  
   There are two attribute creation functions. The first creates an empty
   attributes object. The second accepts a serialized attribute string,
   and uses it to initialize the new object.
   
    SLPAttrAlloc()
    
#include <slp.h>
#include <stdio.h>

SLPError SLPAttrAlloc(
                const char *lang, 
                const FILE *template_h,
                const SLPBoolean strict, 
                SLPAttributes *slp_attr
)

      Description:
      
   SLPAttrAlloc() creates and initializes a new instance of
   SLPAttributes. The new instance contains no data.
   
      Parameters:
      
   lang
          A pointer to a NULL terminated array of characters containing
          the RFC 1766 Language Tag for the natural language locale of
          requests and registrations issued on the handle. Pass in NULL
          or the empty string, "" to use the local the machine is
          configured to use.
          
   template_h
          An open filehandle to the template that these attributes are to
          conform to. May be NULL if type checking is not desired. The
          API will leave the file handle open, but pointing to the eof.
          
   strict
          A boolean flag specifying how strict the API should be when
          verifying tag names against the template specified by
          template_h. If this field is SLP_TRUE, then any attempt to
          register an invalid tag name/type will fail, and SLP_TYPE_ERROR
          will be returned. If this field is SLP_FALSE, the registration
          of invalid tag names will succeed, but a SLP_TAG_WARNING
          message will be returned.
          
          If template_h is NULL, the value of strict must be ignored.
          
   slp_attr
          A pointer to an SLPAttributes handle, through which the
          instance is returned.
          
      Returns:
      
   SLP_OK
          If the SLPAttributes were instantiated properly.
          
   SLP_LANGUAGE_NOT_SUPPORTED
          Uf the lang specified is not supported. This will occur if the
          template specified in the template_h is not of the requested
          language. Note: Allocation and initialization must not occur.
          The application may request again with the template_h field set
          to NULL.
          
   SLP_PARSE_ERROR
          If the template is not of the required format. As with
          SLP_LANGUAGE_NOT_SUPPORTED, allocation does not occur.
          
   SLP_MEMORY_ALLOC_FAILED
          If the API ran out of memory.
          
   SLP_INTERNAL_SYSTEM_ERROR
          An unspecified error occured.
          
   SLP_NOT_IMPLEMENTED
          If the function is not implemented.
          
    SLPAttrAllocStr()
    
#include <slp.h>
#include <stdio.h>

SLPError SLPAttrAllocStr(
                const char *lang, 
                const FILE *template_h,
                const SLPBoolean strict, 
                SLPAttributes *slp_attr,
                const char *str
)

      Description:
      
   SLPAttrAlloc() creates and initializes a new instance of
   SLPAttributes, adding the values from *str.
   
      Parameters:
      
   str
          Serialized attribute string.
          
   see SLPAttrAlloc().
   
      Returns:
      
   SLP_PARAMETER_BAD
          If there is a parse error in the attribute string.
          
   see SLPAttrAlloc().
   
  Destruction
  
   SLPAttributes handles are destroyed with the SLPAttrFree() function.
   
    SLPAttrFree()
    
#include <slp.h>

SLPError SLPAttrFree(
                SLPAttributes attr_h
)

      Description:
      
   Deallocates all resources held by the specified instance of
   SLPAttributes.
   
      Parameters:
      
   attr_h
          The attribute handle specifying the attributes to be
          deallocated.
          
      Returns:
      
   SLP_OK
          If the SLPAttributes were deallocated properly.
          
   SLP_INTERNAL_SYSTEM_ERROR
          An unspecified error occured.
          
  Attribute Addition:
  
   The attribute manipulation functions are made available by type. Each
   takes a value from the application and performs all necessary
   operations to allow the SLPReg() function to send it across the
   network. Since the arguments to functions are type dependent, each the
   name SLPAttrSet is suffixed with the type it operates on.
   
   Since SLP has a concept of "multivalued attributes" (ie, attributes
   associated with a set of values): opaques, integers, and strings may
   be stored in a multivalued list. Booleans and keywords are special
   cases and may not be associated with multivalued lists.
   
    SLPAttrSet_keyw()
    
#include <slp.h>

SLPError SLPAttrSet_keyw(
                SLPAttributes attr_h,
                const char *attribute_tag
);

      Description:
      
   Sets the value of a keyword variable. Since keywords in SLP either
   exist, or do not exist, there is no associated value.
   
      Parameters:
      
   attr_h
          The attribute handle the tag is to be added to.
          
   attribute_tag
          The tag to create.
          
      Returns:
      
   SLP_OK
   SLP_TAG_WARNING
   SLP_TAG_ERROR
   SLP_TYPE_ERROR
   SLP_MEMORY_ALLOC_FAILED
   SLP_TAG_BAD
          
    SLPAttrSet_bool
    
#include <slp.h>

SLPError SLPAttrSet_bool(
                SLPAttributes attr_h,
                const char *attribute_tag,
                SLPBoolean val
)

      Description:
      
   Sets the value of the named boolean attribute to that of the passed
   value. If the value of the named attribute has already been set, it is
   reset.
   
      Parameters:
      
   attr_h
          Attribute handle to set in.
          
   attribute_tag
          The name of the attribute to set. Must be a NULL terminated
          string.
          
   val
          The value to set the variable to. Must be either SLP_TRUE or
          SLP_FALSE.
          
      Returns:
      
   SLP_OK
          If the value of attribute_tag is valid (according to the
          template), and value of attr_h is not NULL.
          
   SLP_TAG_WARNING
          If the attribute_tag is not in the template the attr_h was
          initialized with, and the strict flag is clear (SLP_FALSE),
          this warning will be returned. Note: the value IS set.
          
   SLP_TAG_ERROR
          If the attribute_tag is not in the template attr_h was
          initialized with, and the strict flag is set (SLP_TRUE), this
          error is returned. Note: the value is NOT set.
          
   SLP_TYPE_ERROR
          Returned if a variable with the attribute_tag exists in the
          template, but has a different type. The strict value has no
          effect on this return value. Note: The value is NOT set.
          
   SLP_MEMORY_ALLOC_FAILED
          If an internal allocation failed.
          
   SLP_PARAMETER_BAD
          If the passed value is neither SLP_TRUE nor SLP_FALSE.
          
   SLP_TAG_BAD
          The requested tag contains illegal characters.
          
      SLPAttrSet_int()
      
#include <slp.h>

SLPError SLPAttrSet_int(
                SLPAttributes attr_h,
                const char *attribute_tag,
                long val,
                SLPInsertionPolicy policy
);

      Description:
      
   Sets the value of an integer variable.
   
      Parameters:
      
   attr_h
          Attribute to add the attribute to.
          
   attribute_tag
          Null terminated string specifying the attribute to add to.
          
   val
          The value to store.
          
   policy
          Policy can have one of two values: SLP_ADD, which causes the
          value to be added to the named (in attribute_tag) multivalued
          list; or SLP_REPLACE, which removes the existing value(s) and
          replaces them with val.
          
      Returns:
      
   See SLPAttrSet_bool().
   
    SLPAttrSet_str()
    
#include <slp.h>

SLPError SLPAttrSet_str(
                SLPAttributes attr_h,
                const char *attribute_tag,
                const char *val,
                SLPInsertionPolicy policy
);

      Description:
      
   Sets the value of a string variable. Note that the passed string is
   copied by the API.
   
      Parameters:
      
   attr_h
          Attribute list.
          
   attribute_tag
          The name of the attribute to add the value to. This must be a
          NULL-terminated string.
          
   val
          A NULL terminated string. It does not need to be explicitly
          escaped.
          
   policy
          Specifies what is to be done with existing value: if it is
          SLP_ADD, the string is added to the associated list. If it is
          SLP_REPLACE, the list associated with the given tag is
          destroyed and replaced with val.
          
      Returns:
      
   See SLPAttrSet_int().
   
    SLPAttrSet_opaque
    
#include <slp.h>

SLPError SLPAttrSet_opaque(
                SLPAttributes attr_h,
                const char *attribute_tag,
                const char *val,
                const unsigned int len,
                SLPInsertionPolicy policy
);

      Description:
      
   Sets the value of an opaque attribute.
   
      Parameters:
      
   len
          The length of the opaque data field, in bytes. This allows NULL
          characters to be embedded in the string.
          
   See SLPAttrSet_str().
   
      Returns:
      
   See SLPAttrSet_bool().
   
    SLPAttrIteratorAlloc()
    
   #include <slp.h> SLPError SLPAttrIteratorAlloc( SLPAttributes attr_h,
   SLPAttrIterator *iterator, )
   
      Description:
      
   Creates and initializes an iterator for use with a set of attributes.
   
      Parameters:
      
   attr_h Handle to the attributes to iterate over. iterator The new
   iterator is allocated and returned through this field.
   
      Returns:
      
   SLP_OK If instantiation occured properly. SLP_MEMORY_ALLOC_FAILED If
   the API ran out of memory. SLP_PARAMETER_BAD If the value of attr_h is
   NULL. SLP_NOT_IMPLEMENTED If the function is not implemented.
   
  Attribute Querying:
  
   Obtaining the value associated with a tag can done using any of the
   SLPAttrGet_* function. Three of these (SLPAttrGet_str(),
   SLPAttrGet_opaque(), SLPAttrGet_int()) return arrays of values,
   containing the entire contents of the list -- the size of the list is
   returned as well. It is the application programmer's responsibility to
   deallocate the returned data.
   
   The remaining two functions (SLPAttrGet_keyw() and SLPAttrGet_bool())
   do not return arrays, as SLP does not allow keywords and booleans to
   be associated with lists. Their values are returned directly.
   
    SLPAttrGet_bool()
    
#include <slp.h>

SLPError SLPAttrGet_bool(
                SLPAttributes attr_h,
                const char *attribute_tag,
                SLPBoolean *val
);

      Description:
      
   Gets the value of a boolean attribute.
   
      Parameters:
      
   attr_h
          The attribute structure to query.
          
   attribute_tag
          The tag to query.
          
   val
          A pointer to a boolean to return the value through.
          
      Returns:
      
   ...
   
    SLPAttrGet_int()
    
#include <slp.h>

SLPError SLPAttrGet_int(
                SLPAttributes attr_h,
                const char *attribute_tag,
                long **val,
                size_t size
);

      Description:
      
   Gets the value of an attribute.
   
      Parameters:
      
   attr_h
          Attribute handle to get from.
          
   attribute_tag
          The name of the attribute as a NULL terminated string.
          
   val
          A pointer through which the attribute values can be returned.
          Since SLP allows integer tags to be associated with multivalued
          lists, val returns an array of values. It is the caller's
          responsibility to free() this array. The length of the array is
          returned through the size parameter.
          
   size
          The number of elements in the array returned through val.
          
      Returns:
      
   SLP_OK
          If the value is set properly.
          
   SLP_TAG_ERROR
          If the attribute_tag is unknown.
          
   SLP_TYPE_ERROR
          If the attribute could not be converted into the requested
          type. See the end of this section for a description of when
          this occurs.
          
   SLP_MEMORY_ALLOC_FAILED
          If an internal allocation failed.
          
   SLP_INTERNAL_SYSTEM_ERROR
          Some misc. error.
          
   SLP_NOT_IMPLEMENTED
          If the function is not implemented.
          
    SLPAttrGet_str()
    
#include <slp.h>

SLPError SLPAttrGet_str(
                SLPAttributes attr_h,
                const char *attribute_tag,
                char **val
                int *len
);

      Description:
      
   Gets the value of an attribute.
   
      Parameters:
      
   attr_h
          Attribute handle to get from.
          
   attribute_tag
          The name of the attribute as a NULL terminated string.
          
   val
          A pointer through which the attribute values can be returned.
          Since SLP allows strings to be associated with multivalued
          lists, val returns an array of pointer to strings. It is the
          caller's responsibility to free() this array, and each string
          pointed to by the array. The length of the array is returned
          through the size parameter.
          
   size
          The number of elements in the array returned through val.
          
      Returns:
      
   SLP_OK
          If the value is set properly.
          
   SLP_TAG_ERROR
          If the attribute_tag is unknown.
          
   SLP_TYPE_ERROR
          If the attribute could not be converted into the requested
          type. See the end of this section for a description of when
          this occurs.
          
   SLP_MEMORY_ALLOC_FAILED
          If an internal allocation failed.
          
   SLP_INTERNAL_SYSTEM_ERROR
          Some misc. error.
          
   SLP_NOT_IMPLEMENTED
          If the function is not implemented.
          
    SLPAttrGet_opaque()
    
#include <slp.h>

SLPError SLPAttrGet_opaque(
                SLPAttributes attr_h,
                const char *attribute_tag,
                SLPOpaque **val,
                unsigned int *len
);

      Description:
      
   Gets the value of an attribute.
   
      Parameters:
      
   attr_h
          Attribute handle to get from.
          
   attribute_tag
          The name of the attribute as a NULL terminated string.
          
   val
          A pointer through which the attribute value can be returned.
          Since opaque values have an associated length, the values are
          returned in an SLPOpaque struct. The application programmer
          must free():
          
          + The array of pointers
          + Each SLPOpaque struct
          + The opaque value pointed to by the SLPOpaque struct
            
   len
          The length of the array returned through val.
          
      Returns:
      
   SLP_OK
          If the value is set properly.
          
   SLP_TAG_ERROR
          If the attribute_tag is unknown.
          
   SLP_TYPE_ERROR
          If the attribute could not be converted into the requested
          type. See the end of this section for a description of when
          this occurs.
          
   SLP_MEMORY_ALLOC_FAILED
          If an internal allocation failed.
          
   SLP_INTERNAL_SYSTEM_ERROR
          Some misc. error.
          
   SLP_NOT_IMPLEMENTED
          If the function is not implemented.
          
    SLPAttrGet_keyw()
    
#include <slp.h>

SLPError SLPAttrGet_keyw(
                SLPAttributes attr_h,
                const char *attribute_tag
);

      Description:
      
   Gets the value of a keyword.
   
      Parameters:
      
   attr_h
          Attribute handle to get from.
          
   attribute_tag
          The name of the attribute as a NULL terminated string.
          
      Returns:
      
   SLP_OK
          If the named keyword exists.
          
   SLP_TAG_ERROR
          If the attribute_tag is unknown.
          
   SLP_TYPE_ERROR
          If the attribute could not be converted into the requested
          type. See the end of this section for a description of when
          this occurs.
          
   SLP_MEMORY_ALLOC_FAILED
          If an internal allocation failed.
          
   SLP_INTERNAL_SYSTEM_ERROR
          Some misc. error.
          
   SLP_NOT_IMPLEMENTED
          If the function is not implemented.
          
  Registration:
  
   The SLP attribute API allows services to register themselves with a DA
   using a mechanism almost identical to that provided in the standard
   API.
   
    SLPRegAttr()
    
#include <slp.h> 

SLPError SLPRegAttr( 
        SLPHandle slp_h, 
        const char* srvurl, 
        unsigned short lifetime, 
        const char* srvtype, 
        SLPAttributes attr_h, 
        SLPBoolean fresh, 
        SLPRegReport callback, 
        void* cookie 
);

   Same as the old version, differing only that the attribute string is
   replaced with the attribute handle to register. Note that the old
   version (with explicit control over the setting of the attribute
   string) should still exist.
   
  Querying for Attributes:
  
   Attributes can be queried for in much the same manner as they are
   queried for in the standard API.
   
    SLPFindAttrsAttr()
    
#include <slp.h> 

SLPError SLPFindAttrsAttr (
                SLPHandle hslp, 
                const char* srvurlorsrvtype, 
                const char* scopelist, 
                const char* attrids, 
                SLPAttrCallback *callback, 
                void* cookie
);

   Same as the old version. Note that the callback should be of type
   SLPAttrCallback, which takes an SLPAttributes as an argument. callback
   must not modify the passed SLPAttributes object.
   
  Serializing Attributes:
  
   It is occasionally desireable to serialize attributes.
   
    SLPFindAttrsAttr()
    
#include <slp.h>

SLPError SLPAttrSerialize(
                SLPAttributes attr_h, 
                size_t *count,
                char **str, 
                SLPBoolean fresh
);

      Description:
      
   Gets the serialized version of a set of attributes.
   
      Parameters:
      
   attr_h
          A handle to the attribute structue to query.
          
   length
          A pointer to an integer through which the number characters in
          str are returned. This does not include the trailing NULL.
          
   str
          A pointer to a string through which the serialized version is
          returned. SLPFree must be called on str if the call succeeds.
          Null terminated.
          
   fresh
          If fresh is set to SLP_TRUE, only the values that have changed
          since the last serialize are serialized.
          
      Returns:
      
   SLP_OK
          If the serialization occured properly.
          
   SLP_TAG_ERROR
          The specified tag does not exist in attr_h.
          
   SLP_INTERNAL_SYSTEM_ERROR
          Any misc. error.
          
   SLP_MEMORY_ALLOC_FAILED
          If a malloc failed. If this value is returned, the request
          failed.
          
   SLP_NOT_IMPLEMENTED
          If the function is not implemented.
          
    SLPAttrFreshen()
    
#include <slp.h>

SLPError SLPAttrFreshen(
                SLPAttributes attr_h, 
                const char *new_attrs
);

      Description:
      
   "Freshens" the attribute object with a serialized attribute string.
   Replaces all tag/value pairs in attr_h with those in new_attrs. All
   values not named in new_attrs are ignored. All tags in new_attrs but
   not in attr_h are added to attr_h.
   
      Parameters:
      
   attr_h
          A handle to the attribute structue to query.
          
   new_attrs
          A serialized attribute string.
          
      Returns:
      
   SLP_OK
          If the deserialization occured properly.
          
   SLP_INTERNAL_SYSTEM_ERROR
          Any misc. error.
          
   SLP_MEMORY_ALLOC_FAILED
          If a malloc failed. If this value is returned, the request
          failed.
          
   SLP_PARAMETER_BAD
          Syntax error in the attribute string. Although slp_attr_h is
          still valid, its contents may have arbitrarily changed.
          
   SLP_NOT_IMPLEMENTED
          If the function is not implemented.
          
  Querying the Type of an Attribute:
  
   It is possible to query the type of an attribute if the tag is known.
   
    SLPAttrGetType()
    
#include <slp.h>

SLPError SLPAttrGetType(
    SLPAttributes attr_h,
        const char *attribute_tag,
        SLPType *slp_type
);

      Description:
      
   Queries the type of the requested attribute.
   
      Parameters:
      
   attr_h
          A handle to the attribute structue to query.
          
   attribute_tag
          The name of the attribute to query.
          
   slp_type
          A pointer to the type field to set.
          
      Returns:
      
   SLP_OK
          If the attribute was queried and set.
          
   SLP_TAG_ERROR
          The specified tag does not exist in attr_h.
          
   SLP_INTERNAL_SYSTEM_ERROR
          Any misc. error.
          
   SLP_MEMORY_ALLOC_FAILED
          If a malloc failed. If this value is returned, the request
          failed.
          
   SLP_NOT_IMPLEMENTED
          If the function is not implemented.

---

From: James Kempf <[email-masked]>
Date: Thu, 31 Aug 2000 16:43:45 -0700

Evan,

I am planning on doing a 2614bis draft Sometime Soon. I will fold your description contained
herein into the draft, unless there is any objection from the list. We can decide, going
forward, whether we want to add the attribute API to the RFC.

		jak