/[resiprocate]/main/sip/resiprocate/README
ViewVC logotype

Contents of /main/sip/resiprocate/README

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1284 - (show annotations) (download)
Sat Mar 22 19:33:59 2003 UTC (16 years, 10 months ago) by jason
File size: 7944 byte(s)
*** empty log message ***

1 September 23, 2002
2 head/vocal/sip2/sipstack/README
3
4 SipMessage design goals:
5 - efficient parsing
6 - reasonable interface for the application writer
7 - reasonably easy path to adding new headers, methods, parameter names
8
9 SipMessage design.
10
11 There are two APIs to SipMessage; one from the transport layer 'up' and one from
12 the application layer 'down'. The transport layers pulls the raw message text
13 off the wire, parses the text just enough to segment it onto headers and sets
14 the text of the headers into the SipMessage generically. This minimal header
15 parse phase is called "pre-parsing".
16
17 The pre-parse phase needs to identify the header for generic storage into the
18 SipMessage. In addition, the pre-parse phase needs to know if unescaped commas
19 are delimiters in the header text to be parsed. However, the pre-parse phase
20 does not require static typing of the header or whether the header can appear
21 multiple times in the message.
22
23 The pre-parse phase allows unknown headers.
24
25 The application requests a specific header by static type. If the header does
26 not exists, an empty header of the appropriate type is created. If the header
27 has not already been parsed, a parser is created and associated with the
28 header. The parser is not invoked until the application requests a sub-part of
29 the header. This permits headers to be moved from one message to another without
30 parsing within the header.
31
32 The parser is statically typed to provide a specific interface to the
33 application. The specifics of how to parse a message of a given type is
34 implemented by the parser type. The static header types are available to the
35 application through global variables named after the headers; e.g. CallId, CSeq,
36 From, Via.
37
38 The interface from each parser is a set of accessors. Each accessor may return a
39 reference, allowing the application to set the corresponding value directly, or
40 it may return a const reference, indicating a read only value. Most parsers also
41 present an interface to a generic parameter accessor. This generic parameter
42 accessors allows the application to get or set proprietary parameters.
43
44 The application retrieves unknown headers by the string name of the unknown
45 header.
46
47 Interface Examples:
48
49 SipMessage *msg;
50 msg->get(From).getAddressOfRecord();
51 Data& aor = msg->get(From)->host();
52 msg->get(From).host() = "vovida.org";
53 msg->exists(Warning);
54 msg->exists("Proprietary-Header"); // true if present
55 msg->get("Proprietary-Header"); // returns ParserContainer<String>&
56
57 for (Vias::iterator i = msg->get(Vias).begin();
58 i != msg->get(Vias).end(); i++)
59 {
60 Data& host = i->host();
61 int& port = i->port();
62 }
63
64 Implementation:
65
66 There is a fixed set of headers. Each header is assigned an enum value. There is
67 a type associated with each enum value and a distinctly named global variable of
68 header type. The enum value is used to store and retrieve the headers at
69 runtime. The header type is used to retrieve the parsed and statically typed
70 headers at compile time.
71
72 A SipMessage contains an array of pointers to HeaderFieldValueList. This array
73 is indexed by the header enums.
74
75 The pre-parse phase consists of:
76 0. determine the boundaries of the header string
77 1. determine the boundaries of the header name string
78 2. look up the enum value for the header name
79 3. look up the comma tokenizing property of the header enum
80 4. determine the boundaries of each header in the header string
81 5. for each header in the header string, add the header string boundaries by
82 enum to the message -- the message stores the header string boundaries in the
83 as indexed by the header enum
84
85 While processing headers the pre-parse will allocate chunks of memory to hold the
86 header strings. Each of these buffers is passed opaquely to the message for
87 deletion when the message is deleted.
88
89 After pre-parsing the message header array contains one HeaderFieldValueList for
90 each header encountered in the pre-parse. Each HeaderFieldValueList contains
91 a list of HeaderFieldValue.
92
93 The application requests the contents of a header through a type safe interface;
94 the returned object is either a particular parser type or a particular parser
95 container. A parser container is returned if and only if the header is specified
96 to permit multiple values.
97
98 If the header specifies multiple values, the returned value is iterable. Each
99 iteration provides access to a header value. In addition, there is an interface
100 on the returned value to determine the number of header values.
101
102 The returned value in the single header value case, and within the iteration
103 over the multi header value case provides access to the components of the header
104 value specfic to the type of header. For example, CSeq provides getMethod() and
105 sequence. For sequence, the sequence value is an integer returned by reference
106 and may be directly modified.
107
108 Adding a new header:
109
110 Assume the new header name New-Header
111
112 Symbols.hxx
113 1. Add New_Header to the static symbol declarations.
114 Symbols.chxx
115 1. Add New_Header = "New-Header" to the static symbol definitions.
116
117 HeaderTypes.hxx
118 1. Add New_Header to the Headers::Type enum. Add this entry anywhere before UNKNOWN.
119 Headers are output in the same order they appear in the Headers::Type enum.
120 2. Determine if the header allows multiple values. Use the MultiHeader template
121 if the new header allows multiple values, use the Header template if the new
122 header does not allow multiple values.
123 3. Determine the parser type for the header. This may be StringComponent for
124 unstructured headers, may be another existing parser type (see
125 ParserCategories.hxx), or may require a new parser type.
126 4. Add the declaration of the header type and the header type global variable to
127 HeaderTypes.hxx
128 e.g.:
129 class Header<Headers::New_Header>
130 {
131 public:
132 typedef StringComponent Type;
133 Header()
134 {
135 Headers::CommaTokenizing[Headers::New_Header] = Type::isCommaTokenizing;
136 HeaderStrings[Headers::New_Header] = Symbols::New_Header;
137 }
138 };
139 extern Header<Headers::Content_Disposition> Content_Disposition;
140 5. Add the mapping from the four character hash to the header enum. This is
141 error prone. The hash value is platform dependent.
142
143 HeaderTypesSetup.cxx
144 1. Add a line to the hash id generator.
145
146 HeaderTypes.cxx
147 1. Add the definition of the new header type global variable. Be sure to use the
148 same template type as in the declaration.
149 e.g.
150 Header<Headers::New_Header> Vocal2:: New_Header>;
151
152 ParserCategories.hxx
153 (if the new header requires a new parser)
154
155 1. Declare the new parser category as publicly inheriting from
156 ParserCategory.
157 2. Determine if commas can be used to include multiple header values in a single
158 line.
159 3. Declare virtual ParserCategory* clone(HeaderFieldValue*) const;
160 4. Declare virtual void parse();
161 5. Declare private members as required to store the parsed header value.
162 6. Declare public methods as required to access the parsed header value.
163 7. Typedef the container for the parser. Not required if the header value is
164 never used in a header that allows multiple values.
165
166 e.g.
167 typedef ParserContainer<NewComponent> NewComponents;
168
169 ParserCategories.cxx
170 (if the new header requires a new parser)
171 1. Define clone(), parse()
172 2. Define accessors. Each accessor must call checkParsed() before processing any
173 data.
174
175
176 (*
177 It would be nice if getHeaderType(const char *headerName, int len)
178 was defined my configure/make. The supported.hxx would be replaced
179 with a configuration file headers.hdr that specified the SIP header name, the
180 C++ parser category, and whether the header allows multiple values.
181
182 This file could be compiled into the various declarations and definitions.
183 It is even possible to allow the user to specify additional headers in the
184 code; have the automatically generated types go into the enum
185 HeaderTypesBase, and have HeaderTypes inherit; HeaderTypes::Types could
186 continue where the inherited enum leaves off.
187 *)
188
189
190

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27