/src/resiprocate/resip/stack/SipFrag.cxx
Line | Count | Source (jump to first uncovered line) |
1 | | #if defined(HAVE_CONFIG_H) |
2 | | #include "config.h" |
3 | | #endif |
4 | | |
5 | | #include "resip/stack/MsgHeaderScanner.hxx" |
6 | | #include "resip/stack/SipFrag.hxx" |
7 | | #include "resip/stack/SipMessage.hxx" |
8 | | #include "rutil/Logger.hxx" |
9 | | #include "rutil/ParseBuffer.hxx" |
10 | | #include "rutil/WinLeakCheck.hxx" |
11 | | |
12 | | using namespace resip; |
13 | | using namespace std; |
14 | | |
15 | 0 | #define RESIPROCATE_SUBSYSTEM Subsystem::SIP |
16 | | |
17 | | bool |
18 | | SipFrag::init() |
19 | 4 | { |
20 | 4 | static ContentsFactory<SipFrag> factory; |
21 | 4 | (void)factory; |
22 | 4 | return true; |
23 | 4 | } |
24 | | |
25 | | SipFrag::SipFrag(const Mime& contentsType) |
26 | | : Contents(contentsType), |
27 | | mMessage(new SipMessage()) |
28 | 0 | {} |
29 | | |
30 | | SipFrag::SipFrag(const HeaderFieldValue& hfv, const Mime& contentsType) |
31 | | : Contents(hfv, HeaderFieldValue::CopyPadding, contentsType), |
32 | | mMessage(0) |
33 | 0 | { |
34 | 0 | } |
35 | | |
36 | | SipFrag::SipFrag(const SipFrag& rhs) |
37 | | : Contents(rhs,HeaderFieldValue::CopyPadding), |
38 | | mMessage(rhs.mMessage ? new SipMessage(*rhs.mMessage) : 0) |
39 | 0 | { |
40 | 0 | } |
41 | | |
42 | | SipFrag::~SipFrag() |
43 | 0 | { |
44 | 0 | delete mMessage; |
45 | 0 | } |
46 | | |
47 | | SipFrag& |
48 | | SipFrag::operator=(const SipFrag& rhs) |
49 | 0 | { |
50 | 0 | if (this != &rhs) |
51 | 0 | { |
52 | 0 | Contents::operator=(rhs); |
53 | 0 | delete mMessage; |
54 | 0 | if (rhs.mMessage) |
55 | 0 | { |
56 | 0 | mMessage = new SipMessage(*rhs.mMessage); |
57 | 0 | } |
58 | 0 | else |
59 | 0 | { |
60 | 0 | mMessage = 0; |
61 | 0 | } |
62 | 0 | } |
63 | | |
64 | 0 | return *this; |
65 | 0 | } |
66 | | |
67 | | Contents* |
68 | | SipFrag::clone() const |
69 | 0 | { |
70 | 0 | return new SipFrag(*this); |
71 | 0 | } |
72 | | |
73 | | const Mime& |
74 | | SipFrag::getStaticType() |
75 | 2 | { |
76 | 2 | static Mime type("message", "sipfrag"); |
77 | | //static Mime type("application", "sipfrag"); |
78 | 2 | return type; |
79 | 2 | } |
80 | | |
81 | | SipMessage& |
82 | | SipFrag::message() |
83 | 0 | { |
84 | 0 | checkParsed(); |
85 | 0 | return *mMessage; |
86 | 0 | } |
87 | | |
88 | | const SipMessage& |
89 | | SipFrag::message() const |
90 | 0 | { |
91 | 0 | checkParsed(); |
92 | 0 | return *mMessage; |
93 | 0 | } |
94 | | |
95 | | EncodeStream& |
96 | | SipFrag::encodeParsed(EncodeStream& str) const |
97 | 0 | { |
98 | 0 | mMessage->encodeSipFrag(str); |
99 | |
|
100 | 0 | return str; |
101 | 0 | } |
102 | | |
103 | | bool |
104 | | SipFrag::hasStartLine(char* buffer, int size) |
105 | 0 | { |
106 | | #if 0 |
107 | | //!dcm! -- this probably inefficient, but the SIP grammer makes this very |
108 | | //difficult. Better here than in the MsgHeaderScanner. There's also proabably a |
109 | | //way to make a header that matches the requestLine check which isn't a |
110 | | //request line. |
111 | | |
112 | | ParseBuffer pbCheck(buffer, size); |
113 | | pbCheck.skipWhitespace(); //gratuitous? |
114 | | |
115 | | //!dcm! -- could extend to SIP/2.0, but nobody should start a hname with SIP/ |
116 | | if ((pbCheck.end() - pbCheck.position()) > 4 && |
117 | | strncmp(pbCheck.position(), "SIP/", 4) == 0) |
118 | | { |
119 | | return true; |
120 | | } |
121 | | else |
122 | | { |
123 | | pbCheck.skipToChars(Symbols::CRLF); |
124 | | if (pbCheck.eof()) |
125 | | { |
126 | | //false positive, let MsgHeaderScanner sort the exact error out |
127 | | return true; |
128 | | } |
129 | | |
130 | | pbCheck.skipBackToChar(Symbols::SPACE[0]); |
131 | | if (pbCheck.position() == pbCheck.start()) |
132 | | { |
133 | | return false; |
134 | | } |
135 | | |
136 | | if ((pbCheck.end() - pbCheck.position()) > 4 && |
137 | | strncmp(pbCheck.position(), "SIP/", 4) == 0) |
138 | | { |
139 | | return true; |
140 | | } |
141 | | else |
142 | | { |
143 | | return false; |
144 | | } |
145 | | } |
146 | | #else |
147 | | //!dcm! -- better approach, remove above if this is proven to be correct |
148 | 0 | ParseBuffer pbCheck(buffer, size); |
149 | 0 | pbCheck.skipWhitespace(); //gratuitous? |
150 | 0 | pbCheck.skipToOneOf(" \t:\r\n"); |
151 | 0 | while(!pbCheck.eof()) |
152 | 0 | { |
153 | 0 | switch(*pbCheck.position()) |
154 | 0 | { |
155 | 0 | case ':': |
156 | 0 | return false; |
157 | 0 | case ' ': |
158 | 0 | case '\t': |
159 | 0 | pbCheck.skipChar(); |
160 | 0 | break; |
161 | 0 | case '\r': |
162 | 0 | case '\n': |
163 | 0 | return false; |
164 | 0 | default: |
165 | 0 | return true; |
166 | 0 | } |
167 | 0 | } |
168 | 0 | return true; //false positive, let MsgHeaderScanner sort the exact error out |
169 | 0 | #endif |
170 | 0 | } |
171 | | |
172 | | void |
173 | | SipFrag::parse(ParseBuffer& pb) |
174 | 0 | { |
175 | | // DebugLog(<< "SipFrag::parse: " << pb.position()); |
176 | |
|
177 | 0 | mMessage = new SipMessage(); |
178 | |
|
179 | 0 | pb.assertNotEof(); |
180 | 0 | const char *constBuffer = pb.position(); |
181 | 0 | char *buffer = const_cast<char *>(constBuffer); |
182 | |
|
183 | 0 | size_t size = pb.end() - pb.position(); |
184 | | |
185 | | // !ah! removed size check .. process() cannot process more |
186 | | // than size bytes of the message. |
187 | | |
188 | |
|
189 | 0 | MsgHeaderScanner msgHeaderScanner; |
190 | 0 | msgHeaderScanner.prepareForFrag(mMessage, hasStartLine(buffer, (int)size)); |
191 | 0 | enum { sentinelLength = 4 }; // Two carriage return / line feed pairs. |
192 | | //char saveTermCharArray[sentinelLength]; |
193 | 0 | static const char* sentinel="\r\n\r\n"; |
194 | 0 | char *termCharArray = buffer + size; |
195 | 0 | memcpy(scratchpad,termCharArray,4); |
196 | | |
197 | | /*saveTermCharArray[0] = termCharArray[0]; |
198 | | saveTermCharArray[1] = termCharArray[1]; |
199 | | saveTermCharArray[2] = termCharArray[2]; |
200 | | saveTermCharArray[3] = termCharArray[3];*/ |
201 | | |
202 | 0 | memcpy(termCharArray,sentinel,4); |
203 | | /*termCharArray[0] = '\r'; |
204 | | termCharArray[1] = '\n'; |
205 | | termCharArray[2] = '\r'; |
206 | | termCharArray[3] = '\n';*/ |
207 | 0 | char *scanTermCharPtr; |
208 | 0 | MsgHeaderScanner::ScanChunkResult scanChunkResult = |
209 | 0 | msgHeaderScanner.scanChunk(buffer, |
210 | 0 | (unsigned int)(size + sentinelLength), |
211 | 0 | &scanTermCharPtr); |
212 | | |
213 | 0 | memcpy(termCharArray,scratchpad,4); |
214 | | /*termCharArray[0] = saveTermCharArray[0]; |
215 | | termCharArray[1] = saveTermCharArray[1]; |
216 | | termCharArray[2] = saveTermCharArray[2]; |
217 | | termCharArray[3] = saveTermCharArray[3];*/ |
218 | | |
219 | | // !dlb! not at all clear what to do here |
220 | | // see: "// tests end of message problem (MsgHeaderScanner?)" |
221 | | // in test/testSipFrag.cxx |
222 | 0 | if (false && scanChunkResult != MsgHeaderScanner::scrEnd) |
223 | 0 | { |
224 | 0 | CerrLog(<< "not MsgHeaderScanner::scrEnd"); |
225 | 0 | pb.fail(__FILE__, __LINE__); |
226 | 0 | } |
227 | 0 | else |
228 | 0 | { |
229 | 0 | size_t used = scanTermCharPtr - buffer; |
230 | | |
231 | | // !ah! I think this is broken .. if we are UDP then the |
232 | | // remainder is the SigFrag, not the Content-Length... ?? |
233 | 0 | if (mMessage->exists(h_ContentLength)) |
234 | 0 | { |
235 | 0 | mMessage->setBody(scanTermCharPtr, |
236 | 0 | static_cast<int>(size - used)); |
237 | 0 | } |
238 | 0 | else |
239 | 0 | { |
240 | | // !ah! So the headers weren't complete. Why are we here? |
241 | | // !dlb! |
242 | 0 | if (mMessage->exists(h_ContentLength)) |
243 | 0 | { |
244 | 0 | pb.reset(buffer + used); |
245 | 0 | pb.skipChars(Symbols::CRLF); |
246 | 0 | mMessage->setBody(pb.position(),int(pb.end()-pb.position()) ); |
247 | 0 | } |
248 | 0 | } |
249 | 0 | pb.reset(pb.end()); |
250 | 0 | } |
251 | 0 | } |
252 | | |
253 | | /* ==================================================================== |
254 | | * The Vovida Software License, Version 1.0 |
255 | | * |
256 | | * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. |
257 | | * |
258 | | * Redistribution and use in source and binary forms, with or without |
259 | | * modification, are permitted provided that the following conditions |
260 | | * are met: |
261 | | * |
262 | | * 1. Redistributions of source code must retain the above copyright |
263 | | * notice, this list of conditions and the following disclaimer. |
264 | | * |
265 | | * 2. Redistributions in binary form must reproduce the above copyright |
266 | | * notice, this list of conditions and the following disclaimer in |
267 | | * the documentation and/or other materials provided with the |
268 | | * distribution. |
269 | | * |
270 | | * 3. The names "VOCAL", "Vovida Open Communication Application Library", |
271 | | * and "Vovida Open Communication Application Library (VOCAL)" must |
272 | | * not be used to endorse or promote products derived from this |
273 | | * software without prior written permission. For written |
274 | | * permission, please contact vocal@vovida.org. |
275 | | * |
276 | | * 4. Products derived from this software may not be called "VOCAL", nor |
277 | | * may "VOCAL" appear in their name, without prior written |
278 | | * permission of Vovida Networks, Inc. |
279 | | * |
280 | | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED |
281 | | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
282 | | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND |
283 | | * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA |
284 | | * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES |
285 | | * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, |
286 | | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
287 | | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
288 | | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
289 | | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
290 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
291 | | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
292 | | * DAMAGE. |
293 | | * |
294 | | * ==================================================================== |
295 | | * |
296 | | * This software consists of voluntary contributions made by Vovida |
297 | | * Networks, Inc. and many individuals on behalf of Vovida Networks, |
298 | | * Inc. For more information on Vovida Networks, Inc., please see |
299 | | * <http://www.vovida.org/>. |
300 | | * |
301 | | */ |