/[resiprocate]/main/resip/stack/test/testTcp.cxx
ViewVC logotype

Contents of /main/resip/stack/test/testTcp.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10639 - (show annotations) (download)
Thu Oct 10 18:21:49 2013 UTC (6 years, 1 month ago) by bcampen
File MIME type: text/plain
File size: 13656 byte(s)
See if we can force the sender to notice the connection has dropped by sending a stun ping.

1 #if defined(HAVE_CONFIG_H)
2 #include "config.h"
3 #endif
4
5 #if defined (HAVE_POPT_H)
6 #include <popt.h>
7 #else
8 #ifndef WIN32
9 #warning "will not work very well without libpopt"
10 #endif
11 #endif
12
13 #include <signal.h>
14 #include <iostream>
15
16 #include "resip/stack/TcpTransport.hxx"
17 #include "resip/stack/Helper.hxx"
18 #include "resip/stack/PlainContents.hxx"
19 #include "resip/stack/SipMessage.hxx"
20 #include "resip/stack/Uri.hxx"
21 #include "resip/stack/ExtensionHeader.hxx"
22 #include "rutil/Data.hxx"
23 #include "rutil/DnsUtil.hxx"
24 #include "rutil/Logger.hxx"
25 #include "rutil/Random.hxx"
26 #include "rutil/DataStream.hxx"
27
28 using namespace resip;
29 using namespace std;
30
31 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP
32
33 void
34 process(TcpBaseTransport* sender,
35 TcpBaseTransport* receiver)
36 {
37 FdSet fdset;
38 if (receiver) receiver->buildFdSet(fdset);
39 sender->buildFdSet(fdset);
40
41 fdset.selectMilliSeconds(1);
42
43 try
44 {
45 if (receiver) receiver->process(fdset);
46 }
47 catch(std::exception& e)
48 {
49 // .bwc. Do nothing substantive, since the stack thread doesn't
50 }
51 sender->process(fdset);
52 }
53
54 int
55 main(int argc, char* argv[])
56 {
57 #ifndef _WIN32
58 if ( signal( SIGPIPE, SIG_IGN) == SIG_ERR)
59 {
60 cerr << "Couldn't install signal handler for SIGPIPE" << endl;
61 exit(-1);
62 }
63 #endif
64
65 #ifdef WIN32
66 initNetwork();
67 #endif
68
69 char* logType = 0;
70 const char* logLevel = "WARNING";
71 int runs = 100;
72 int window = 10;
73 int seltime = 100;
74
75 #if defined(HAVE_POPT_H)
76 struct poptOption table[] = {
77 {"log-type", 'l', POPT_ARG_STRING, &logType, 0, "where to send logging messages", "syslog|cerr|cout"},
78 {"log-level", 'v', POPT_ARG_STRING, &logLevel, 0, "specify the default log level", "DEBUG|INFO|WARNING|ALERT"},
79 {"num-runs", 'r', POPT_ARG_INT, &runs, 0, "number of calls in test", 0},
80 {"window-size", 'w', POPT_ARG_INT, &window, 0, "number of registrations in test", 0},
81 {"select-time", 's', POPT_ARG_INT, &seltime, 0, "number of runs in test", 0},
82 POPT_AUTOHELP
83 { NULL, 0, 0, NULL, 0 }
84 };
85
86 poptContext context = poptGetContext(NULL, argc, const_cast<const char**>(argv), table, 0);
87 poptGetNextOpt(context);
88 poptFreeContext(context);
89 #endif
90
91 #ifdef WIN32
92 Log::initialize(Log::Cout, Log::Info, "testTcp");
93 #else
94 Log::initialize(logType, logLevel, argv[0]);
95 #endif
96
97 cout << "Performing " << runs << " runs." << endl;
98
99 Fifo<TransactionMessage> txFifo;
100 TcpTransport* sender = new TcpTransport(txFifo, 5070, V4, Data::Empty);
101
102 Fifo<TransactionMessage> rxFifo;
103 TcpTransport* receiver = new TcpTransport(rxFifo, 5080, V4, Data::Empty);
104
105 NameAddr target;
106 target.uri().scheme() = "sip";
107 target.uri().user() = "fluffy";
108 target.uri().host() = "localhost";
109 target.uri().port() = 5080;
110 target.uri().param(p_transport) = "tcp";
111
112 NameAddr from = target;
113 from.uri().port() = 5070;
114
115 InfoLog (<< "Creating messages");
116
117 list<SipMessage*> messages;
118 {
119 UInt64 startTime = Timer::getTimeMs();
120 for (int i=0; i<runs; i++)
121 {
122 SipMessage* m = Helper::makeInvite( target, from, from);
123 m->header(h_Vias).front().transport() = Tuple::toData(sender->transport());
124 m->header(h_Vias).front().sentHost() = "localhost";
125 m->header(h_Vias).front().sentPort() = sender->port();
126 int contentLength=resip::Random::getRandom()%65535;
127 std::string body(contentLength,'0');
128 std::auto_ptr<Contents> contents(new PlainContents(Data(body.data(), body.size())));
129 m->setContents(contents);
130 int headerLength=resip::Random::getRandom()%1024;
131 std::string bigHeader(headerLength,'h');
132 m->header(h_Subject).value()=Data(bigHeader.data(), bigHeader.size());
133 messages.push_back(m);
134 }
135
136 UInt64 elapsed = Timer::getTimeMs() - startTime;
137 cout << runs << " calls performed in " << elapsed << " ms, a rate of "
138 << runs / ((float) elapsed / 1000.0) << " calls per second.]" << endl;
139
140 InfoLog (<< "Messages created");
141 }
142
143 //delete receiver;
144 //receiver=0;
145
146 in_addr in;
147 DnsUtil::inet_pton("127.0.0.1", in);
148 Tuple dest(in, target.uri().port(), TCP);
149 InfoLog (<< "Sending to " << dest);
150
151 UInt64 startTime = Timer::getTimeMs();
152
153 int tid=1;
154 int outstanding=0;
155
156 while (!messages.empty())
157 {
158 // load up the send window
159 while (outstanding < window)
160 {
161 Data encoded;
162 {
163 DataStream strm(encoded);
164 SipMessage* next = messages.front();
165 messages.pop_front();
166 next->encode(strm);
167 outstanding++;
168 delete next;
169 }
170 std::auto_ptr<SendData> toSend(sender->makeSendData(dest, encoded, Data(tid++), Data::Empty));
171 sender->send(toSend);
172 }
173
174 FdSet fdset;
175 if (receiver) receiver->buildFdSet(fdset);
176 sender->buildFdSet(fdset);
177
178 fdset.selectMilliSeconds(seltime);
179
180 if (receiver) receiver->process(fdset);
181 sender->process(fdset);
182
183 Message* msg;
184 if (rxFifo.messageAvailable())
185 {
186 msg = rxFifo.getNext();
187 SipMessage* received = dynamic_cast<SipMessage*>(msg);
188 if (received)
189 {
190 //DebugLog (<< "got: " << received->brief());
191 outstanding--;
192
193 assert (received->header(h_RequestLine).uri().host() == "localhost");
194 assert (received->header(h_To).uri().host() == "localhost");
195 assert (received->header(h_From).uri().host() == "localhost");
196 assert (!received->header(h_Vias).begin()->sentHost().empty());
197 assert (received->header(h_Contacts).begin()->uri().host() == "localhost");
198 assert (!received->header(h_CallId).value().empty());
199 }
200 delete msg;
201 }
202 }
203
204 while (outstanding>0)
205 {
206 FdSet fdset;
207 if (receiver) receiver->buildFdSet(fdset);
208 sender->buildFdSet(fdset);
209
210 fdset.selectMilliSeconds(seltime);
211
212 if (receiver) receiver->process(fdset);
213 sender->process(fdset);
214
215 while (rxFifo.messageAvailable())
216 {
217 Message* msg = rxFifo.getNext();
218 SipMessage* received = dynamic_cast<SipMessage*>(msg);
219 if (received)
220 {
221 //DebugLog (<< "got: " << received->brief());
222 outstanding--;
223
224 assert (received->header(h_RequestLine).uri().host() == "localhost");
225 assert (received->header(h_To).uri().host() == "localhost");
226 assert (received->header(h_From).uri().host() == "localhost");
227 assert (!received->header(h_Vias).begin()->sentHost().empty());
228 assert (received->header(h_Contacts).begin()->uri().host() == "localhost");
229 assert (!received->header(h_CallId).value().empty());
230 }
231 delete msg;
232 }
233 }
234
235 UInt64 elapsed = Timer::getTimeMs() - startTime;
236 cout << runs << " calls peformed in " << elapsed << " ms, a rate of "
237 << runs / ((float) elapsed / 1000.0) << " calls per second.]" << endl;
238
239 SipMessage::checkContentLength=false;
240 {
241 UInt64 startTime = Timer::getTimeMs();
242 for (int i=0; i<runs; i++)
243 {
244 SipMessage* m = Helper::makeInvite( target, from, from);
245 m->header(h_Vias).front().transport() = Tuple::toData(sender->transport());
246 m->header(h_Vias).front().sentHost() = "localhost";
247 m->header(h_Vias).front().sentPort() = sender->port();
248
249 messages.push_back(m);
250 }
251
252 UInt64 elapsed = Timer::getTimeMs() - startTime;
253 cout << runs << " calls performed in " << elapsed << " ms, a rate of "
254 << runs / ((float) elapsed / 1000.0) << " calls per second.]" << endl;
255
256 InfoLog (<< "Messages created");
257 }
258
259 UInt32 type=0;
260 Data badContentLength1("-1");
261 Data badContentLength2("999999999999999999999999999999");
262 std::string hugeString(ConnectionBase::ChunkSize*2,'h');
263 ExtensionHeader h_huge(Data::from(hugeString));
264
265 while (!messages.empty())
266 {
267 // We need a well formed message to test that any traffic has
268 // gotten through at all.
269 Data wellFormed;
270 std::auto_ptr<SipMessage> next(messages.front());
271 messages.pop_front();
272
273 {
274 DataStream strm(wellFormed);
275 next->encode(strm);
276 outstanding++;
277 }
278
279 Data garbage;
280 const UInt32 NEGATIVE_CONTENT_LENGTH = 0;
281 const UInt32 HUGE_CONTENT_LENGTH = 1;
282 const UInt32 HUGE_HEADER_NAME = 2;
283 const UInt32 HUGE_HEADER_VALUE = 3;
284
285 switch(type%4)
286 {
287 case NEGATIVE_CONTENT_LENGTH:
288 case HUGE_CONTENT_LENGTH:
289 {
290 garbage = wellFormed;
291 // .bwc. Send one at a time for maximum potential damage.
292 garbage.replace("Content-Length: 0","Content-Length: "+( type == NEGATIVE_CONTENT_LENGTH ? badContentLength1 : badContentLength2));
293 }
294 break;
295 case HUGE_HEADER_NAME:
296 {
297 DataStream strm(garbage);
298 next->header(h_Subject).value()=Data(hugeString.data(), hugeString.size());
299 next->encode(strm);
300 }
301 break;
302 case HUGE_HEADER_VALUE:
303 {
304 DataStream strm(garbage);
305 next->header(h_huge).push_front(StringCategory("foo"));
306 next->encode(strm);
307 }
308 break;
309 }
310
311 ++type;
312 // Send a garbage request, followed by a good request
313 std::auto_ptr<SendData> garbageSend(sender->makeSendData(dest, garbage, Data(tid++), Data::Empty));
314 sender->send(garbageSend);
315
316
317 for(int p=0; p < 10; ++p)
318 {
319 process(sender, receiver);
320 std::auto_ptr<Message> msg(rxFifo.getNext(1));
321 SipMessage* received = dynamic_cast<SipMessage*>(msg.get());
322 // .bwc. These are all unrecoverable garbage, we should not get
323 // any sip traffic on this fifo.
324 if(received)
325 {
326 cout << "Unexpected message received: " << *received << endl;
327 }
328 assert(!received);
329 }
330
331 // Send a stun ping to make sure the sender has noticed the connection
332 // is closed.
333 std::auto_ptr<SendData> ping(sender->makeSendData(dest, "\r\n\r\n", Data(tid++), Data::Empty));
334 sender->send(ping);
335
336 // Throw in a process call to ensure that both sides have
337 // torn down the connection.
338 process(sender, receiver);
339
340 // Verify that good traffic can come through
341 std::auto_ptr<SendData> goodSend(sender->makeSendData(dest, wellFormed, Data(tid++), Data::Empty));
342 sender->send(goodSend);
343 bool failedToReceiveGoodMessage = true;
344 for(int p=0; p < 10; ++p)
345 {
346 process(sender, receiver);
347 std::auto_ptr<Message> msg(rxFifo.getNext(10));
348 SipMessage* received = dynamic_cast<SipMessage*>(msg.get());
349 if(received)
350 {
351 cout << *received << endl;
352 failedToReceiveGoodMessage = false;
353 break;
354 }
355 }
356 assert(!failedToReceiveGoodMessage);
357 }
358
359 return 0;
360 }
361
362 /* ====================================================================
363 * The Vovida Software License, Version 1.0
364 *
365 * Copyright (c) 2000-2005 Vovida Networks, Inc. All rights reserved.
366 *
367 * Redistribution and use in source and binary forms, with or without
368 * modification, are permitted provided that the following conditions
369 * are met:
370 *
371 * 1. Redistributions of source code must retain the above copyright
372 * notice, this list of conditions and the following disclaimer.
373 *
374 * 2. Redistributions in binary form must reproduce the above copyright
375 * notice, this list of conditions and the following disclaimer in
376 * the documentation and/or other materials provided with the
377 * distribution.
378 *
379 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
380 * and "Vovida Open Communication Application Library (VOCAL)" must
381 * not be used to endorse or promote products derived from this
382 * software without prior written permission. For written
383 * permission, please contact vocal@vovida.org.
384 *
385 * 4. Products derived from this software may not be called "VOCAL", nor
386 * may "VOCAL" appear in their name, without prior written
387 * permission of Vovida Networks, Inc.
388 *
389 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
390 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
391 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
392 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
393 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
394 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
395 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
396 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
397 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
398 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
399 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
400 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
401 * DAMAGE.
402 *
403 * ====================================================================
404 *
405 * This software consists of voluntary contributions made by Vovida
406 * Networks, Inc. and many individuals on behalf of Vovida Networks,
407 * Inc. For more information on Vovida Networks, Inc., please see
408 * <http://www.vovida.org/>.
409 *
410 */
411
412 // vim: softtabstop=3:shiftwidth=3:expandtab
413

Properties

Name Value
svn:eol-style native
svn:mime-type text/plain

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27