/[resiprocate]/branches/b-identity-0505/ConnectionBase.cxx
ViewVC logotype

Contents of /branches/b-identity-0505/ConnectionBase.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4598 - (show annotations) (download)
Wed May 11 22:53:07 2005 UTC (14 years, 6 months ago) by derek
File size: 10899 byte(s)
set svn:eol-style to LF
1 #if defined(HAVE_CONFIG_H)
2 #include "resiprocate/config.hxx"
3 #endif
4
5 #include "resiprocate/os/Logger.hxx"
6 #include "resiprocate/ConnectionBase.hxx"
7 #include "resiprocate/SipMessage.hxx"
8 #include "resiprocate/Security.hxx"
9 #include "resiprocate/os/WinLeakCheck.hxx"
10
11 using namespace resip;
12
13 #define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT
14
15 char
16 ConnectionBase::connectionStates[ConnectionBase::MAX][32] = { "NewMessage", "ReadingHeaders", "PartialBody" };
17
18
19 ConnectionBase::ConnectionBase()
20 : mSendPos(0),
21 mWho(),
22 mMessage(0),
23 mBuffer(0),
24 mBufferPos(0),
25 mBufferSize(0),
26 mLastUsed(0),
27 mState(NewMessage)
28 {
29 DebugLog (<< "ConnectionBase::ConnectionBase, no params: " << this);
30 }
31
32 ConnectionBase::ConnectionBase(const Tuple& who)
33 : mSendPos(0),
34 mWho(who),
35 mMessage(0),
36 mBuffer(0),
37 mBufferPos(0),
38 mBufferSize(0),
39 mLastUsed(Timer::getTimeMs()),
40 mState(NewMessage)
41 {
42 DebugLog (<< "ConnectionBase::ConnectionBase, who: " << mWho << " " << this);
43 }
44
45 ConnectionBase::~ConnectionBase()
46 {
47 while (!mOutstandingSends.empty())
48 {
49 SendData* sendData = mOutstandingSends.front();
50 mWho.transport->fail(sendData->transactionId);
51 delete sendData;
52 mOutstandingSends.pop_front();
53 }
54 // delete mBuffer;
55 // delete mMessage;
56 }
57
58 ConnectionId
59 ConnectionBase::getId() const
60 {
61 return mWho.connectionId;
62 }
63
64 void
65 ConnectionBase::preparseNewBytes(int bytesRead, Fifo<TransactionMessage>& fifo)
66 {
67 assert(mWho.transport);
68
69 DebugLog(<< "In State: " << connectionStates[mState]);
70 //getConnectionManager().touch(this); -- !dcm!
71
72 start: // If there is an overhang come back here, effectively recursing
73
74 switch(mState)
75 {
76 case NewMessage:
77 {
78 if (strncmp(mBuffer + mBufferPos, Symbols::CRLFCRLF, 4) == 0)
79 {
80 StackLog(<<"Throwing away incoming firewall keep-alive");
81 mBufferPos += 4;
82 bytesRead -= 4;
83 if (bytesRead)
84 {
85 goto start;
86 }
87 else
88 {
89 return;
90 }
91 }
92 assert(mWho.transport);
93 mMessage = new SipMessage(mWho.transport);
94
95 DebugLog(<< "ConnectionBase::process setting source " << mWho);
96 mMessage->setSource(mWho);
97 mMessage->setTlsDomain(mWho.transport->tlsDomain());
98 mMsgHeaderScanner.prepareForMessage(mMessage);
99 // Fall through to the next case.
100 }
101 case ReadingHeaders:
102 {
103 unsigned int chunkLength = mBufferPos + bytesRead;
104 char *unprocessedCharPtr;
105 MsgHeaderScanner::ScanChunkResult scanChunkResult =
106 mMsgHeaderScanner.scanChunk(mBuffer,
107 chunkLength,
108 &unprocessedCharPtr);
109 if (scanChunkResult == MsgHeaderScanner::scrError)
110 {
111 //.jacob. Not a terribly informative warning.
112 WarningLog(<< "Discarding preparse!");
113 delete mBuffer;
114 mBuffer = 0;
115 delete mMessage;
116 mMessage = 0;
117 //.jacob. Shouldn't the state also be set here?
118 delete this;
119 return;
120 }
121 mMessage->addBuffer(mBuffer);
122 unsigned int numUnprocessedChars =
123 (mBuffer + chunkLength) - unprocessedCharPtr;
124 if (scanChunkResult == MsgHeaderScanner::scrNextChunk)
125 {
126 // Message header is incomplete...
127 if (numUnprocessedChars == 0)
128 {
129 // ...but the chunk is completely processed.
130 //.jacob. I've discarded the "assigned" concept.
131 //DebugLog(<< "Data assigned, not fragmented, not complete");
132 mBuffer = new char[ChunkSize + MsgHeaderScanner::MaxNumCharsChunkOverflow];
133 mBufferPos = 0;
134 mBufferSize = ChunkSize;
135 }
136 else
137 {
138 // ...but some of the chunk must be shifted into the next one.
139 size_t size = numUnprocessedChars*3/2;
140 if ( size < ConnectionBase::ChunkSize )
141 {
142 size = ConnectionBase::ChunkSize;
143 }
144 char* newBuffer = new char[size + MsgHeaderScanner::MaxNumCharsChunkOverflow];
145 memcpy(newBuffer, unprocessedCharPtr, numUnprocessedChars);
146 mBuffer = newBuffer;
147 mBufferPos = numUnprocessedChars;
148 mBufferSize = size;
149 }
150 mState = ReadingHeaders;
151 }
152 else
153 {
154 // The message header is complete.
155 size_t contentLength = mMessage->header(h_ContentLength).value();
156
157 if (numUnprocessedChars < contentLength)
158 {
159 // The message body is incomplete.
160 char* newBuffer = new char[contentLength + MsgHeaderScanner::MaxNumCharsChunkOverflow];
161 memcpy(newBuffer, unprocessedCharPtr, numUnprocessedChars);
162 mBufferPos = numUnprocessedChars;
163 mBufferSize = contentLength;
164 mBuffer = newBuffer;
165
166 mState = PartialBody;
167 }
168 else
169 {
170 // The message body is complete.
171 mMessage->setBody(unprocessedCharPtr, contentLength);
172 if (!transport()->basicCheck(*mMessage))
173 {
174 delete mMessage;
175 mMessage = 0;
176 }
177 else
178 {
179 Transport::stampReceived(mMessage);
180 DebugLog(<< "##Connection: " << *this << " received: " << *mMessage);
181 fifo.add(mMessage);
182 mMessage = 0;
183 }
184
185 int overHang = numUnprocessedChars - contentLength;
186
187 mState = NewMessage;
188 mBuffer = 0;
189 if (overHang > 0)
190 {
191 // The next message has been partially read.
192 size_t size = overHang*3/2;
193 if ( size < ConnectionBase::ChunkSize )
194 {
195 size = ConnectionBase::ChunkSize;
196 }
197 char* newBuffer = new char[size + MsgHeaderScanner::MaxNumCharsChunkOverflow];
198 memcpy(newBuffer,
199 unprocessedCharPtr + contentLength,
200 overHang);
201 mBuffer = newBuffer;
202 mBufferPos = 0;
203 mBufferSize = size;
204
205 DebugLog (<< "Extra bytes after message: " << overHang);
206 DebugLog (<< Data(mBuffer, overHang));
207
208 bytesRead = overHang;
209 goto start;
210 }
211 }
212 }
213 break;
214 }
215 case PartialBody:
216 {
217 size_t contentLength = mMessage->header(h_ContentLength).value();
218 mBufferPos += bytesRead;
219 if (mBufferPos == contentLength)
220 {
221 mMessage->setBody(mBuffer, contentLength);
222 if (!transport()->basicCheck(*mMessage))
223 {
224 delete mMessage;
225 mMessage = 0;
226 }
227 else
228 {
229 DebugLog(<< "##Connection: " << *this << " received: " << *mMessage);
230
231 Transport::stampReceived(mMessage);
232 fifo.add(mMessage);
233 }
234 mState = NewMessage;
235 mBuffer = 0;
236 }
237 break;
238 }
239 default:
240 assert(0);
241 }
242 }
243
244 std::pair<char*, size_t>
245 ConnectionBase::getWriteBuffer()
246 {
247 if (mState == NewMessage)
248 {
249 DebugLog (<< "Creating buffer for " << *this);
250
251 mBuffer = new char [ConnectionBase::ChunkSize + MsgHeaderScanner::MaxNumCharsChunkOverflow];
252 mBufferSize = ConnectionBase::ChunkSize;
253 mBufferPos = 0;
254 }
255 return std::make_pair(mBuffer + mBufferPos, mBufferSize - mBufferPos);
256 }
257
258 void
259 ConnectionBase::setBuffer(char* bytes, int count)
260 {
261 mBuffer = bytes;
262 mBufferPos = 0;
263 mBufferSize = count;
264 }
265
266 Transport*
267 ConnectionBase::transport()
268 {
269 assert(this);
270 return mWho.transport;
271 }
272
273 std::ostream&
274
275 resip::operator<<(std::ostream& strm, const resip::ConnectionBase& c)
276
277 {
278
279 strm << "CONN_BASE: " << &c << " " << c.mWho;
280
281 return strm;
282
283 }
284
285
286
287
288 /* ====================================================================
289 * The Vovida Software License, Version 1.0
290 *
291 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
292 *
293 * Redistribution and use in source and binary forms, with or without
294 * modification, are permitted provided that the following conditions
295 * are met:
296 *
297 * 1. Redistributions of source code must retain the above copyright
298 * notice, this list of conditions and the following disclaimer.
299 *
300 * 2. Redistributions in binary form must reproduce the above copyright
301 * notice, this list of conditions and the following disclaimer in
302 * the documentation and/or other materials provided with the
303 * distribution.
304 *
305 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
306 * and "Vovida Open Communication Application Library (VOCAL)" must
307 * not be used to endorse or promote products derived from this
308 * software without prior written permission. For written
309 * permission, please contact vocal@vovida.org.
310 *
311 * 4. Products derived from this software may not be called "VOCAL", nor
312 * may "VOCAL" appear in their name, without prior written
313 * permission of Vovida Networks, Inc.
314 *
315 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
316 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
317 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
318 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
319 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
320 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
321 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
322 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
323 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
324 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
325 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
326 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
327 * DAMAGE.
328 *
329 * ====================================================================
330 *
331 * This software consists of voluntary contributions made by Vovida
332 * Networks, Inc. and many individuals on behalf of Vovida Networks,
333 * Inc. For more information on Vovida Networks, Inc., please see
334 * <http://www.vovida.org/>.
335 *
336 */
337

Properties

Name Value
svn:eol-style LF
svn:executable *

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27