Subject: [SIP] JAIN SIP - Issues to be resolved

From: Chris Harris <[email-masked]>
Date: Wed, 15 Nov 2000 16:05:09 +0000

All,

Now that the JAIN SIP API is using interfaces instead of classes for
messages and headers, the implementations of these interfaces will have
their own parsing mechanisms. Currently the API set methods throw
IllegalArgumentExceptions if the user attempts to use a null or
zero-length parameter. The question now is should an implementation
throw an IllegalArgument if it doesn't like the value, or should we
create an exception for anything implementation-specific.

An example of this is the AcceptLanguageHeader. The API allows any
String that is not null or zero-length be used as the language range.
Obviously an implementation should be stricter on the content of this
String.

The reason we are so tolerant of parameter values was that the headers
were originally defined as classes in the API, and we did not want to
include a full SIP parser in the API. However, now that interfaces are
used, an alternative would be to simply extend the definition of an
illegal argument - for example, the implementation should throw an
IllegalArgumentException if the language range does not conform to the
RFC. (Of course testing this would be another matter entirely!)

Another separate issue is - what should an implementation do if receives

something from the network that it cannot parse correctly? Should the
JAIN SIP application be made aware of it, or should the implementation
automatically send back the appropriate response to the network? This
obviously depends on whether the implementation is lazy-parsing or
parsing the entire message up front, and we have to accomodate both
scenarios (this is after all one of the main reasons we moved from
classes to interfaces)

Your opinions are of course welcomed.

Regards,
Chris Harris

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

---

From: "M. Ranganathan" <[email-masked]>
Date: Wed, 15 Nov 2000 17:14:17 -0500

â°v«®+0®‹^YM£ajÛax5"ò"²ë"ž§µêßiÇ¬Š{-y§h}ÉZ²Ç¬~ŠÁ«è"È­¢ë_¢ºnnXœëâ{¬ÉëfzËëØ^i×«²Ø^Šjezg§µ«b¢{(~Ø^±è§µêßiÇ¬Â)e…«Þ¶¢®Œ'¥ªìŠx&yÈZž+&°+«éí—+axÈ±ëfzØhvËa®Œ–W jP+‚éžžÑ1qêmŠ‰ì‰ûazë«mzjm²Ú.±æ§ºYh¯7«¢W§‚Øij¶¦z×«Nª¹ë-Š‰ç£¬².•Ö§Šjezg§µ«b¢{a®Œœ‰ez¥¸.™éí‰øv‡¬žÙb‘ëazö¥¹ê+².•Ür·šµæ§{¦Ø¨ú+j|†)àŠjezg§µ«b¢{)yÈŸ‰Â,º²Ür·šµæ§{¦Ø¨ÉZ²Çè­©e¥ªìz»)yÈŸ‰Ç±qêmŠ‰ìjwaj÷©j»®Ë.mÉZ²È­¶‹az*íjË^²‰ž™¬°j{m¢¯yø§z¸+j)Þuì\z›b¢{-…©è¶«°z0iº.µ¨êâq"=ªìxL\z›b¢w%jË0†'!ŠÆÚ²'–\šµ¨ Šx•«,~º&Âœ†)©•éžžÖ­Š‰ìq©ì¹·%jË,¥ç"~'ÅÇ©¶*'°‰àzw«jWè®ËZÖ«všuêì{¦Ø¨žÊ'ŠY^©eÉú+™«myØ^i×«²Çžç(šg§u«b¢vÞ–ŒjvÞuéZÉçh®Øk£	ÚŸ+b™ëaz·¢²z+z«ž²ÚÞ¦\¦¡×¥Štˆ>Ê-…ç%‰éíP°ŠYg¢ÖÞç²Æ«Š\°j+bžè­ªÞ¦\š–ØhºbµÊ.•ÚÞ¶¼žÙ^²Érw±jjez‡í†+"²Ø^Ç¦ÒÚžšáÞi×«N€<†¥–Œ,j|’¶¸§‚ØZ¶+'¢Ùî–Z+Íêè•éà¶ÞºÇjËazV§‚æ z¶§ã›¾*.²\šž)©•éžžÖ­Š‰ì†‹¥u·¬¶¸œµêèžØ^r‰íz{h~Øb±+kŠxzÆî¶Ø^¥ªìz¹ÞyÙèµ·¬¶¸œµ8^æ¬¢|j·¬¢Ú%z¶§¶‡éj¶¦z×«½©nzÌ²ØZ¶Ø^…æz»0z·¨®("©eÉ×ŸŠwjÇ%jË²)í…à!©ÝÁçbvz-Á©í¶ˆ§r[y§î–Tˆ>–«±êâžØ^ò£¯z¹èÂØZ¶)íz·Úqëë¬yÖ§j[^®vŠ÷°¢é]mëh²)©—'±µéÝ¶yø§ŠØ¨ž‡Úž)ez¥j¸.™éí~ŠÞÅ©©•ëaz)©•éžžÖ­Š‰ì†‹¥vØk£§"Y^©@®¦z{DÅÇ©¶*'‰ûazV§‚æ z¶§çhzÉèµÊ'~Šæ¶‹ayB9÷(º»µë-Šx-†+0¢é]mæ§¢Ø^®fµêÞžØ«z\€ž‹az»¥ªÚµè¬²ç¢³Z¶ÈhºWZž)©•éžžÖ­Š‰Ý¢'ëyÇ¢½ë,¢g†)à~º&¶§zÜ(®KajØ­q©ç¢ÚZ®Çœ¢ºÞrÙrJ.•Ûax5"jše‰Æ­Š‰Ûzfy¬êŠÚ+².•Ûaz)©•éžžÖ­Š‰ÚºÚ&jØœjYr±éÝm§$¶š¦šè¦¸šµêÞ²š'±ëh¶§zÜ(®DáŠÊ¾*.²\z—§vÊ'Â…êí…è¦¦W¦z{Z¶*'ŠÉZÏ*Z®È§‚Šéj»"žayéíŠ·¦zËë©~º'µ©ÝÁèZ½ëhiÇ(š‡Zµæè¶zv«Š‹-†+"±§íz¶¥–‰Þ¡ûazf¢ž·š²‰ìÁé¨½ç_®‰œ•«,zËhŠ{^öœzÀrjše‰Æ­Š‰ÈjË.™ì¨¹ªÞ­çÞ®¸§‚Ú-…ç¯z{ajwezºh®Ø¨ž‡í…ë-iÉz·¬›+Z‘â-†)ä²—œ‰øœ’)Ý²‡Þ®º+±ú+{¦¦W®ž·œ¢	âÍçfzØhvG²ÂŠÝ²ØZ¶'^žØŸ‰ë-…è^i×«·*^².•ØêÚµêk¢jmž‹b~'¶*'jÆ°k*jYhÂ)àŠjezg§µêì¶†îŠW^Æ×§²*'±»¶v‡¬ž‹gyçm¡ªi—+h¶žžØ«zg¬±¨N¬Â!©¬º²Ø§‚+-…«^½éÚ•¬ò¥ªìz¹h¢F¶ŸŠ»-¦ŠíŠ‰è~Ø^…æz¶§v)ï¢Gš…©Ý•êâ~Ø^…æz¸¬ž‹hê¶©ç^~)ÞvÜ©zË.¦š+µç[ÊØ^¥ªìz±èÁëÞ®Øb±Ú²z-ç¶†©¦\¡©e…æz»¢·±jjez'í…è^i×«ŠÆ¬µ©Ýj·ay§^è¢{ZrØ^i×«nëm…êÞ²Ú¶¡y§^®+iÓë¢jmHƒëzÊhžÇ¬~º&¶¬z»Þ®éÝz».r"Ë¦²Ö§qëéèµªÞªè«zg§¶‡í…ë)yÆ¬}ªÚ°‰'£ÞÇ­…ìÈ‹§uêìµ©ÝŠ×(®·œ¶g¢|†¦Âº'‚+p¢é]mé^©_¢»azÇ«½êí¡Úžé›zº¶§‚Ë§uêí†+,qéÚ®*"Énv)àŽë-Š	èëazf§‚W…æz¶§uÚè¦+lŠW§¶\¬¢Øb±·¡jø¨®+zËeyûnžÊ^r'âyØ§$
HƒàŠ÷¬Šjezg§µ«b¢{-…æ›ŠXÊÚ†Š,zÚ£ZµëÞ®Ø^Ë§µ8ZžKz«vÄZž˜¢êè¦)â¢{êr‹«±ì•Ê&yÔ^ªÝ°(kŠÁÚ®¸¬Hƒæj)bž	b²Ôˆ>X¬¶ÆÞ–YZnÇ(šm§ÿåŠËlmée•¦ìr‰¿™¨¥™©ÿ–+-ŠwèþÈ©1§©Ú¶§4„“ÛÚÇ5ëp¢¹"žÞrè–ˆ"zÁ«¢êuÓ@næ®¸¯y+h§ÏvÐf¢¶«±»«€ÀöÓÏ}MéwÓ_{ç~ºàV±ßMy÷M=ß

---

From: Chris Harris <[email-masked]>
Date: Wed, 15 Nov 2000 23:42:56 +0000

Ranga,

Thanks for the input! Comments below...

Regards,
Chris

M. Ranganathan wrote:

> Chris Harris wrote:
> Bravo!  Is it out for public review as yet?
> 
It's not yet. I can email the current version to anyone who is 
interested. The first public draft will be available from Sun's site, 
for the next bake-off

> I suggest we create an exception class for all parser specific 
> exceptions and have parsers subclass it to their taste (some may want 
> to have finer grained exceptions than others). How about a generic 
> SIPParseException class which is basically a "tagging" class from 
> which implementations can subclass specific exceptions. In general, 
> for standard headers,  exceptions on illegally formatted headers (see 
> recommendation below) can be delayed or thrown anytime (there is no 
> request-reply model in SIP so the client UAS will not be necessarily 
> waiting for a reply although it could retry endlessly....)
> 
The implementations can certainly subclass such an exception - but the 
application will only know about the base exception from the API - so I 
think a SipParseException is sufficient. I assume you mean we keep the 
IllegalArgumentException for just the null argument case, and use the 
SipParseException for all other unparsable String arguments (including 
zero-length)?

We need to decide whether this should be a checked or runtime exception.

> Yes but the parser need not be strict.
> 
OK - but chances are it will be stricter than the API :)

> By application I assume you are referring to the event handler portion 
> of the stack. Heres my take....
> 
> I think specific kinds of errors (for example unrecognized  method 
> keywords that identifies the header type)  should generate prompt 
> notification as a way of allowing implementers to build  extensions 
> but that does not need to apply to the entire message. Thus, what I am 
> suggesting is that even a lazy parser look at the first portion of the 
> header and invoke a handler if the header is not one of the 
> pre-defined types supported by the parser.
> 
Well the implementation should pass an unrecognised header to the JAIN 
SIP application (as a generic Header)- after all the JAIN SIP 
application might be aware of extensions that the underlying 
implementation knows nothing about.

> However, this does not need to apply to all headers - for example if 
> the header is a standard header  (e.g. Contact header) but the rest of 
> the header is bad.
> 
If lazy parsing is being used, this bad part will not be discovered 
until the application attempts to access it - so should the get methods 
throw the JainSipParseException too? (Again this may affect whether the 
exception should be checked or not)

> Prompt SIP responses from the server under such circumstances are not 
> a requirement of the spec (as far as I know).  Hence, the way 
> I understand it (correct me if I am wrong)  it would be legal for the 
> server to do a number of things under this scenario including just 
> ignore the mangled header  (and drop it silently)  so this behavior 
> is  best left unspecified in JAIN-SIP (gives implementations the 
> ability to choose to do whatever they want).
> 
Is dropping the broken header the usual way to handle this case? Do any 
SIP implementations keep the header and leave the header content as a 
string?

> Thanks.
> Ranga.
> -- 
> M.Ranganathan
> NIST Advanced Networking Technologies Group,
> 100 Bureau Drive, Stop 8920, Gaithersburg, MD 20899. 
> Tel: 301 975 3664 Fax: 301 590 0932
>

---

From: Sean Olson <[email-masked]>
Date: Fri, 17 Nov 2000 13:08:28 +0100

Just one brief comment.
/sean

> Thanks for the input! Comments below...

<snip>

> SIP implementations keep the header and leave the header content as a

To be really "future proof", you should return the header content as is,
even if it doesn't parse correctly (according to the parser's notion of
correctness). Dropping it seems very wrong.

---

From: Chris Harris <[email-masked]>
Date: Fri, 17 Nov 2000 12:20:40 +0000

Sean,

If dropping the malformed header is considered wrong, then one solution in
the JAIN context would be to use the generic Header class instead of the
particular subclass, say FromHeader. But this assumes that the header is
fully parsed before the object is created - if lazy-parsing is used the
FromHeader will be created based on the header name - and the fact that the
header content is malformed will not be discovered until the application
attempts to access the various parts of the header.

As an alternative, a JainSipParseException could be thrown by the get
methods, and if one is thrown, the application must then call the getValue()
method to get the string version of the malformed content?

Chris

---

From: "M. Ranganathan" <[email-masked]>
Date: Fri, 17 Nov 2000 13:49:54 -0500

"ØbžG¯zv¥k<©j»®wžvËh–Š$jØî²ÙË
+vØZ¶'^žØŸ‰ë-…è^i×«·*^‰çë¢khz×"šg‰«^—"ž‰Ë
+vfr¬¶§¶¡y§^®+.ž·œ¢	âÍçZÛazgœ…©â²khuæ¥Â+aºzÞrˆ'‹7…æz»,†‹¥u·¢žú$yÚk¢jm—+aºÆ¥–Œ"ž§Šjezg§µ«b¢{h{^Ôˆ>)ÚÁéej·!Š×œµç_jÈb¢s§¶¨¶«…©Ý‰ûaz·¢±©šµÈbž^i×«‰×§¶'âz»az{az·¢²z'yçm¢–«±ëaz·¬¶‡í…è^i×«Šižv&z\ˆµÆ§mç^}êëyÛ§¶)m…æ©¦XœjØ¨ìi–'"¶\«z«ž²Û-…â@ Ôˆ>)©•éžžÖ­Š‰í¡Ú,¡8n°‹aŠy+jØ^®ØZž§vW†+jÇ°ŠØcºËkzÛ«ž)àjšuêíÊ—¥ŠG zw«jX^i×«Ê‹¦k,"²hr‰ì‰×«jw¯z{fyÈZž+&¶Â‹¥v)ï¢Gš…©Ý•êß¢»§²êi¢»^všuêè®Øk£§{¦Ø¨ž'ò¢êky÷«Z"gšžÖÞ–ŒÉÚè¦˜§‚+b²z-¶©j»Ø¬qªÝŠx-…è^i×«nëZªi–'¶*'±¬š¦º1ÊÇ«½êÝŠÇØ§‚Ø^…æz»ajØ¬¡ú'z‡í…ër¥ëyø§yØ§¶‘&îµÚ²z-¥ªìyÊ+ç-—"-ŠÆœ¶æ¥—+(™ì!jÛk‰É2¶ˆ§²+-¶jv©¦XœjØ¨·«z«¢çm¢·¬¦‰ÝÂ§jg¬±¨r‰íj)ìjf§‚W…æz¶¬¶©j»®k¬µ·šnW¢–«±ç§¢è!¡ûazšuêí¡Ê'²ÚîrÖ¦y©âžî–·¬¦‰ìy©Ý’z0Â&¶ŠÞ²š'vÚµªiyªì¶¶†)à¶‡hºw^®Ø^±ç"Ë¦²Ö§që0¢é]mëh™©ë)¢{²Ú&jx%yÙž²Æ zÊ)¶*'jSŸr‹«±è(¡Ø¦¦W¦z{Z¶*'³¥•©pk+-¯+hë)¢wi®‰©¶\ž½éî×«zºèê.±Ê'v+b¢{ç%j¸Ÿ‰Æ­Š‰í…«B†¸¬r‹¥v¥¦g°ŠØRk"»&‰ƒR úk£¬z»Þ­©Ý#§¶Ú0®+^jw±µéìŠ‰Èuæ¥—"0¢é]–)¶‡±µéÝ¶©®Œr±êïz¼"¶.¶Ú.r§‚+lr‡^Œ¢é]¶¬mçhèžÂ™ç!jx¬šÈZ½ì¨¹»¢–Ø§Â+aÂÊ‹¡j÷zÈ çHjièµÉZŠh§‚+\j{[yÚ'z;¬¶ØZ´‡hžÛ§uêìµ©Ý†Œ-¡Ú"µ j·lE©àh(kŠÁÚ®¸¬Âº-y'šœ‡Ý®ŠiŠx-…éš•ú+™çay§^®+¢{"uêÞw
èžazz'zÊ%ºØ¨ž)í…â@ ×(ž×±·
.•ÖÞ¶‹¬zØ^éÞ®'y§^ÉZ²È§²×šv‡í…êZ®ØœºV«²æÜ•«,±¬…®‰‡y§^¬¶¬jË.™ë-…«m…è^i×«ŠÇî–\©j»u·Ÿ¢·…êç-ŠÇ+y«^v'åk<©j»"ž¬ºÇ¶…®‰‡y§^¯¥•·œæyÖÚ±çhžØ^…æz¹Ú™æ§vØ^}§-¶¶¡y§^Ê'µéíŠÉš•ú+™çpŠYg¢ÖÞv+¢÷«yÛ§¶)m…æ©¦XœjØ¨«mzjm²ÚqÇ¬²Ø^½ªâ¢ë)j»l¡ûazšuêÀ±©Ú–×««b½æ‰j)ÒŠ“Ú®Ç„ÅÇ©¶*'r‹¥u·†º0¼…è¶g†‡ljwb~‰ÞŠËa®Œ'¶š¦™bq«b¢y®²Ûazw–[azU©nzg†‡m¢¶¬¶¸§‚÷«²*'¡ûazf¥~Šæy×(ž×§´(kŠÄžjs¥²‰ð®‹^&ë-¢w›®'Ÿr‰¦z{±æ§
â°v«®+0®‹^E©ài8ZžK¢»az)éºÐ¨šg§¶ÆÞ–Œz«vÀ¡®+E©àjv…©ð®‹^
â°v«®+0®‹^²x©>º&¦Ôˆ>·¬¦‰ìzÇë¢kazÇ«½êî×«²ç!r*Üºk-jw±ªÞž‹Zê®Š·¦z{h~Ø^²—œjÇÚ­«’z0éÜzØ^Á¬ˆºw^®ËZØ­rŠëyËfz'Èjl+¢x"·
.•ÖÞ•è•ú+¶¬z»Þ®Ú¡©î™·«¡ûaŠx,ºw^®Øb²Çªâ¢)Ü–çbžî²Ø žŠÞ¶¦jx%yØ^i×«jw]®Šb¶È¥z{eÊÊ-†+z¯ŠŠâ±·¬¶WŸ¶éì¥ç"~'Šr@ Ôˆ>¯zÈ¦¦W¦z{Z¶*'²Ø^i¸¥ŠÜ­¡Èh¢Ç­¡Ú0…«^½êí…ì°j{H±Úè¦˜§‚Ø^nº$zx^i×«¶®²æ¥Á¬¢§vW†+jÇƒ¡©òHƒâš™^™éíjØ¨žÉz›azšuêÚÙ^j÷…è^i×«r‰íz{Z±«-®)àN†Þ­æ¥—'î¶êÞ¦º(*.².•ÚÞ¶êç¶¡y§^Ê'µéíjÈ¬z÷§‰øv‡¬žÚZ®Çœ¢ºÞrÙriÇ(Ø§‚Ú-…êZ®Ç«²z-Š‰è}Ê+ç-ë,º)¦)àŠÛzk/z¼°®‰àN§’Ä^ªÝ±§¤ˆ>f¢–)à–+-HƒåŠËlmée•¦ìr‰¡¶ÚþX¬¶ÆÞ–YZnÇ(›ùšŠYšŸùb²Ø§~ìŠ“jx«ajsHI0½©ÜyÓ^·
+’)àMç!ž‰h‚'¬º.§]4êÞjàëŠ÷’¶Š|÷mj+az»º¸m<÷ÔÞ—}5÷¾wë®kô×ŸtÓÝö

---

From: "farhan" <[email-masked]>
Date: Sat, 18 Nov 2000 11:36:14 +0530

why do we have a 3 way handshake for INVITE? is an INVITE-Response not
enough ? why?
i do know some of the issue involved with a 2 way handshake. but can someone
tell me about what are all the problems with just an INVITE-Response system
(without needing an ACK) .

- farhan

---

From: "Simon Barber" <[email-masked]>
Date: Fri, 17 Nov 2000 22:29:56 -0800

This is to do with the rather confusing conecpt of the SIP transaction, and
reliability. In my opinion we need a document that clearly documents this,
since it is one of the most confusing aspects of the protocol - and it got
that way because the protocol has 'evolved'.

The INVITE retransmission will stop on receiving a provisional response, so
the ACK is needed to ensure the reliability (and stop retransmission of) the
final response.

(correct me if I'm wrong please!)

Simon.

----- Original Message -----
From: "farhan" <[email-masked]>
To: <[email-masked]>; "Chris Harris" <[email-masked]>
Cc: <[email-masked]>; <[email-masked]>; <[email-masked]>;
<[email-masked]>
Sent: Friday, November 17, 2000 10:06 PM
Subject: [SIP] a stupid question on 3way handshake

---

From: Stuart Bargon <[email-masked]>
Date: Sat, 18 Nov 2000 17:57:32 +1100

I would suggest looking into the solutions developed to get around the two
armies problem. The classic computer science problem goes something like
this:

Two generals with two armies are besieging a city, each on the opposite side
of the city. They have very good clocks. They communicate by messengers that
may be killed on the way. The generals need to agree on a time when to
attack simultaneously the city. If they attack separately, they will lose.
If together they will win.

-----Original Message-----
From: [email-masked]
[mailto:[email-masked]]On Behalf Of farhan
Sent: Saturday, 18 November 2000 5:06 PM
To: [email-masked]; Chris Harris
Cc: [email-masked]; [email-masked]; [email-masked];
[email-masked]
Subject: [SIP] a stupid question on 3way handshake

- farhan

---

From: "farhan" <[email-masked]>
Date: Sat, 18 Nov 2000 12:51:09 +0530

well simon i am glad that someone shares the confusion. is dr. rosenberg on
the list? i would love to hear from him on why the protocol got that way.

---

From: Billy Biggs <[email-masked]>
Date: Sat, 18 Nov 2000 05:24:34 -0600

farhan ([email-masked]):

> i do know some of the issue involved with a 2 way handshake. but can
> someone tell me about what are all the problems with just an
> INVITE-Response system (without needing an ACK) .

  I see two reasons why an ACK system is useful:

1. Forking.  Remember that an initial request creates many call legs.
   Say that A sends a request to a proxy which forks in parallel to
   three locations:

       __                               __                 
    A  /\ ---------> Proxy -----------> /\   B    200 OK / T:u@p;tag=5
          SOMEMETHOD       \            __              
          T:u@p              ---------> /\   C    200 OK / T:u@p;tag=6
          F:A;tag=4          \          __              
                               -------> /\   D    200 OK / T:u@p;tag=7

   Say all three answer the request at the same time with a 200 OK.  We
   now have created three call legs: A-B (4-5), A-C (4-6), and A-D
   (4-7).

   Consider an unreliable transport (UDP).  How do we ensure that A
   receives all three of these responses?  The HTTP request-response
   model was not built to handle forking.

   One solution is to reliably transmit final responses.  Each of B, C,
   and D can retransmit their response until they get an acknowledgement
   that someone actually got it.  This is really a hack to the model,
   and you get some weird interactions:  For example, in SIP you must
   retransmit final responses to INVITEs even when used over TCP!

   SIP decided that this stronger form of reliability is only useful for
   INVITE requests.  It is critical for INVITE that all successful
   responses are received: otherwise we would get mysterious calls where
   one end thinks it's connected, but the other end never got the
   response.  So, INVITE is treated as a big special case where
   responses are retransmitted until they hear an ACK.

   Unfortunately, this means that requests such as MESSAGE cannot take
   full advantage of the forking capabilities of SIP, since you cannot
   reliably tell how many endpoints received a forked request.  Another
   problem method is SUBSCRIBE.

   Consequently, in order to build a deterministic system proxies should
   only parallel fork INVITEs, and wait for confirmation of a CANCEL
   before trying another branch of a non-INVITE sequential fork.

2. Optimization.  The assumption in SIP is that INVITE transactions take
   a long time, while everything else is pretty much immediate.  So, in
   order to optimize our flow, we retransmit the INVITE until we hear a
   provisional response, and then wait for the remote end to retransmit
   its final response.

   Unfortunately, this assumption is now false, and long-outstanding
   requests such as REFER must be continuously retransmitted to poll for
   the response when used over UDP.

  The main problem is trying to use the request/response model with the
forking concept.  If I were redesigning SIP, I would clean things up by
making every transaction a 3-way handshake for protection.  I guess you
would also want to fix the retransmissions over TCP thing too.  Ugh.

-- 
Billy Biggs, 3Com               Email: [email-masked]
http://www.div8.net/billy/      Phone: [email-masked]

---

From: "farhan" <[email-masked]>
Date: Sat, 18 Nov 2000 17:53:36 +0530

>    the response when used over UDP.

yes billy, forking is out of question without an ACKnowledgement. thanks for
pointing this out. however, as forking is not an essential behaviour,
couldn't it have moved away to
be invoked only under certain conditions like Requires:acknowledgment. ?

TCP/IP does a three way handshake too. it however has very different reasons
for the handshake. TCP/IP's three way handshake has been called 'necessary
and sufficient' by late richard stevens. tcp/ip handshake is not for a
transaction but for a stream creation. therefore, the starting sequences
have to be acknowlegded by both ends. There are actual two two way
handshakes in tcp/ip, called end point sends a syn and gets and
acknowledgement, then the called party sends syn and gets an
acknowledgement. The four way handshake is merged into a three way handshake
by riding the called party syn and ack into a single packet. However, that
is no parallel for SIP as I see it.

I am wondering if there are also issues of call parameter negotiation that
require (or get enhanced) by a three way handshake

---

From: Billy Biggs <[email-masked]>
Date: Sat, 18 Nov 2000 07:06:43 -0600

farhan ([email-masked]):

> yes billy, forking is out of question without an ACKnowledgement.
> thanks for pointing this out. however, as forking is not an essential
> behaviour, couldn't it have moved away to be invoked only under
> certain conditions like Requires:acknowledgment. ?

  Nope.  There is no way to tell if a request will fork, and for
security reasons the proxy server may not wish to disclose that the call
forked to multiple locations.

> [...] tcp/ip handshake is not for a transaction but for a stream
> creation. therefore, the starting sequences have to be acknowlegded by
> both ends. [...]

  Right, but in SIP you can setup a signalling connection (the parallel
to a TCP/IP stream) using any method, not just INVITE.  So, as you
noted, setup of a SIP connection definitely does not require a 3-way
handshake.  It's just that INVITE needs to be more robust and
responsive.

> I am wondering if there are also issues of call parameter negotiation
> that require (or get enhanced) by a three way handshake

  Not really.  A client can delay sending a session description by not
sending one in the INVITE and later sending it in the ACK, but that is
simply a convenient optimization.  In an INVITE transaction there are
only ever two session descriptions, one for each end.  For an API, the
ACK is only to stop retransmissions, there is no need to have a concept
of a 3-way handshake.

  One thing I forgot to mention: another reason why INVITE needs to have
this special mechanism is to ensure speedy call setup.  When the called
party picks up their phone the response is retransmitted to help setup
the call as quick as possible.

---

From: Henning Schulzrinne <[email-masked]>
Date: Sat, 18 Nov 2000 08:55:26 -0800

The speedy call setup is the main (and motivating) reason. The only
other alternative (with an unreliable transport) would have been to have
a separate, callee-initiated transaction that says "I accept the call".

All of this motivation, by the way, is contained in the spec in the
section on transport. The reason for not making other methods 3-way was
to make them simpler and to reduce message count, something that our
wireless friends are very worried about. The ACK does allow to delay the
session description, which is useful in some scenarios (some versions of
H.323 interoperation, for example), but that by itself is mostly a minor
advantage.

As usual, optimization yields complexity.

---

From: "farhan" <[email-masked]>
Date: Sat, 18 Nov 2000 17:44:18 +0530

---

From: Gonzalo Camarillo <[email-masked]>
Date: Sat, 18 Nov 2000 20:06:17 +0200

Hi,

A 2-way handshake would lead to the following situation:

A sends an INVITE to B and begin retransmitting it. After a while A
gives up and stops retransmitting the INVITE. A thinks that there is no
session established.

At the same time (when A is giving up), B sends a 200 OK back. Since B
observes that A has stopped retransmitting the INVITE the 200 OK in not
retransmitted, B thinks that the session is established...

A 3-way hand-shake helps synchronizing both ends during session
establishment.

Regards,

Gonzalo

-- 
Gonzalo Camarillo         Phone :  +358  9 299 33 71
Oy L M Ericsson Ab        Mobile:  +358 40 702 35 35
Telecom R&D               Fax   :  +358  9 299 30 52
FIN-02420 Jorvas          Email :  [email-masked]
Finland                   http://www.hut.fi/~gonzalo

---

From: "farhan" <[email-masked]>
Date: Sun, 19 Nov 2000 02:02:44 +0530

> retransmitted, B thinks that the session is established...

imagine the samething happening on the ACK. Party B keeps sending 200 OK
until it times out and just then Party A responds back with an ACK and
considers that the session is established. No, that is not a solution we
need an infinite way handshake in such a case.
- farhan

---

From: Gonzalo Camarillo <[email-masked]>
Date: Sun, 19 Nov 2000 12:50:50 +0200

Hi,

You were asking for the historical reason of having a 3-way handshake,
and that is what I answered.

Check page 6 of the first version of SIP and you will find the same
explanation as I gave.
http://www.cs.columbia.edu/sip/drafts/draft-ietf-mmusic-sip-00.ps

More comments inline:

> need an infinite way handshake in such a case.

Actually, if the network fails completely to deviler datagramas you
definitively have a problem. However, a 3-way handshake makes B
retransmit his 200 OK a number of times since the ACK has to been
received.

A big difference between the rest of the requests in SIP (that have a
2-way handshake) and INVITE (3-way handshake) is that the rest of the
requests are usually retransmitted by the UA until the transaction is
finished without the user stopping this process.

For example, if a user hangs up (he is using a SIP phone) his UA will
retransmit the BYE as many time as necessary until it gets a final
response.

However, the user can try to call someone and hang up before a final
response arrives. This stops the retransmission process of the INVITE.

But even if the 200 OK got lost, since the ACK will never arrive the
callee will not believe that there is an established session.

Best regards,

Gonzalo

-- 
Gonzalo Camarillo         Phone :  +358  9 299 33 71
Oy L M Ericsson Ab        Mobile:  +358 40 702 35 35
Telecom R&D               Fax   :  +358  9 299 31 18
FIN-02420 Jorvas          Email :  [email-masked]
Finland

---

From: Chris Harris <[email-masked]>
Date: Tue, 21 Nov 2000 11:25:32 +0000

Erik,

The implication of what you say is that all set methods in the header
interfaces which take String arguments must throw a checked
JainSipParseException. I think this is reasonable given that different
implementations will be more tolerant than others. However, in order to allow
lazy parsing by an implementation, all get methods in the header interfaces
(regardless of return type) must throw a checked parse exception. This is a
lot of checked exceptions - and will make life more awkward for the
application developer. It would certainly be much less effort to not allow
lazy parsing - there would be no need to throw a parse exception for all get
methods - greatly reducing the number of checked exceptions. Unfortunately it
has been said that JAIN SIP support for lazy parsing is a must. If it is then
I guess there is no other choice than to include the exceptions?

Regards,
Chris

Erik Nissen wrote:

> The rule of thumb is to use:
> * checked exceptions when the program should handle situations which
> can/will occur.
> * runtime exceptions when there are programming error (God forbid :-)
>
> So:
> Parse errors should throw checked exceptions.
> Becaurse parse errors are outside the control of the programmer
> and he/she should be forced to handle such conditions in the code.
>
> Null/wrong arguments should throw runtime exceptions.
>
> If it is possible, reduce the number of methods throwing (checked)
> exceptions
> to a minimum.
>
> Best regards,
> /Erik Nissen,
> Ericsson Utveckling AB

---

From: "M. Ranganathan" <[email-masked]>
Date: Thu, 23 Nov 2000 20:30:37 -0500

â°Jâ‘hb•ìj·¨žØ^²æãyËh|L\z›b¢{0‡'hžéej¸.™éí²Øk£
îžØ¦yì\z›b¢{0…éò¢çhj¢{azahìZš™^Š{axz›bž×«}§ëB¢{^žÔ®nÜ©zØk£"Y^©@®¦z{DÅÇ©¶*'‰ø¬žée ÁÎ"ØbžHŠËÚ–'m¢¯y©î–[.nÜ©zÊ0‡)è¶;¬¶·º¹çºYkjØ^®ØZžØk£±qêmŠ‰áz·ˆv‰íªèyú%–Œ-…æ«‚éžžÛajÙZÏ*Z®È§‚wœzË"µ«^²Øk£§ªZ®ÇžÅÇ©¶*'~ŠÚ–X¶g†‡lêÞŠÌ!jÒ!i×§¾+"¢wÕh^©ž²Æ yÊ&zÈ§ŠÜ"–VÞ±êZ«^v)í¢šuêìm«v‰íÊ—¶N¡y§^¯
.•ÖÞ­ën®wÂ+až‡âzWbž+bjX³y×±qêm¶{\¢ºÞ²š'v)à¶‹azg¬±¨¶¬Â‹¥vwœzË"µ«^{¦Šx§‚Ø^~*ìµ÷°o+^²‡í…éž²Æ zÚz×«š)Þ¶¡y§^®Ü©y»¶«zËkzf¢žË§¥ªìyÖ(¹Æ§j[(²Ú0k²¶Ê—¢ú+™«b¢x§¶‡y§^®ØZ¶++zÛ«çZ³¥–Ú$žŒ0†'!¥ªìzºî•ëhŠ{è‘éZµê÷-«^¯^žØ^jše‰Æ­Š‰ðj{l¶ŠZ®Ç­…è^i×«ŠØZ²Ø^²Úâž(®·¬¦‰ÝŠx-¢Ø^™ë,jš×ž§v+h}ûh¶©j»¯bržØ^ø¥–)í…æ©¦º)®&yøž•Û¢ºÞ²š'v)à¶‹azšuêøJæìz«žžÙr¶š¦™bq«b¢w§zË-…çâzWlŽë-jÆ§y¨®–«±êÛjÇjše‰Æ­Š‰ð¢é]v…¡z·š˜‰¢²È§‚Ø^n†Â+a¶¬"Ö©¥æ«²ØZ·Z¶+z)àjÛ^š›^v«z™^jÇœ¢ºÞrÙž‰ò›
èž¬¶‹¬yì\z›b¢{±©žr§ŠÉ­¡Æ­r§Šx‰©bÍç_‰é]²Ê-…êZ®Ç«q©Ûz)ï¢GŠ{ayì\z›b¢xZÙ^®—«…ªlN¬•æ²Ú–‹h~‹Þ®šv)Ü–éäÉÊx‹aŠy"¶+š+-jG¢Øk£±qêmŠ‰ì¢w¯z¼ zÛh¶¼¢šèµç-¶š¦™bq«b¢wë¢h§iÛÞ®×§¶\šqÇ¬²)à~'¥vËajØZ½éèµ·žž)â¶&¥‹7Z§¢Øî²Ö¬²éž¶¶š¦™bq«b¢y®²ÖÞ²f«µéèºm¢–«±ëazšuêí{[yú+y§zË"žâzWljwg¢ÛkÊÚ)®‹âuæœ¢je{žr§ŠÉš±¦è½ä^ªÝ±§ ¡®+jºâ³
èµá+ŠDáz)©–'¶*'¡ü!jÜ¨ºÆ²ŠËajÖ¥–Ç­™ëa¡Û"žØ^…æz¸§µêßiÇ¬Âœ†Ö¤y+kŠx®¦z{lšë-¶èÁ§!yÉt–¢(©=ªìxL\z›b¢r-†)ä¶¬ŠÊÞjÊ'i¹^‚+ÞžØZµØŸ}êÞžØ¦¦W¦z{Z¶*'³¥•·¦¢·¢W«j{m…©è¶«°z0z÷«Šz+uêí¡©e£	ZÏ*Z®È§¼šž)©•éžžÖ­Š‰Ú–X¶g†‡lŠ{azšuêâž×«}§²· j·ezË(~·º¹íÊ—¦ºËm†º0iÈ^rG¥ªìyì\z›b¢táŠÈ¬jZ-¡÷!yÉuì\z›b¢{Ü"–Yš‘éb}é¨­æ°“«uú+¶š¦™bq«b¢w^½éh¥êÈ·
.•×®Ö¢ž\›zkœ†W¬±çß¢»m¢z-jYhÂV³Ê–«²)à¶«{
.•ÖÞž‰ÞyÛh¶èÁªZ®ÇžÅÇ©¶*'~ŠÚ–X¶g†‡l‚·š¶\«yÛœŠx-…éî™·«¡÷!yÉuì\z›b¢{ú+¶éÚµérŠØZ±·žžÆ¢vØZ´5"²êi¢»_¢¹ZÏ*Z®È§‚+šë-!øŠËazr ¹ë,¶«z+'¢‹az·!¢'¶§¶ˆ§r[zØ^{¦Ø¨žÄ^ªÝ°(kŠÁ+ŠCb²Ç§Âº-x(kŠÁÚ®¸¬Âº-yg§yçm¡×œ‰×°…ëaz»aŠË!¢é]mæœ…ç$yÚ+®éíŠgžÅÇ©¶*'N«ºW¨~Øn™¸¬¶‹¬yÈ^rG{¦Ø¨žÌ!z{azšè‚¶¦².•ØZÙ^²+njØ¨žÌ!‰È\jðŠYhqË«®éíŠgžÅÇ©¶*'³^žØ^æ«zšè‚¶¦š)àzºè¬j~ŠÛ‰Ô¨=ªìyêë¢»,†‹¥vØk£!yÉuì\z›b¢{yÆ®®Ç©j»zºè®Æ«z‹²'^¶œ¢{k¢Z¶©®ˆ+již©Ý…ïì…ë!¢é]mçèÇ¶ˆZÙ^²ç!r‰ÝŠØ¨žÈ§¶œ¡×ºYÂº'ªàºg§¶Ë!¢é]¶èÂ»§¶)ž{¦Ø¨žÂŠØ¬¦‹,‰¹^çnqëaz{¦mêè~g†‡l¶èÂ)àrœ‘ç^ÅÇ©¶*'²Úš)âšézËkz«vÏÄ®)
ŠËœJârË(KoyÉ%Šx"™¨¥Šx%ŠËR ùb²ÛzYei»¢hm¶Ÿÿ–+-±·¥–V›±Ê&þf¢–f§þX¬¶)ß£û"¤ÄZž§jØZœÒLojwt×­ÂŠäŠxyÈg¢Z ‰ë®‹©×Mº·š¸:â½ä­¢Ÿ=ÛAšŠØ^®Æî®ÛO=õ7¥ßM}ïúëZÇ}5çÝ4÷}

---

From: Chris Harris <[email-masked]>
Date: Fri, 24 Nov 2000 15:02:19 +0000

Ranga,

See comments below.

Regards,
Chris

"M. Ranganathan" wrote:

>
> Chris, Erik,
>
> While we are on the subject of Exceptions, why do null arguments throw
> runtime exceptions when you do a get on them? For example, in the
> Accept interface, getContentSubtype throws a IllegalArgumentException
> if  is null. IMHO, I think it is valid to have a null subtype so why
> not just return null rather than throw exception here?

By a "doing a get on a null argument" here I assume you mean attempting
to get a non-existent optional field? If you do this a checked
ParameterNotSetException is thrown, not a runtime exception.

There are two approaches to handling optional header parts. One approach
is to allow the passing and returning of null objects from get and set
methods (implicit "remove" and "has"), and the other is to explicitly
add has and remove methods (and exceptions on the set and get methods).
As for mandatory header parts - I think passing null to a set method
should definitely throw an IllegalArgumentException.

(If it is considered acceptable to have a "null" subType then we should
make it optional)

>
>
> I don't quite follow the argument that lazy parsing  "necessitates
> throwing a parse exception for all get methods".   Here is what I had
> envisioned:
>
>
> 1 When a message comes in it will be separated into headers based on
> type.
> 2 The header would be returned with no field initialized except the
> text corresponding to the message. (this would necessitate examining
> the first few bytes of the message to determine the header type but
> the rest remains unparsed.) You can also stow away the type
> information in the Header that is returned as well to know which
> parser rule to invoke later.
> 3. Later, when the application wants to parse the header, it has the
> string corresponding to the message and can hand it off to the parser,
> which can then fill in the appropriate fields corresponding to the
> header.
> 4. Subsequently, the application can access the fields just as an
> eager parser based application would do.
>
> ( Where am I missing the boat with this? )

An application has no idea whether an implementation is using lazy or
eager parsing - it is simply passed a header object - and then if it is
interested in a particular field it calls the appropriate get method
(which would internally invoke the parser in a lazy parsing
implementation). So the application is completely oblivious to whether
or not this "optimisation" is used by the implementation.

If the field is optional and does not exist in the header a
ParameterNotSetException will be thrown by the implementation. If the
field is mandatory and does not exist, a JainSipParseException will be
thrown (header is malformed). If any header field is malformed a
JainSipParseException is thrown. If a JainSipParseException is thrown,
this indicates that the application must use the header's getValue
method to get a string representation of the header value and do what it
can with that.

>
>
> It appears that what is being attempted here (please correct me if I
> am wrong) is to use exceptions as a mechanism to catch un-initialized
> fields so the parser can be invoked in the exception handler perhaps.
> This leads to a lot of overhead in clunky code. I think it is a
> mistake to throw exceptions on every get to try to protect the
> application from inadvertently accessing fields that have not been
> initialized.  Why not just assume that the application must be smart
> enough to parse the header text before accessing fields and not try to
> provide a complex mechanism as above?

We are using ParameterNotSetException for the case of an optional header
not existing, and a JainSipParseException for the case of a malformed
header being received from the network.

If we assume the application is smart enough to do all header value
parsing, we reduce a header to just being two strings - the type and
value, which puts the burden of parsing on an application - this work
can be done by the underlying implementation - doesn't it make more
sense for an application to catch an exception than have to parse all
header value strings (especially since this functionality already exists
in the underlying stack)

---

From: Chris Harris <[email-masked]>
Date: Mon, 27 Nov 2000 15:05:02 +0000

Ranga,

My comments are in red...

Chris

"M. Ranganathan" wrote:

> Chris,
>
> Thanks for the prompt response.  Hope you had a great Thanksgiving.

I wish there was such a thing as Thanksgiving in Ireland :(

>
>
> My followup is below. ( in blue)
>
> Regards
>
> Ranga.
>
> Chris Harris wrote:
>
>> Ranga,
>>
>> See comments below.
>>
>> Regards,
>> Chris
>>
>> "M. Ranganathan" wrote:
>>
>> >
>> > Chris, Erik,
>> >
>> > While we are on the subject of Exceptions, why do null arguments
>> > throw runtime exceptions when you do a get on them? For example, in
>> > the Accept interface, getContentSubtype throws a
>> > IllegalArgumentException if  is null. IMHO, I think it is valid to
>> > have a null subtype so why not just return null rather than throw
>> > exception here?
>>
>> By a "doing a get on a null argument" here I assume you mean
>> attempting to get a non-existent optional field? If you do this a
>> checked ParameterNotSetException is thrown, not a runtime exception.
>
>
> Yes. Thats what I had meant.  The word "argument" should have been
> "field".   Why do you need a  ParameterNotSet exception in this case?
> Are you trying to handle the case of basic types like integers, floats
> and so on ? For objects, null is synonymous with not set isnt it?

We discussed this matter in depth at the last JAIN SIP meeting in
October, and we came to the conclusion that getting and setting null
values is not a good idea for several reasons e.g. it is easier to debug
a ParameterNotSetException than searching for the source of a later
NullPointerException, and it forces the application to allow for the
fact that there is a reasonable chance that a particular field does not
exist. [Of course, if we did allow the use of null, we could cut down on
the number of methods and drop the ParameterNotSetException - but  is it
really worth sacrificing clarity and robustness for the sake of cutting
down on API size?]

>
>
>>
>>
>> There are two approaches to handling optional header parts. One
>> approach is to allow the passing and returning of null objects from
>> get and set methods (implicit "remove" and "has"), and the other is
>> to explicitly add has and remove methods (and exceptions on the set
>> and get methods). As for mandatory header parts - I think passing
>> null to a set method should definitely throw an
>> IllegalArgumentException.
>
> I have the following questions about setXXX methods:
>
> 1.  Why do you restrict throwing IllegalArgumentException to only null
> arguments in some of the headers? Why are you not checking for proper
> formatting of the passed arguments (by giving it to the parser for
> example and running the appropriate  parser rule).

In general, an IllegalArgumentException is thrown if an argument to a
set method fails basic validation (i.e. no implementation-specific
parsing is used). Note that an application can ensure that this
exception is not thrown by following the rules defined in the API . So
if an argument is a String, I throw an IllegalArgumentException if the
argument is null or zero-length.

Of course this is not sufficient validation and the string must be
parsed to check for whitespaces, newlines etc, and different
implementations will be more tolerant than others. This is why there is
a checked JainSipParseException - an application cannot tell in advance
if a particular implementation will accept a certain value, so it must
catch this exception.

I am proposing that this exception should also be thrown by get methods
(for all fields), because if an implementation uses lazy parsing, then
there is no guarantee that the header value will parse correctly upon
the invocation of the get method, and again this is
implementation-dependent.

>
>
> 2.  A more general question - why do you have set methods at all in
> the interfaces?  The class that implements the interface can have set
> methods but the interface itself does not need to have them.

I have set methods in the interfaces because the objects will not only
be coming up from the implementation - an application needs to be able
to create and send requests, and this means being able to set the
values.

>  Moreover, the parser has the job of setting up stuff in the returned
> object. It has a set of BNF rules to decide on the correctness of the
> arguments and it does not need for the class to re-implement the
> check. For example, I think it ought to be the parser's job to check
> if the q value is between 0 and 1.   (Is the purpose of the set method
> to allow for the application to do header formatting?)

I absolutely agree that the parser should perform validation (hence the
JainSipParseException) - but as I mentioned above there are certain
basic criteria that must be met by all implementations and applications
- I am using the IllegalArgumentException to cover these. Perhaps
certain cases go too far in this validation - perhaps the
IllegalArgumentException could be thrown only if a null argument is
passed and all other validation is left up to the implementation's
parser? (although a problem with certain cases such as PriorityHeader
comes to mind, where the header values are defined as constants in the
API and an IllegalArgumentException is thrown if any other value is
passed - should we allow any non-null String values for the priority? Or
to take your example of q-value above - should we just allow any
non-null Float and let the parser enforce the 0-1 range?

>
>
>
>>
>>
>> (If it is considered acceptable to have a "null" subType then we
>> should make it optional)
>>
>> >
>> >
>> > throwing a parse exception for all get methods".   Here is what I
>> > had envisioned:
>> >
>> >
>> > 1 When a message comes in it will be separated into headers based
>> > on type.
>> > text corresponding to the message. (this would necessitate
>> > examining the first few bytes of the message to determine the
>> > header type but the rest remains unparsed.) You can also stow away
>> > the type information in the Header that is returned as well to know
>> > which parser rule to invoke later.
>> > 3. Later, when the application wants to parse the header, it has
>> > the string corresponding to the message and can hand it off to the
>> > parser, which can then fill in the appropriate fields corresponding
>> > to the header.
>> An application has no idea whether an implementation is using lazy
>> or eager parsing - it is simply passed a header object - and then if
>> it is interested in a particular field it calls the appropriate get
>> method (which would internally invoke the parser in a lazy parsing
>> implementation). So the application is completely oblivious to
>> whether or not this "optimisation" is used by the implementation.
>
>
> Ah! ( Why is this hiding  of the implementation so important? )  Can
> this be handled in the following fashion by an implementation:
>
> 1. The implementation keeps a flag in the  class that implements the
> interface whether the parsing has been done or not (i.e. boolean
> parsingDone flag).
>
> 2. The Implementation keeps the entire string corresponding to the
> header in the object. So the parser has to peek into the message
> header to know what type the message is as soon as it has the  header
> string and then grabs the string and stores it away for lazy parsing.
>
>
> 3. The get Method  checks if the flag has been set, calls the parser
> to do the parse if the flag has not been set and then returns a
> parseException if the parse fails. This can be done transparently to
> the caller.

This is exactly what I would expect a lazy-parsing implementation to do
- the fact that lazy-parsing is hidden from the application (except that
the application must catch a JainSipParseException on the get methods to
allow for the possibility that an implementation uses lazy-parsing - so
technically the application will know that an implementation uses
lazy-parsing if this exception is thrown by a get method - but I think
the two cases are handled nicely by the addition of the exception)

>> ParameterNotSetException will be thrown by the implementation.
>
> A suggestion (shoot it down if it does not jive):
>
> 1. All fields are represented by objects (not simple types like int,
> use Integer instead).

I buy this part - then the IllegalArgumentException is only ever thrown
if an object parameter is null, and the JainSipParseException is thrown
for all other problems with the argument.

>
> 2. If the field is not set just return null

See above for null discussion,

>
>
>
>
>> If the field is mandatory and does not exist, a
>> JainSipParseException will be thrown (header is malformed). If any
>> header field is malformed a JainSipParseException is thrown. If a
>> JainSipParseException is thrown, this indicates that the application
>> must use the header's getValue method to get a string representation
>> of the header value and do what it can with that.
>
>
> Why the headers getValue ? Why is the string not part of the
> Exception?

Sure - we can say that the JainSipParseException's message must be the
string value of the header.

>
>
>
>>
>>
>> >
>> >
>> > It appears that what is being attempted here (please correct me if
>> > I am wrong) is to use exceptions as a mechanism to catch
>> > un-initialized fields so the parser can be invoked in the exception
>> > handler perhaps. This leads to a lot of overhead in clunky code. I
>> > think it is a mistake to throw exceptions on every get to try to
>> > protect the application from inadvertently accessing fields that
>> > have not been initialized.  Why not just assume that the
>> > application must be smart enough to parse the header text before
>> > accessing fields and not try to provide a complex mechanism as
>> > above?
>>
>>
>> We are using ParameterNotSetException for the case of an optional
>> header not existing, and a JainSipParseException for the case of a
>> malformed header being received from the network.
>>
>> value, which puts the burden of parsing on an application - this
>> work can be done by the underlying implementation - doesn't it make
>> more sense for an application to catch an exception than have to
>> parse all header value strings (especially since this functionality
>> already exists in the underlying stack)
>
>
> No that is not what I had intended. Parser functionality exists in the
> stack but has to be called explicitly by the implementation. Too much
> hiding of the implementation from the application has its own set of
> disadvantages (IMHO).

I wanted parser fuctionality to be invoked implicitly by an application
- from the API perspective it is an implementation detail - so the
application should not be aware of how or when the underlying parser is
invoked - it should just know that it is there in some form, and that if
it tries to get or set a value that the implementation doesn't like it
will get a JainSipParseException thrown back at it. This is important if
we want to maintain the three core values of JAIN - portability,
portability and portabilty ;)

---

From: "M. Ranganathan" <[email-masked]>
Date: Mon, 27 Nov 2000 15:26:47 -0500

â±8ZžK¢»azšèš›kzÊhžÇ¢Ûhv¶ ¶¬¢wèëÞ­»"¯y§ÞÂj+zË ë-Š‰ìŠwè–Z0º›hÊ‹«r‰¦z{lýÉZ®'âq«b¢{"¹ny·¥£,Ê‹šè§"·¥jwr¢êæŠË"•ëjyè¶·šrž²‚jvÞn‰]EèÛjx×¬Š	â²Ëžž‹]ŠÇ.²ÇméhÁh^ëÞ®Ø^è¬šŠÞ¶§¢w¡y§^®Úz·º¹Þvøš…æz»¢·±jje{*.ën®v§jºÚÈ	Ú®¶²ŠÇš³+hÁ©d¶èºG£¯z²0¢é]¶§’+f¢·®±çî–Ú+zÛ«§(–Wœ¶*'¡û(™ë(®ÛajÛ.¦š+¶Æv+b¢v¥™ëa¡Û,¹ÈZ±È^rH§‚'Ú§]ë,{¬¶È§¶¥ŠËh~šuêìën®wz×…«fŠmmê²‰žºÇ­¡©âš™^™éíjØ¨œ‡ò¢ç^~)Þ¶«zÛ«çmÊ—š±©Ú®¶²¡ø^i×«²Ø^è¬žŒÊÚÆ×§vØ^rV¬²Ú,ºšh®Öv+b¢v¥~éÜ¶*'jXÈÆ²"Ë ë-i×bžœ¢Y^rØ¨ÉZ²È§µêßiÇŸ¢·(–Wœ¶*'²‡Ò ñÞi×«±©Ý¶q©ÛzÊ^r&¥‹7o(¦¦W¦z{Z¶*'²Ú,ºšh®Öv+b¢v¥ªç«Êg†‡lz×,k+(™ëaŠx%ŠG’ ñÞi×«.+-
â°v«®+0®‹^E©àhÌœ¢ižžÛè§­çB†¸¬1§©Ú¶§Âº-x(kŠÄájy,~Ší…êk¢jmë)¢{Š^Ê‹¡iÖ æN§’È"¾)à#¬†Ø^ì²Ëœ…«aŠx±8ZžK Šø§‚)È­éZÓ2~‰e£©ŠÆÞ–Œ"¹ny j·lE©àh(kŠÁÚ®¸¬Âº-y§¤žyÊ&™éí±·¥£^ªÝ°(kŠÃjx«aj|+¢×‚†¸¬¸¤Z¥{šê'¶¬¹¸ÞrÚ¦Ø¨žÌ!ÉÚ'ºYZ®¦z{l¶èÂ»§¶)ž{¦Ø¨žÌ!z|¨¹ÚëhžØ^˜Z+{¦¦W¢žØ^Ç¦Ø§µêßiÇ zÐ¨ž×§µ+›·*^¶èÂÆˆ–W jP+‚éžžÑ1qêmŠ‰â~+'ºYH0sˆ¶§’+b²ö¥‰Ûh…«Þj{¥–Ë›·*^²Œ!Êz-Žë-ën®yî–ZÚ¶«¶§¶èÁì\z›b¢x^àriÚ"ž zÚ'j{¥•ªàºg§¶«x†¬²éžÊ‹¦y©Ú¶×¦¦Ø§‚Ú zÖ§¢w±ŠË^žÚ)¶*'jWâzWH*.v‹aŠÆœ…ç$yÓÚ­©žµêÍ¢Ôž´L\z›b¢x¬¶èÂyèµªîžØ¦yì\z›b¢v±8Z¶Ì!jÒ!iÙžj{S…ì(Ö«‚éžžÛ!¢é]…«Þmç§~'¥uhrvŒ¨ºwžu£Ú­©žµêÍ¢Ôžµì\z›b¢x§¶¬q«·²¢ëkÊ)à¶ˆZÙ^¶œjÇ¨}¶¬‰Ër¥ë%ŠG¢ž× z»–†±©Ý²Š'Šèn7œ¶Éî–X¬³)èŸ)¨ºÌ"¶è¶Ç­ŠÉíŠÕžv+ºËvØb²fµêâ×©¶¶¥jËIƒR ùžzØ§‚)ÎrÚz¶§wœjg¢Ø^r‰Ü–ë"¢{ajØ¶Ø§©Ý±ëmŠx'ºYoj[ž²+'¢Ö ¢‡buæŸ¢»½êÚ–·š²‰ìzŠÇš²'«¶‡^nè=ªÚ™ë^¬Ú-IëDÅÇ©¶*'¶§±æ«r§ú+¶¬¢êÜz‡Ú•«^¬Û¥”ú"ž×«¦Ø¨©ÝŠ×èÇ¬¶š¦™bq«b¢{hjYhÁú+¶ŸiËm…«m…êÞŠÆ«y«(¦åyÈZÇ­…«Z¥ªí‰Ë¥j·âzW]¡ë'¢×±ŠËN}Ê.®Ç¢‰Ö¥–Œ-…ë¬z‡çºYpyÊ.•×.µÚ0ž‰í…éî™·«¡ùž¶±©Ývº)¶j¶¦z×«6‹RzÑ1qêmŠ‰ÛºØ¬ŠÚÞjYrÂŠí†Æœ®'âr)àrV«ŠÜšÚènë-ë,~Ší…ë‘êrëmŠx£	èœÈ²,ÞYée"ž²ËajØ¬j;éžž×–U¢¶aŠÇ^²('Ê‹¦k(Z½ç(uëajØ¬r[µêÞw…©h¶‡ÞÅÇ©¶*'…©Ý•êìjwm…à"+*º+^n(…ç$Šx¢¹î–X¬}¨«—+-jwZÖ¦"¯Šx&É¨k²jwHq©ìyæ­•æ¬µ§ÞÂ™Zqë"žØ^m«$@ò0…êÞžéeŠÊÞ¶êçyÛhuéèµç¦¦ÜšÖ§Ë²¶š¦˜Z±¨(¡Ú%vËZrKkiÇ­¢·¥Ê‰í¢Çž¶¬¢êÜz‡í…ç±qêmŠ‰ð…éçºYi¢)íz»ç§r‹§µêÞtkšØ§©Ú¦™bq«b¢wë¢iî–ZhŠ{^ì\z›b¢x¬¦··(ZÖ§Ë²²Œ!ÉÊ&¦Xœj×­…à"Ú!jwezØb²‰Þq«ŠÜ¢Y^rØ¨žÊHƒÇy§^®Ì¨¹Æ§rœ‘ú+zjmÉÊ%•ç-Š‰ÚÜ¨»¥–z-…«Þ¶¬¦º•é“…êÞj·Â†©¦ºr¬¶ˆZÙbž
)¶*'jX^i×«¥ªí°éÞjšk¡§!ŠËhjYhÂØ^¥«,ŠxÚÞ¶êçŠx(~{¥–†ãyËl~º&ëZÛ¶g†‡lŠje‰È­é¨½æ§v¬jwm…ê-…êâ²ÚÆ™br+eÉ§]…«ÚÞš‹Þ™ëa¡Û×±qêmŠ‰ì¢{azÇ­jw`zÙž¶°¢¹šÖ­¢¼¡y§^®–«¶Â-†)ä¥«,Šx'ºYm¡«¶g†‡l†‹¥u×ŸŠxz\†º0jr%•è”
àºg§´L\z›b¢r!j÷…çè–Z0Šx*¹ë-Š‰ìiº.¶Ç­]uæzØhvÍV‡'hÊ‹«zËk‰Ëm†º0Šx–W jP+‚éžžÑ1qêmŠ‰í¢‰åÊ{¥•ªàºg§¶È§²‰ž¡ûazšuêìZšì¨ºz-rœ’)à~Šé®Š^ú+™«mŠx(~Ø^¥«,yÖ«‚éžžÛÊ¯Šx"¶Ú-…êZ®Ç«~ŠÞÅ©©•æ§v»§ž)à¶š¦šè¦¸šµêZ®Ç«®é^"xêÚ•©È–W jP+‚éžžÑ1qêmŠ‰â²Øk£	â}©Ú®¦z{m¡«¶g†‡_j)lm«"rö¥‰Ö­Š‰âzz"š™^™éíjØ¨žÊ^r'âr–«²)àŠË¬yÓhµëajÖ§jše‰Æ­Š‰Üjw§²êÞ¶¶¬{¦Ø¨ž+'¢Ûa®Œ'o'è–Z0Šx-…êî•ëyø§yØ§¶€<„¨‰ö§j¸.™éíŠÆ’¶¸§€‹a®Œœ‰ez¥¸.™éí¦Ø¨ž'í…æ«‚éžžØ¬žée¢¼Þ®‰^ža9÷(º»¶¬ŠÉè¶ËŸ~'"z{ojXjØ¨©Ý¶¬¶¸§‚k¬µ·©j»vÚ…ç$~Šð†+^²–œzÉÞÂX§zÇ­q©Ýv'ßz·§¶)©•éžžÖ­Š‰ìÂ)emé¨­ëh•êÚžÛajz-…êìN¬ŠÌ!ÊØ^è¬iÈ^rG%¨§J*Oj»¦Ø¨©Ú¦™bq«b¢wžz-µéeŠv½©Üz'Ú¥ªí‰Ë¥j¸¦¦W¦z{Z¶*'Â)eiÇ¦Öœz»ZŠ{Ú–ç¬¢+fºË\j×!¶¬{¦Ø¨œ†¦¦º)¢È§‚ØZ¶Øb±ì\z›b¢{!¢é]j[(mëa®Œ'o(¶g†‡l~ŠÚ–WâzWlmçºÇ¢}©âš™^™éíjØ¨žë²V³Ê–«²)à¶§¶«z+'¢š©íyëajÛazšuêïj[žÂ)e¥ªìyÊ+ç-—+©¢{az)ï¡Æ­Š‰è~Ø^ëfzØhu©Ýj¢žØb²+"š™^™éíjØ¨×©zw^žÝ€šŠÞéÞ­©j¹ë-Š‰ð‡'hÊ‹¡j÷¬zÙž¶±«Z–X§¶¢ž×«}§±8^rV¬²ØZ¶)©•éžžÛ-…è§µêßiÇœjxZ½ë¶g†‡lnëm…è§µêßiÇ¢¶Ç¥}Ú²z-ç¶ˆZ½ëazb!j÷¬zÙž¶²)í…è§µêßiÇ¬mçºÇ­…êç-³¥–z-¢yrmç(š)àº—ë¢kaz)©•éžžÖ­Š‰Úªi–'¶*'ç²Úy¦åzÚæy©Ý±éÝ­ê®zËljwm†+&y©ìmè§¦åzÚ,zÛazö¥¹ë„Ì®×«²Ö§v)àÁ«¢ºÞrÛazsŠ=êáj›-†+0¢é]mëh¢kœ†‡Úr§çè¯*.¶‡(žÈz¶î¶W™éš‘æ¬º²Ø¨©òÁ¬ˆ¶§‘ú+™«mŠx!y§^®Ë!¢é]mç(žÈz·ºw^§b}÷«z{lzÚòz·¢³Z´†¦²è zËbž
FzÚâv‡í…ëµu×Š{^öœzËaz–«±êðŠYaj÷Š·œµ§zË-¢Ø^rV¬±ë×hzÉè¶wžvØ^™©ÝŠÜ"–W.µÚ0žØ^²,Þ¡ûaxÈØv¯y¤ˆ<Ç¬±¨ŠæjÛ^®)íz·Úqì!¢Ç¬¢W£¡¸ŠËh~ŠæjÚ.¶›™ë,j¬N¬q©áj÷¦zØhvËh~ŠæjÛayØŸ}êÞžÚ.¶
"ž	ž²Æ zÆ§w¥–Øk£
Z®ÇžÅÇ©¶*'²'í…ë-®)à²ØZ¶+`zÛè§rŠëyËS…ã²Æ xZ+™«mz¸§µêßiÇ­jG¬jÊZ©žµêïj[ž²‰åÉ+kŠx,
‰Ü­ë^—'èìZš™^¦æå‰È§µêßiÇ’ ó²Æ xZ+™«mzºnnXœJÚâž+y«^º&1ë,j’¶¸§úè™+kŠx-ja®Œ,HƒÏj»¦Ø¨œ‹p¢é]më%£«~ŠÚž)©•éžžÖ­Š‰í¡ìm§-¶¬jg¢ú+™«b¢z.¶‡Ú²ÚîrÛ«y©Ý…©ÝŠÛhj–«±êß¢»Ú–'Z¶*' ÁÎZ(±è¦¦W¦z{Z¶*'™¬§¢ÜžÛhmæè¶«yÜ"¶Ú–'Z¶*'jÖ¥•©Ý•æ¯z+m¢Ø^ç"z÷«¶ŠÞç-¶¦zÆ zØ^æò™©"žaz)©•éžžÖ­Š‰ßjË^®Šâ¶f²v‹Þ¯'.®Ê+ÉÈ^rH§€Ê+z‹Þ®Ø^¥ªìz¸Z²Ø^Ž†è~Ç­¶)àº›-¹÷âžØ^ën®w¡¸ÞrÒ-…«±ëh|E®é^²ÚyÈz‰í…ç(®·œ¶w¬²‡í…æ«‚éžžÛØ­v‡¬ž‹gyç_¢»ayÉZ²Ëhè¦¦W¦z{m…ç!yÉ¢·±jjex‹aŠy"¶‹ †Ûhmëaz–«±êìŽ†í¡È^rHŸ¶ª½©nz+zÜz}ÝH²Ø^¦êé¢Ç¨~Ø^±ëfzØhvÚ–Z0~Ší…æ©¦XœjØ¨žÚ¢šuêß¢¹š¶Ø§€†›²‰nµérj
ÞzØZ¶Ø^¥ªìz»!¢é]¥êß¢¹¯jXjØ¨ž§qëax–¢(©=ªìxL\z›b¢vîµ«™éíŠ‰Þu¦è½ëaz·šç®Ö¢¶¬‰Ç+Š×«‰«ajÙ®²ÖÞ™ë[É©eŠjezg§µ«b¢{Ö©¦XœjØ¨žÂšë"žax‰ez¥¸.™éí¦Ø¨žÚ¢÷«¶¬x÷«…ªlqêíj)ÜjÇ¬‚‹h¡ö«Š{aŠËÚ–'Z¶*'¥êáj›-…â%•è”
àºg§´L\z›b¢w(ºW[zØk£	èž\¢}©î–V«‚éžžØ¬¥«,yÖ§u©e¢Ø^®ö¥‰Ö­Š‰â²WŸ¶êm¢Ø^Šjezg§µ«b¢{)j»©m†‹ …ªk¡¹^›…Ç«µ¨§q«²Ëœ…«®*+ŠÜ‡y§^Ê&zËhš)ÝÂ«zØ^…æz»Ú–ç¬j·yø§yÖ¬r‰ìµ©í²)í…à!©Ýjr%•è”
àºg§´L\z›b¢x¬¶èÂxŸj|¨¶«½©nz+)jËvÈhºWpy©e£§Êz'žéeJÚâžÚ–ç¬~Ší…êkŠŠâ·#«¶‹Z‘ì¨º·±jjez‡ê½©ny¦è½ë!¢é]Áèî²Ö¥–ŒŸ)èž{¥”YhjÖ§vW¶©j»éß¢·¶´Ö¶§â-†)ä"éÝz»-jwm…êhŠ{Zn‹rœ’)à~ŠçºYH¶§’'ò¢æ«y×švÇ­¢v¢›bžazÇ­™ëa¡Ö¬k²¡÷(žËk¹Ëbž^i×«²‰Þ².•ÛÚ–'Zµæ«‚éžžÛ/‰«az–«±êÚÛa®Œj»¦Ø¨ú+j|†)à¢Ø^®ØZž{¥•ªàºg§¶Ã§¶¨¶«…©Ý"šè¦‹²‰ž¶§éíŠ·¥ÉØŸ}êÞž×èÊ'²ÚîrØ§‚šuêìiº/x‡â¶+¢{"uêÞu§z›ZnW¢¯y©î–[.m<©zØ^Ÿ¬†‹¥vf¤z+h¦Ø¨©Hv‰íªèyú%–Œ-…æ«‚éžžÛajÙZÏ*Z®È§‚wœzË"µ«^²Øk£§ªZ®ÇžÅÇ©¶*'~ŠÚ–X¶g†‡lêÞŠÌ!jÒ!i×§¾+"¢wÕh^©ž²Æ yÊ&zÈ§ŠÜ"–VÞ±êZ«^v)í¢šuêìm«v‰íÊ—¶N¡y§^¯
.•ÖÞ­ën®wÂ+až‡âzWbž+bjX³y×±qêm¶{\¢ºÞ²š'v)à¶‹azg¬±¨¶¬Â‹¥vwœzË"µ«^{¦Šx§‚Ø^~*ìµ÷°o+^²‡í…éž²Æ zÚz×«š)Þ¶¡y§^®Ü©y»¶«zËkzf¢žË§¥ªìyÖ(¹Æ§j[(²Ú0k²¶Ê—¢ú+™«b¢x§¶‡y§^®ØZ¶++zÛ«çZ³¥–Ú$žŒ0†'!¥ªìzºî•ëhŠ{è‘éZµê÷-«^¯^žØ^jše‰Æ­Š‰ðj{l¶ŠZ®Ç­…è^i×«ŠØZ²Ø^²Úâž(®·¬¦‰ÝŠx-¢Ø^™ë,jš×ž§v+h}ûh¶©j»¯bržØ^ø¥–)í…æ©¦º)®&yøž•Û¢ºÞ²š'v)à¶‹azšuêøJæìz«žžÙr¶š¦™bq«b¢w§zË-…çâzWlŽë-jÆ§y¨®–«±êÛjÇjše‰Æ­Š‰ð¢é]v…¡z·š˜‰¢²È§‚Ø^n†Â+a¶¬v©¦XœjØ¨ž¬žˆy¬!zØ^©âš™^™éíjØ¨ž+.²)à•¬ò¢·šêéj»"žŠË"š™r¥«,yÖ¡y§^®†ãyËZÛazxŸŠØ¬Š{^ë-yØ§j–«¶'.•ªß‰é]Š×–[-…æ©¦º)®&z™ëa¡Ü!‰Èp¢é]Š{^®v¥—(§¾‰¶©j»®)Ú•¬ò¥ªìŠx"š™^™éíjØ¨*-…æ©¦XœjØ¨ž+¢jez×¥Ê†åŠø¨ºËhÂ…êè®z-¶¬¢›bš+¶*'ŠË¬yÖò¶¢š™^™éíjØ¨œV‡(¬¶¬†'bž
¶¢š™^™éíjØ¨žÊ"šš+µ©í	©í†+z§vWŠ{ayú%–Œ"žÚ²¨¼šž)©•éžžÖ­Š‰õN¢š™^™éíjØ¨žGž¦ÆŸ•¨"žØ^rV¬²ØZ¶)©•éžžÛ-…è§µêßiÇ°…ëaz»az–«²)à…«yéÝ¢w¨®z-‰æè¢Wšž–«²)à‰Þ~V Ù8^"jezg§µ«b¢yz›-…ç§¶*Þ²Úâž(®·¬¦‰ÝŠx-¢Ø^…æz¸§¶¨n7œµ*-…êZ®Ç«…«-¢—ž’)í¢Ø^™ë,j¡y§^®Ú$žŒ0…«mÊ—…éž²Æ z+²Ê(«"¶¬¶¡y§^®ËkŠxÛazx+i»-…ë-®)àjwl¶ŠÞ²+ZÁ¬Ÿ¢¹ZÏ*Z®È§ƒtáz1ëa¡×!yÉ,‰ûayùZ‚¬mç§±ë\jYl¶©j»®Ú¢Ø^¥ªìz'í…çåjZ²z-mç§±ëZÛazzÞ¶êç±ªZ®Ç„ÅÇ©¶*'‰ûaz–«±çÚŠ[†+jvÞv‰Þ¶¶§²–«z{eÊÚ-…ç–W«N¬ŠÇ±iËeËZ´Œ(ºW^Æ—œµ©ZÏ*Z®È§‚)©•éžžÖ­Š‰í¡Ú-…çÚrÛajÙZÏ*Z®È§‚+!‰×^úèšØ^jše‰Æ­Š‰ÞÅÇ©¶ØZ¶Ø^jše‰Æ­Š‰æºË\j×!h–¢(©=ªìxL\z›b¢z'¶ zÙž¶²Ú–Z0~Ší…êh²È›ŠXÊØZµ©âš™^™éíjØ¨žë²V³Ê–«²)à²‹^râq©eÊØ^jše‰Æ­Š‰ðŠYdžŒ-…«Zž)©•éžžÖ­Š‰î±ë%k<©j»"žŸ¶¬{¦Ø¨ž+-†º0¼šëfzØhu»"ØbžKazÜ(q«±ªÞ…©Ý•çg‰Ç¥É¼…æv+b¢z¶žÅÇ©¶*'!ûayøž•Ø¬¢›b¢v¥jw]¡ë'¢×±ŠËbžØ^…æz¶j¶¦z×«6‹RzÑ1qêmŠ‰ðŠY[zØk£	ÛÊØ^Šjezg§µ«b¢p,º²Ø¨žÈh¢Ø­vŒ'‰øv‡¬ž‹cŠ÷µY_‰é]±ªÞ­êkzÇ§µç[Ê†ãyËlž‹lŠjezÜ©zÉb‘è§¶ë"{^êâžË^iÒ»+aŠÊZ®Ûaz{ax‰ez¥¸.™éí¦Ø¨ž+(ž\ž½êí†º0ž'Úž†ãyËij¶¦z×«ŠÉî–V§vØ^%¨§J*Oj»¦Ø¨ž+-†º0ú+jYh¶«¦º•é¬Â+a¶š®¦z{N*Øb²8¯zÆ§v+jÈ¥É×ŸŠwØ‡í…çâzWb²z-±ëcºËkzÛ«ž{¥•'žiº/yú+žéev+ºË"¢r¶Ÿ‰é]ŠÉšÖ­¢¼š×hzÉèµìb²Ö‰j)ÒŠ“Ú®Ç„ÅÇ©¶*'Â)emëa®Œ'…æz¸¬™©_¢¹žt‡ÚŸ(^i×«~'¥v+&jWè®gh–¢(©=ªìxL\z›b¢x¬¶èÂrh–¢(©=ªìxL\z›b¢x¬¶èÂ{aŠÈ§v'µë-…«m…æ©¦XœjØ¨žk¬¶ë¶¡y§^®ÈµV¥¹éž¶¶ˆµ«-®)àêkzÇ§µ«b¢z¶¡y§^®ö¥¹æ§uÚ0…«bµÆ§Â+a¶Z…è^i×«²U©nyhrŠËazËkŠx'¢ÚZ®Ú¶„ÅÇ©¶*'JêÞÁçžÆ²¶¶‰j)ÒŠ“Ú®Ç„ÅÇ©¶*'²g¬±¨šë-mëazËkŠx/j[ž¡ûazšuêÎ(iZw*.nì­…«hâ-jš^j»-…«p…«b±·¢žµé©µçaz·©•æ¬yÊ+ç-™èŸ!©°®‰àŠËhºÇžÅÇ©¶*'±«™ç!jx¬šÚj×!ºx§ŠØš–,Þuøž•Û,¢Ø^¥ªìz··¢žú$yØ§¶žÅÇ©¶*'…©Ý•êéz¸Z¦ÄáŠÉ^iÛ-¡©h¶‡è½êáy§bÉnžLœ¡×ˆ¶§’+b±©¢²Ö¤zÚ-†º0{¦Ø¨žÊ'z÷«Ê¶‹kÊÚ)®‹^rÛayªi–'¶*'~º&Šv½êíz{eÉ§zË"žâzWl¶…«Þž‹[yéâž+bjX³yÕ¡Êz-Žë-jË.™ëajÛayªi–'¶*'šë-më&j»^ž‹ †Ú)j»¶¡y§^®×±µ·Ÿ¢·šqÇ¬²)à~'¥vÆ§vz-¶¼¢šè¾'^iÊ&¦W±™ç!jx¬™«n‹ÞYæ«zë"žÚ­©žµêÍ¢Ôž´L\z›b¢wè®Ø^q«¡ö§¢›b¢v¥…æz¹èµìb²Ø§©Ýh–¢(©=ªìxL\z›b¢wè®Ø^q«¡ö¦jWè®g…æz¶ÞŠx+yÇ¢½ç_®‰…éÞ·
+‡ðy«,ºg…æ©¦XœjØ¨ž+,™ªízz.‚hv†¥–šuêïj[ž¥ªìŠx0z·¹Çš…æz»hŽë-mè§‚Ü(²Úâž-…ër¥æ§vö¥¹ì!‰ÈiºÛ-…æî×§¡úZ®È§‚‰Úªi–'¶*'¶¬ÂŠäq©ÛyÚ'y¼…ë§uêåÊ)àŠjezg§µ«b¢whzÉíŠÙš‘é¨­ëžÇŸ¢¶§jše‰Æ­Š‰í¡Æ­r§{¦Ø¨žØZž¯zÚ)j»jYay§^®ö¥¹ë-®)à±ë)yÈš–\¬Šw¶¬~éÜ¶*'jXÉ©ky§r{¬¶È§¶®×«—(§‚ËZrCh¶ŠÉè·Z´ˆZv)ízw^tö«±êßºw-Š‰Ú–+r{¬¶È§¶¬µ§$nëajËhmç–W{e‰È­—&ò¶¢š™^™éíjØ¨:(šç!†'bž
¶¢š™^™éíjØ¨úèšØ^jše‰Æ­Š‰ájÈ­²Œ'±ëh}Ø¬iÛÚžÖ zÂâ0j{^v–«±êß¹Ëb¢v¥ŠÜ­¡·¢žú$yØ¦¦XœŠÙro&§jše‰Æ­Š‰ß®‰…à"—«²—œ¶+ÞŠØ¬jx¦¦W¦z{Z¶*'uëZŠ[(¶š¦™bq«b¢{!¢é]ž‹[y¬ê†Œ(¯^žØ^ºw^®\¢ž
Z®Ç«ŠÈ§¾‰v+l†‹¥v;¬¶IèÂØZ¶+b²Ø^è§²‰ž~Šæjwm…«b~+m®'¬¶ˆ¶ŠìzÖ¯j[ž¶¶¢š™^™éíjØ¨Ú²{eŠG¢·¥–h–¢(©=ªìxL\z›b¢{a®Œ'm§$jØ­N¬ŠÈ¦¦Šíj{b°j{m¢f¢žÖ¢žØ^¶ÞyÊ+zö¥¹ë(|6š+µ¦â–+r¦Šíi¸¥ŠÜšÚh®Ö›Š[rN©¢)íiº.¶š+µ¦â–+rŠÆ ¢‡hãŸr‹«±ëaz)©¢»ZžÛaŠxn‹¦Šíi¸¥ŠÜ¢²Úy¦åzÚ&j)íj)í…ë™ë™©í‰Ë(}ì\z›b¢{³¥”Z+jwšêéj»®Ø^è¬žŠh²È›ŠXÊ‡í†º0Šx¥ªìyì\z›b¢z'j‰êZ®ÇžÅÇ©¶*'q©çz÷«¡Ç.®‰ÚëW]{(¶«{¥•·¬¢gœº¸¨ºÇ(uè§j]uâš™^™éíjØ¨ú+jwšêéj»®ØZ¶¬¶‹a®Œì\z›b¢w¯z|!zxv‡¬ž‹gyçm¢;¬¶Ú$yêm…ç(š˜¥z¸Z¦œ’yÊ'vØ^jše‰Æ­Š‰ájËhmì"–X§‚Új×!²ç!jw±qêmŠ‰í¡·šnW¡û§rØ¨º-‡…©ZÏ&§u©Þj«Šjezg§µ«b¢x§jÚÚžÊZéí}«!Š‰ÚØ­™¬¡ØŸ}êÞžÛaŠx,Â§¶¢š™^™éíjØ¨ž+%k<°†'!{h±ë-…ë§uêåÊ)àŠjezg§µ«b¢v§Ë²jÌ¨º¯zz-yÑ1¦XœŠ×(žÚè•¼…æ©¦XœjØ¨žf²‚+Þ¶š¦™bq«b¢wâêà­¨§y×(žÚè•©ÝzX¦ŠvzÊ&y¬$ÁªÝ{¦Ø¨ž§vX§‚ØZ¶+'¢Ùžjx§û¥~ŠÚæ zºZ®Ç«N¬Á¬²¢ç©l¢¯zh±yÙ¨uêZ®È§©e£§‚Ø^jše‰Æ­Š‰í¡×œ‰×°…«ay§^®È­Á©í²Ú!jwez)Ú•¬ò}«!Š‰ÚÜ!‰Èhë"·§¶Ëh…©Ý•è§jwšêßjÈb¢p'¢Ø^®Ë ë-Š‰æk&Þi¸§bq©p¢é]ŠÙš‘ëžÇ­¢¯yìmz{"¢x§µêßiÇ¬Â+azxZÇëW]x§µêßiÇ¬¶j·¨ž\¢š™^™éíyÖò•¬ò¥ªìz»Ùš‘éZÏ*Z®È§‚ŠmŠ‰Ú–Ê(ž\¡ŠeÊ—«~Šæjw±éìŠØ¯yªi³¥•«ÚŠ[azk–÷¬¡û.r§µêßiÇ¬Â«y«&¢ËZ¦™bq«b¢{0ŠYn±ëayæ zºZ®Ç«Š{^öœzÇè®]uÌk*+™¬§¢Ùš‘ëžÇˆ¶.‚HÂ‹¥vg§¶*'ŠÖ¬ŠÚrêÞvÚ&x	òÁ¬…êÞŠÉ¨ìÊËajz'zÚ,’)Úq«IºËdyê^½êò¶§«,Šjey«)¢Ë"nW›ºÙè²)©•êÈjk.ì¨¹ªÞy¨®Ú®)à¶¬¶‡%¢Ë«zÊÂ)ež‹[zV›¢»azš"žÖ›¢ë^j«¥ªìŠx/z».²V³Ê–«²)àj[a¢è!jÆŸŠv¥¦ˆ§´Œ(ºWcºËeŠG¢ËZµëajÚh®Ö›ŠXÉÆ§mèZÙ^w^¶«¢¹è¶Ø^¥ªìz+Æ™br+eÊŠâš™br+eÊV³ÈIèºlj'hžØb²š"žÔ^ªÝ±§£jx«ajsHI0½©ÜyÓ^·
+’)àMç!ž‰h‚'¬º.§]4êÞjàëŠ÷’¶Š|÷mj+az»º¸m<÷ÔÞ—}5÷¾wë®kô×ŸtÓÝö

---

From: Chris Harris <[email-masked]>
Date: Tue, 28 Nov 2000 10:31:54 +0000

Ranga,

I think I'll go for green this time...

Regards,
Chris

"M. Ranganathan" wrote:

> Chris,
>
> Thanks for the prompt response. Not to drag this on for ever, but I
> have a few more suggestions  in followup to your
> comments/clarifications  (in blue below). As  you are in Ireland, your
> missiles cannot reach me so I can be bold :)
>
>
>
> Regards
>
> Ranga.
>
>
> A design issue not discussed below:
>
> Whenever there is more than one header to be returned (via  headers
> for example), you return an array.  An array is easy to walk through.
> However,  I would think it more useful to return a collection of some
> sort that supports additional methods such as checking if an address
> exists in the list of headers returned etc. That might be of some use
> to an implementation.  If you define the returned type as an array of
> headers, there is no way to extend the class to support additional
> functionality.  May I suggest adding a collection class interface for
> collections of SIP Headers (and that can be specialized by
> implementations to support additional query methods etc.), say
> something like SIPHeaderList

I initially wanted to return a Vector, but was told that an array was
preferable for API's. Besides, any addition of functionality would be
purely for the implementor's benefit and would not be available (without
using reflection anway) to the application.

>> >> > While we are on the subject of Exceptions, why do null
>> >> > arguments throw runtime exceptions when you do a get on them?
>> >> > For example, in the Accept interface, getContentSubtype throws
>> >> > a IllegalArgumentException if  is null. IMHO, I think it is
>> >> > valid to have a null subtype so why not just return null rather
>> >> > than throw exception here?
>> >>
>> > "field".   Why do you need a  ParameterNotSet exception in this
>> > case?  Are you trying to handle the case of basic types like
>> > integers, floats and so on ? For objects, null is synonymous with
>> > not set isnt it?
>>
>> values is not a good idea for several reasons e.g. it is easier to
>> debug a ParameterNotSetException than searching for the source of a
>> later NullPointerException, and it forces the application to allow
>> for the fact that there is a reasonable chance that a particular
>> field does not exist. [Of course, if we did allow the use of null,
>> we could cut down on the number of methods and drop the
>> ParameterNotSetException - but  is it really worth sacrificing
>> clarity and robustness for the sake of cutting down on API size?]
>
>
> Well, I guess that is a judgement call.  With this design, you may
> have code that is cluttered with a lot of exception handlers and the
> API is quite big.  Checking for null is fairly standard  (am I giving
> my age away ? :)  and I can see at least a few places in the base JAVA
> API where null is returned to denote empty  and anyway, the app has a
> good old stack trace to rely on to see the source of the exception
> when null pointers are encountered.   Guarding an application from
> null pointer exception is pretty hard anyway so why complicate the API
> to handle this one case?  ( For collections of SIPHeaders, you can
> check for empty collection and you will not have this problem. )
>

I guess it is a judgement call. I actually approached this topic at the
meeting from your perspective (devil's advocate? :) ) There were a few
who agreed (who admitted that their opinion was due to their C
background!), but the majority preferred the explicit handling of the
ParameterNotSetException and the use of has and remove methods to be on
the safe side. I hear what you are saying about null being sprinkled
about in the core Java APIs - but even Sun can make mistakes :)

>> >>  approach is to allow the passing and returning of null objects
>> >>  from get and set methods (implicit "remove" and "has"), and the
>> >>  other is to explicitly add has and remove methods (and exceptions
>> >>  on the set and get methods). As for mandatory header parts - I
>> >>  think passing null to a set method should definitely throw an
>> > 1.  Why do you restrict throwing IllegalArgumentException to only
>> > null arguments in some of the headers? Why are you not checking for
>> > proper formatting of the passed arguments (by giving it to the
>> > parser for example and running the appropriate  parser rule).
>>
>> In general, an IllegalArgumentException is thrown if an argument to
>> a set method fails basic validation (i.e. no implementation-specific
>> exception is not thrown by following the rules defined in the API .
>> So if an argument is a String, I throw an IllegalArgumentException
>> if the argument is null or zero-length.
>>
>> implementations will be more tolerant than others. This is why there
>> is a checked JainSipParseException - an application cannot tell in
>> advance if a particular implementation will accept a certain value,
>> so it must catch this exception.
>>
>> I am proposing that this exception should also be thrown by get
>> methods (for all fields), because if an implementation uses lazy
>> parsing, then there is no guarantee that the header value will parse
>> correctly upon the invocation of the get method, and again this is
>> > the interfaces?  The class that implements the interface can have
>> > set methods but the interface itself does not need to have them.
>>
>> I have set methods in the interfaces because the objects will not
>> only be coming up from the implementation - an application needs to
>> be able to create and send requests, and this means being able to
>> set the values.
>
> Ah! My understanding was correct then.
>
> OK. Perhaps this would be too much of a change for you to consider but
> let me make a suggestion anyway ....
>
> I think formatting headers should be considered under a different set
> of API.  Here is what I am suggesting
>
> 1. Get rid of the setXXX interfaces (the parser will have direct
> access to the classes and does not need them and it will cut down the
> size of the API).
>
> 2. Have a  SIPMessageFormatter interface who'se sole job it is to
> format output messages.  This can have methods to format the different
> outgoing messages and will throw parse exceptions if the strings that
> it gets are incorrect. The MessageFormatter interface takes as
> parameter values only Strings.
>
> Concretely,  for example:
>
> public interface SIPMessageFormatter {
>         public String createFromMessage( String from ,  String tag)
> throws SIPParseException;
>
>     .....................
>
> }
>
> It would be slower for an implementation to extract the same
> information out of a structure and hand it to a parser for validation
> (IMHO). A "loose implementation" may not want to be bothered with
> validation at all and leave it to the reciever to reject the mesage,
> thereby making the implementation faster or it may do very cursory
> checking.
>

This is a major change at this stage (public review technically closes
today)  - I personally don't think it's very OO, but I would be
interested to hear other people's opinons.

>
>
>
>
>
>>
>>
>> >  Moreover, the parser has the job of setting up stuff in the
>> > returned object. It has a set of BNF rules to decide on the
>> > correctness of the arguments and it does not need for the class to
>> > re-implement the check. For example, I think it ought to be the
>> > parser's job to check if the q value is between 0 and 1.   (Is the
>> > purpose of the set method to allow for the application to do header
>> > formatting?)
>>
>> I absolutely agree that the parser should perform validation (hence
>> the JainSipParseException) - but as I mentioned above there are
>> certain basic criteria that must be met by all implementations and
>> applications - I am using the IllegalArgumentException to cover
>> these. Perhaps certain cases go too far in this validation - perhaps
>> the IllegalArgumentException could be thrown only if a null argument
>> is passed and all other validation is left up to the
>> implementation's parser? (although a problem with certain cases such
>> as PriorityHeader comes to mind, where the header values are defined
>> as constants in the API and an IllegalArgumentException is thrown if
>> any other value is passed - should we allow any non-null String
>> values for the priority? Or to take your example of q-value above -
>> should we just allow any non-null Float and let the parser enforce
>> the 0-1 range?
>
>
> I think I understand the point about checking for null.  I think, if
> you are dead set on adopting the set method as a way of constructing
> headers, one should validate arguments via the parser and throw
> ParseException for anything other than null arguments. On the other
> hand, I propose something entirely different for constructing headers
> (above).
>
>>
>>
>>
>> >
>> >
>> >
>> >>
>> >>
>> >> > I don't quite follow the argument that lazy parsing
>> >> > "necessitates throwing a parse exception for all get
>> >> > methods".   Here is what I had envisioned:
>> >> >
>> >> >
>> >> > 1 When a message comes in it will be separated into headers
>> >> > based on type.
>> >> > 2 The header would be returned with no field initialized except
>> >> > the text corresponding to the message. (this would necessitate
>> >> > header type but the rest remains unparsed.) You can also stow
>> >> > away the type information in the Header that is returned as
>> >> > well to know which parser rule to invoke later.
>> >> > 3. Later, when the application wants to parse the header, it
>> >> > has the string corresponding to the message and can hand it off
>> >> > to the parser, which can then fill in the appropriate fields
>> >> > corresponding to the header.
>> >> > 4. Subsequently, the application can access the fields just as
>> >> > an eager parser based application would do.
>> >> >
>> >>  An application has no idea whether an implementation is using
>> >>  lazy or eager parsing - it is simply passed a header object - and
>> >>  then if it is interested in a particular field it calls the
>> >>  appropriate get method (which would internally invoke the parser
>> >>  in a lazy parsing implementation). So the application is
>> >>  completely oblivious to whether or not this "optimisation" is
>> >>  used by the implementation.
>> >
>> >
>> > Ah! ( Why is this hiding  of the implementation so important? )
>> > Can this be handled in the following fashion by an implementation:
>> >
>> > 1. The implementation keeps a flag in the  class that implements
>> > the interface whether the parsing has been done or not (i.e.
>> > boolean parsingDone flag).
>> >
>> > header to know what type the message is as soon as it has the
>> > header string and then grabs the string and stores it away for lazy
>> > parsing.
>> >
>> >
>> > 3. The get Method  checks if the flag has been set, calls the
>> > parser to do the parse if the flag has not been set and then
>> > returns a parseException if the parse fails. This can be done
>> > transparently to the caller.
>>
>> This is exactly what I would expect a lazy-parsing implementation to
>> do - the fact that lazy-parsing is hidden from the application
>> (except that the application must catch a JainSipParseException on
>> the get methods to allow for the possibility that an implementation
>> uses lazy-parsing - so technically the application will know that an
>> implementation uses lazy-parsing if this exception is thrown by a
>> get method - but I think the two cases are handled nicely by the
>> addition of the exception)
>
>> >
>> >
>> >
>> >
>> >
>> >
>> >>
>> >>
>> > 1. All fields are represented by objects (not simple types like
>> > int, use Integer instead).
>>
>> I buy this part - then the IllegalArgumentException is only ever
>> thrown if an object parameter is null, and the JainSipParseException
>> is thrown for all other problems with the argument.
>
>
> OK this jives and is easily defined.
>
>>
>>
>> >
>> >>  JainSipParseException will be thrown (header is malformed). If
>> >>  any header field is malformed a JainSipParseException is thrown.
>> >>  If a JainSipParseException is thrown, this indicates that the
>> >>  application must use the header's getValue method to get a string
>> >>  representation of the header value and do what it can with that.
>> >
>> >
>> Sure - we can say that the JainSipParseException's message must be
>> the string value of the header.
>
>
> OK Glad you buy that one.

I was just wondering what the message of a JainSipParseException thrown
from a set method should contain - the value passed in? Perhaps we
should add a string field to the JainSipParseException (say unparsable)
which can be whatever the parser was unable to parse? Then the message
can be left for explanatory comments.

>
>
>
>>
>
>>
>>
>> >
>> >
>> >
>> >>
>> >>
>> >> >
>> >> >
>> >> > It appears that what is being attempted here (please correct me
>> >> > if I am wrong) is to use exceptions as a mechanism to catch
>> >> > un-initialized fields so the parser can be invoked in the
>> >> > exception handler perhaps. This leads to a lot of overhead in
>> >> > clunky code. I think it is a mistake to throw exceptions on
>> >> > every get to try to protect the application from inadvertently
>> >> > accessing fields that have not been initialized.  Why not just
>> >> > assume that the application must be smart enough to parse the
>> >> > header text before accessing fields and not try to provide a
>> >> > complex mechanism as above?
>> >>
>> >>
>> >>  header not existing, and a JainSipParseException for the case of
>> >>  a malformed header being received from the network.
>> >>
>> >>  If we assume the application is smart enough to do all header
>> >>  value parsing, we reduce a header to just being two strings - the
>> >>  type and value, which puts the burden of parsing on an
>> >>  application - this work can be done by the underlying
>> >>  implementation - doesn't it make more sense for an application to
>> >>  catch an exception than have to parse all header value strings
>> >>  (especially since this functionality already exists in the
>> >>  underlying stack)
>> >
>> >
>> > No that is not what I had intended. Parser functionality exists in
>> > the stack but has to be called explicitly by the implementation.
>> > Too much hiding of the implementation from the application has its
>> > own set of disadvantages (IMHO).
>>
>> I wanted parser fuctionality to be invoked implicitly by an
>> application - from the API perspective it is an implementation
>> detail - so the application should not be aware of how or when the
>> underlying parser is invoked - it should just know that it is there
>> in some form, and that if it tries to get or set a value that the
>> implementation doesn't like it will get a JainSipParseException
>> thrown back at it. This is important if we want to maintain the
>> three core values of JAIN - portability, portability and portabilty
>> ;)
>
>
> The point about portability is a good one. Of course the important
> thing about portability is to be able to maintain the same semantics
> of exceptions as well.  For an eager parser,  there is no possibility
> of throwing a parse  exception  on a get (i.e. parse exception can
> never occur on a getXXX) so there will be some curious code in a
> getXXX  implementation  for an eager parser that has to throw an
> exception even when it does not need to (just to keep the compiler
> happy).   Second,  the application has to be willing to catch such an
> exception to be able to function both with a lazy and an eager
> implementation in a transparent fashion and it may do different things
> when the implementation is lazy, which exposes the underlying
> implementation anyway as you have noted.
>
> Explicit control by the application may give the application finer
> grained control and eliminate some awkward exception handling that is
> not meaningful for an eager parser .  This way, you can also have
> mixed mode parsing, allowing the application to decide what headers it
> wants to handle in a lazy fashion and which ones it wants to handle in
> an eager fashion.

The application does not get to decide which method is used by an
implementation - an implementation could be lazy, eager or, as you point
out, a mixture of both. An application has to accomodate this fact to be
portable.

>
>
> Another suggestion ( may be a bit radical) - would it make sense to
> have extension interfaces (with enhanced getXXX  interfaces)  that are
> only implemented by lazy parsers and make lazy parsing optional (so
> only highly performance sensitive apps will  avail themselves of such
> interfaces whereas most applications will use the eager parser
> interfaces for getXXX).  ( May or may not make sense, I thought I
> would mention it as it occured to me.  )

Again, the application does not choose - the implementator does.

>
>
> Anyway,  there is more ways than one to skin a cat. Just keep
> everything as simple as possible but no simpler. I am sure you are
> eager to bring this to closure so I will not belabor the point about
> eager parsing versus lazy parsing  although, as a final point I would
> just like to state that portability can be handled whether or not the
> parse is explicitly or implicitly lazy. Enough said on this point.

Thanks for all your input Ranga!