Subject: [SIP] Re: [Fwd: [Fwd: Munged JainSipApi0_6.jar file?]]

From: Chris Harris <[email-masked]>
Date: Fri, 01 Dec 2000 21:06:08 +0000

Hi Bryan,

Comments below...

Chris

Bryan Thale wrote:

> > I don't know how much use the 0.6 code would be to you - I am writing the
> > reference implementation for 0.7 and I was hoping I could just move the
> > method implementations from the 0.6 classes into the reference
> > implementation - but as it turns out it's easier to start from scratch!
>
> OK.  I've never seen many opportunities for re-use in actual practice either!
> :-)
>
> > PS - the reason I moved them together is that each token constant could be
> > called say "ACCEPT_ENCODING" rather than just "token" - mind you it's really
> > "Header.ACCEPT_ENCODING" instead of "AcceptHeader.token"
> >
> Difference of opinion on style I guess.  I prefer not to put anything in a
> super class (or super interface in this case) that ties it to its subclasses.
> I always seem to regret those reverse dependencies when I use them.

OK - I guess if I step back and look at this, I have to say I shouldn't have moved
the header names to the base interface - every header has a name, but only
Accept-Encoding headers have a name of "Accept-Encoding", so I guess it logically
belongs to the sub-interface. I would want to change it from "token" to something
more meaningful though - "name" being the most obvious. What do you think?

>
>
> On a similar topic, what do you envision as the purpose for the integer header
> type codes?

The reason is to allow an application to treat (particularly experimental) headers
correctly - e.g. an implementation that knows an Call-Info is a general header can
tell the application this, and this overrides the default behaviour of treating it
as an entity header. This could work going down from the application to the
implementation too. I don't know how useful this actually is - but I figured
someone would probably want this functionality sooner rather than later. It sounds
like you think this should be dropped?

>
>
> Bryan.
>
> --
> Bryan Thale
> Motorola Labs, Networking and Infrastructure Research
> mailto:[email-masked]

_______________________________________________
SIP mailing list
[email-masked]
http://lists.bell-labs.com/mailman/listinfo/sip

---

From: Bryan Thale <[email-masked]>
Date: Fri, 01 Dec 2000 19:54:05 -0600

Chris,

> more meaningful though - "name" being the most obvious. What do you think?

That seems like the cleaner approach, keep each sub-interface
self-contained and keep the super-interface generic.  "name" makes
excellent sense as the field name.

> like you think this should be dropped?

The integer type code, yes, unless someone has a specific need for it
that can't be solved otherwise.  The class/interface hierarchy should be
able to differentiate between the different header types.  The
instanceof operator would be more reliable since it doesn't rely on a
programmer-assigned integer which, if incorrect, could cause type
mismatches at run-time.  So, if a stack or application implementation
knows about Call-Info headers it would have an interface hierarchy such
as:

interface Header;
interface RequestHeader extends Header;  // Empty Interface
interface ResponseHeader extends Header;  // Empty Interface
interface CallInfoHeader extends RequestHeader, ResponseHeader, etc...

Even if the recipient of such a header did not grok the meaning of a
Call-Info header, polymorphism should allow it to correctly handle it as
best it can given it doesn't know the specifics of the sub-interface.
That is, the basic Header methods would all work OK which is all anyone
who doesn't have knowledge of the specific Call-Info interface would
need.  And, the type system will allow the recipient to recognize it as
a general/request/response header.

I don't think a GeneralHeader interface tag is necessary since a
"general header" is simply a header that can be both a "request header"
and a "response header" and the multiple inheritance of interfaces
solves that problem nicely.

If Call-Info headers were unknown, they could be represented using a
minimal UnrecognizedHeader interface such as:

interface EntityHeader extends Header;   // Empty Interface
interface UnrecognizedHeader extends EntityHeader;

BTW, the UnrecognizedHeader interface is the only one that would need to
provide the setName() method.  That would clean up the Header interface
and avoid the problem of having an interface with a method this is
unusable the vast majority of the time.

How does that approach strike you?

Bryan.

---

From: Chris Harris <[email-masked]>
Date: Sat, 02 Dec 2000 11:26:08 +0000

Bryan

> interface CallInfoHeader extends RequestHeader, ResponseHeader, etc...

The original API class hierarchy originally had this layer of GeneralHeader,
RequestHeader, ResponseHeader and EntityHeader - but it was suggested that this added
unnecessary complexity to the API - thus the header type attribute was born. I
personally preferred the extra layer and would love to see it replace the header type
attribute. In fact, now that the hierarchy is defined in terms of interfaces rather than
classes, there is a very strong case for adding this layer again. Does anyone have any
objections to this?

> solves that problem nicely.

I think a GeneralHeader interface would be useful to indicate to an application that it
should copy a received unrecognised header into a response.

> interface UnrecognizedHeader extends EntityHeader;

The interfaces for different header types would imply the existence of
UnrecognizedEntityHeader, UnrecognizedRequestHeader, UnrecognizedResponseHeader and
UnrecognizedGeneralHeader rather than just UnrecognizedHeader. We would also need a
createUnrecognizedEntityHeader, createUnrecognizedRequestHeader,
createUnrecognizedResponseHeader and createUnrecognizedGeneralHeader methods on the
JainSipHeaderFactory. Is this acceptable?

Would it be preferable to just remove the setName (and setMethod) method from the Header
interface, and only have the name parameter in the factory's createHeader method? If
not, I would suggest that the setName method should not be any header interfaces - the
name should be fixed upon creation of the object.

---

From: Chris Harris <[email-masked]>
Date: Sat, 02 Dec 2000 19:36:50 +0000

Bryan,

Actually we could move both the getName() and setName() methods of header to
UnrecognizedHeader - the application can use instanceof rather than getName() with the
same advantages associated with the header type interfaces - the getName() method would
only ever be invoked if(receivedHeader instanceof UnrecognizedHeader). [Of course if the
application wants the actual text of the header name it can just use XXXHeader.name].
What do you think?

So now things are looking like (with createMethods only for the bottom four of the
hierarchy in JainSipHeaderFactory)

Header
   |
   +---UnrecognizedHeader(getName(), setName())
   |         |
   |         +-----------------------------------+
   |                                             |
   +---GeneralHeader                             |
   |         |                                   |
   |         +---UnrecognizedGeneralHeader-------+
   |                                             |
   +---RequestHeader                             |
   |         |                                   |
   |         +---UnrecognizedRequestHeader-------+
   |                                             |
   +---ResponseHeader                            |
   |         |                                   |
   |         +---UnrecognizedResponseHeader------+
   |                                             |
   +---EntityHeader                              |
             |                                   |
             +---UnrecognizedEntityHeader--------+

How does this look?

Chris

---

From: Bryan Thale <[email-masked]>
Date: Mon, 04 Dec 2000 15:25:13 -0600

Chris,

> I think a GeneralHeader interface would be useful to indicate to an application
> that it should copy a received unrecognised header into a response.
>

Two points, first, if the header is unrecognized, it is not possible to
determine that it is a general header.  The header is unrecognized; it
could be anything and SIP mandates that such headers be treated as
entity headers not general headers.

Second, general headerness, if you will, can be determined by simply
testing instanceof ResponseHeader and/or instanceof RequestHeader  Only
general headers will be instances of both RequestHeader and
ResponseHeader, so they can be adequately detected without a special
GeneralHeader type.  By eliminating the redundant GeneralHeader tag, we
can simplify the API by allowing general headers to be processed along
with the other request or response headers as appropriate without
introducing a special case into the logic.

> UnrecognizedEntityHeader, UnrecognizedRequestHeader, UnrecognizedResponseHeader
> and UnrecognizedGeneralHeader rather than just UnrecognizedHeader. We would
> also need a createUnrecognizedEntityHeader, createUnrecognizedRequestHeader,
> createUnrecognizedResponseHeader and createUnrecognizedGeneralHeader methods on
> the JainSipHeaderFactory
>

I don't follow.  If the header is unrecognized, how can we make any
judgments about it being a request, response, general, or entity header?

> Would it be preferable to just remove the setName (and setMethod) method from the
> Header interface, and only have the name parameter in the factory's createHeader
> method? If not, I would suggest that the setName method should not be any header
> interfaces - the name should be fixed upon creation of the object.
>

By setMethod, do you mean setType?

I think setType should be done away with entirely and setName moved to
the UnrecognizedHeader interface.  The names of the headers should be
statically defined for all the recognized headers that have defined
interfaces in the API.  The exception being the UnrecognizedHeader.  In
that case, the name of the header must be determined from the actual
message header received over the wire.  Since it can represent any new
or experimental header, we cannot possibly know its name in advance and
thus must set the name in the object we create to represent it.

> Actually we could move both the getName() and setName() methods of header to UnrecognizedHeader - the
> application can use instanceof rather than getName() with the same advantages associated with the header
> type interfaces - the getName() method would only ever be invoked if(receivedHeader instanceof
> UnrecognizedHeader). [Of course if the application wants the actual text of the header name it can just use
> XXXHeader.name]. What do you think?
>

I think getName is still an important method to have in the Header
interface.  Headers have two basic properties, a name and a value.  It
is just as valuable to have a sub-type independent way of retrieving a
header's name as it is to retrieve its value.  In most cases, getName
will simply return the static XXXHeader.name value, but
UnrecognizedHeaders would return the "dynamically" set name of the
header.  This is an important property because it allows a collection of
various header types to be processed as a collection of generic Header
objects without requiring explicit knowledge of the various sub-types of
Header.  For example:

void printHeaders( Header[] hdrs )
{
    for (i=0; i<hdrs.size; i++)
    {
        System.out.println( hdrs[i].getName() + ": " +
hdrs[i].getValue() );
    }
}

Such a routine could handle any and all headers, recognized or
otherwise, and won't be impacted by the definition of new headers.  I
realize that this particular example could be accomplished by invoking
the toString method, but my purpose is to illustrate that it might be
desirable to have access to a header's name as well as its value in a
generic manner.

> So now things are looking like (with createMethods only for the bottom four of the hierarchy in
> JainSipHeaderFactory)
>
> Header
>    |

I don't see the need for the UnrecognizedXxxHeader interfaces.  If a SIP
stack received a header it didn't recognize, how would it choose which
UnrecognizedXxxHeader to create?  On the other hand, why would an
application ever create an UnrecognizedXxxHeader?  Since it is creating
the header, it *must* know what it is.

Take, for example, an application that wanted to add a new experimental
general header, one that the SIP stack it was using didn't support.
Wouldn't that application define a class like

public class XdashMyHeader implements RequestHeader, ResponseHeader,
etc.,

instantiate it, and then simply pass that object into the addHeader
method of the message under construction?  While it is true that the SIP
Stack won't know exactly what the header represents, it can still do
everything it needs to do through the generic Header interface and the
type system.

Bryan.

---

From: Chris Harris <[email-masked]>
Date: Wed, 06 Dec 2000 16:26:52 +0000

Bryan,

I think I should point out that UnrecognizedHeader is a misnomer - it should be UndefinedHeader. An application
or an implementation may or may not recognize a header that is not defined in the API. Also an application uses
the header and message classes provided by an implementation, it does not use its own, and is not allowed mix
implementations. It creates these header and message objects through a factory. So if an implementation
recognizes an undefined header - it can specify which type of header it is, which may be useful for the
application (which may not recognise the undefined header). The same applies for an application passing an
undefined header down to an implementation. We are simply providing the standard means to represent undefined
headers.

Implementing the GeneralHeader interface can be replaced by implementing both the ResponseHeader and
RequestHeader interface. But if we are using a type attribute we need to define a general header type. I think we
may have to stick to the type attribute rather than using header type interfaces, because an application does not
use its own header classes - implying the need for an undefined header interface for each header type. Also there
is significant overhead in using the instanceof operator rather than switching on the header type. I admit the
interface approach is a more OO way to go - but it has been criticized as being inefficient.

Regards,
Chris