Subject: Re: New Drafts

From: James Kempf <[email-masked]>
Date: Thu, 21 Dec 2000 13:43:45 -0800 (PST)

Hi Matt,

Thanx for the comment.

>SLP Service URLs are required
>------------------------------
>SLP Service URL syntax is required for all functions that accept url
>strings.  The following is a list of affected functions: 
>
>       SLPReg() 
>       SLPDeReg() 
>       SLPDelAttrs() 
>       SLPFindAttrs() 
>       SLPParseSrvURL() 
>       SLPSrvURLCallback() 
>
>The decision to require SLP Service URL syntax was made based on in part
>the following scenario: 
>
>Suppose that two calls were made to SLPReg() with a srvurls and srvtypes
>of "192.168.100.2","http" and "192.168.100.2","ftp".  Now the developer
>wants to deregister one service with out deregistering the other. How
>can it be done?  The SLPDeReg() call does not have a service type
>parameter so it would be impossible for the underlying implementation to
>distinguish between the two registrations.  In an attempt to
>standardize, OpenSLP expects valid Service URLS.
>
>OpenSLP requires strict Service URL syntax so that a Service URL can be
>treated as a unique "database key" that identifies a registered
>service.   Not requiring Service URL syntax allows for several
>ambiguities like the one mentioned above. 
>  
>

I believe RFC 2608 requires that there be a one to one mapping between a service
type and a service URL. This would forbid having one URL that is a service: URL
and one that is not registered under the same service type name, so there would be no 
ambiguity w.r.t. SrvDereg.

With respect to registering random strings, I can put some words into the
spec requiring the string parameters to SrvReg and SrvDereg to have URL
format, with reference to the latest RFC on that topic.

>Scopelist may be the empty string ("") or NULL
>----------------------------------------------
>In the calls where a scope list is accepted as a parameters, RFC 2614
>says that this parameter may not be the empty string or  NULL.   OpenSLP
>allows scope list to be NULL or the empty string.  If the empty string
>is passed in as a scopelist, then OpenSLP will use the scopelist the
>system administrator has configured for the machine.  This saves 99% of
>all developers the time of calling SLPFindScopes() and parsing the
>result. 
>
>Scoping is almost entirely an administrative task.  Having to deal with
>and understand scopes will be a burdon to the large majority of
>programmers.  Unless they are writing some sort of SLP browser, they
>will be very content to use the scope that the machine is configured to
>use. 
>

In general, I am not a fan of NULL parameters, if there is an alternative. 
The reason is because many datatypes, such as strings, have a value which
maps to "no value", and client code passing NULL into an API is often
due to a bug in the client code. I prefer to reserve NULL for exceptional circumstances.

However, I have no objection to allowing empty string to mean "use the configured
default". The API contains a function allowing the
programmer to find out what scopes are currently available, and the programmer
can call that function once, then pass the result to all calls that require
a scope list parameter string. Since this may not be the same as the configured
default, I can see your point.

>
>Incremental registrations an de-registrations
>---------------------------------------------
>The only reason I can think of ever wanting to expose the functionality
>of incremental registration and deregistration is to represent dynamic
>data via SLP attributes.  I can think of a long list of reasons why this
>is a very very bad idea.  With out doubt, it is best to instruct SLP
>developers to minimize, when ever possible, the number of calls that
>ultimately generate SrvReg and SrvDereg messages.  If dynamic data is to
>be represented, it is best do do it via a specialized protocol optimized
>for the given service.  OpenSLP does not support incremental
>registrations and de-registrations via SLPReg() and SLPDelAttrs()
>because we have found that when developers learn what really happens
>"under the SLP covers" they are very carefull *not* to call them very
>often. 
>
>In addition to poor usage of network resources, incremental
>registrations and de-registrations require additional code that
>decreases the efficiency of and increases the size, and complexity of
>API and agent implementations.
>
>

There are commercial products that do incremental update. I'm speaking
here of the load balancing telnet server products. I don't know if they use
the API or not, or even if they use the incremental protocol operations as
opposed to updating the entire advertisement, but I don't think the API should prohibit 
something that the protocol supports. The right place to support this kind of functionality
(or maybe not support it is better) is at the protocol level. If you would
like to get this in the protocol, send email to Erik proposing it be included
in the 2608bis draft.

>Possible addition of a *VERY SIMPLE* Attribute parsing function
>---------------------------------------------------------------
>The following function is secretly included with OpenSLP and has proven
>to be very useful:
>
>
>SLPError SLPParseAttrs(const char* attrstr,
>                       const char* id,
>                       int* valsize,
>                       const char** val);
>/*                                                                        
>*/
>/* Used to get individual attribute values from an attribute string
>that   */
>/* is passed to the
>SLPAttrCallback                                        */
>/*                                                                        
>*/
>/* attrstr  (IN) the attribute string as passed to
>SLPAttrCallback         */
>/*                                                                        
>*/
>/* id       (IN) the ID of the attribute you want the value
>for            */
>/*                                                                        
>*/
>/* valsize  (OUT) the size in bytes of the attribute value.  May be
>zero   */
>/*                if the ID was not
>found.                                 */
>/*                                                                        
>*/
>/* val      (OUT) the attribute value of the requested attribute.
>Maybe    */
>/*                null if ID was not found. The returned pointer
>points    */
>/*                back into the original attrstr. Do not free the
>returned */
>/*                pointer.  val WILL NOT BE NULL TERMINATED.  IF YOU
>WANT  */
>/*                A NULL TERMINATED STRING malloc() valsize+1 bytes
>of     */
>/*                memory, memcpy() val and null terminate the
>buffer       */
>/*                                                                        
>*/
>/* Returns: Returns SLP_PARSE_ERROR if an attribute of the specified
>id    */
>/*          was not
>found                                                  */
>
>
>

I don't like the idea of passing back a string that is not null terminated.
C strings should always be null terminated. If you want a simple attribute parsing 
function, then maybe we can support something like strtok() but I would need to see a much 
better description than the above.

>NULL and empty string are acceptable parameters
>-----------------------------------------------
>According to RFC 2614, NULL is not exceptable value for any parameter. 
>Instead programmers are instructed to pass the empty string "".  OpenSLP
>allows programmers to use either NULL or the empty string.   It is very
>easy to deal with both NULL or empty string in the implementation, and
>allows developers to write more familiar and slightly more efficient
>code.  There should not be any reason why the compiler should be
>required to pass a pointer to a static constant empty string when NULL
>will do just a well.   This is why the vast majority of C APIs use NULL
>to indicate an ignored parameter or default value -- not the empty
>string (""). 
>

As I mentioned above, I prefer to have "system level" APIs catch NULL as
an error, because client code often passes NULL in due to a bug. By catching
NULL, the API library can often save the developer a considerable amount
of time localizing the bug, if the application code does proper checking on
the library call return code.

		jak

---

From: Matt Peterson <[email-masked]>
Date: Thu, 21 Dec 2000 16:04:00 -0700

> format, with reference to the latest RFC on that topic.

O.K, then why is the pcSrvType parameter needed at all?  Wouldn't we
always know the service type by parsing the sceme of the URL?  Why would
you ever need to use pcSrvType if there is always a 1 to 1 correleation
between the URL and the type?  

Take a call to SLPReg() where pcSrvURL = "ftp://ftp.acme.com",
pcSrvType="weird.x" what is passed in the message?  Now, how do I
de-register this thing with out possibly deregistering another
registraion with pcSrvURL = "ftp://ftp.acme.com", pcSrvType="ftp"?

I'm not trying to be critical, I'm just trying to understand.

> default, I can see your point.

Also, discovering scopes is not a care free process from a network usage
point of view.  I suppose you could call SLPGetProperty() for
net.slp.useScopes, but again, why should you have to.  I have SLPized
several legacy services, and  I speak from experience when say that
anything the API can do to minimize the amount of code required for SLP
development will crucial to the increased adoption of SLP.  In the
OpenSource world, project maintiners are much more eager to accept small
patches that are easy to understand. 

> like to get this in the protocol, send email to Erik proposing it be included

I agree that this is probably not a discussion for the API 2614bis draft
as the API is just exposing functionality from the protocol.  The
argument to change this aspect of the protocol probably belongs in
another thread.

> better description than the above.

The reason I don't like the strtok() approach is because I wanted
SLPParseAttrs() to be something that can be used from within the
SLPAttrCallback -- without requiring an intermediate memory
duplication.  strtok() modifies the parsed buffer (squashing delimeters
with nulls).  strtok() is also not thread safe and a reentrant (
strtok_r() ) still modifies the parsed string.  

The attribute string returned by SLPAttrCallback is const and must not
be modified.  This means that you have to duplicate the attribute list
before parsing.  This duplication is almost always a wasted  buffer as
you will most likely have to duplicate the value (again) before using
it.

Return of a pointer and a length means you do not have to destructively
parse the attribute string and you do not have to force the caller to
waste a call to malloc() and free() to temporarily hold a copy of the
attrlist as you destructively parse it.  

In addition, most string classes and string data structures provide very
fast constructor methods which accept strings (buffers) in the form of a
pointer and length. 

Still,  I can't blame you for wanting to see all strings NULL
terminated.  It does make you a little more comfortable.  In this case,
what would you think about a function that returns a pointer to an
allocated string?

SLPError SLPParseAttrs(const char* attrlist,
                       const char* id,
                       char** val);

Where val is the value of the requested id.  val would have to be freed
by SLPFree().

> the library call return code.

I guess I can understand your paranioa.  

-- 
Matthew Peterson
Sr. Software Engineer
Caldera Systems, Inc
[email-masked]