RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
00001 /* http_long_header_test.cc 00002 Jeremy Barnes, 31 January 2011 00003 Copyright (c) 2011 Datacratic. All rights reserved. 00004 00005 Test that we can't crash the server sending long headers. 00006 */ 00007 00008 #define BOOST_TEST_MAIN 00009 #define BOOST_TEST_DYN_LINK 00010 00011 #include <boost/test/unit_test.hpp> 00012 #include "soa/service/http_endpoint.h" 00013 #include "soa/service/active_endpoint.h" 00014 #include "soa/service/passive_endpoint.h" 00015 #include <sys/socket.h> 00016 #include "jml/utils/guard.h" 00017 #include "jml/utils/filter_streams.h" 00018 #include "jml/arch/exception_handler.h" 00019 #include "jml/utils/testing/watchdog.h" 00020 #include "jml/utils/testing/fd_exhauster.h" 00021 #include "test_connection_error.h" 00022 00023 using namespace std; 00024 using namespace ML; 00025 using namespace Datacratic; 00026 00027 #define BOOST_TEST_MAIN 00028 #define BOOST_TEST_DYN_LINK 00029 00030 #include <boost/test/unit_test.hpp> 00031 #include "soa/service/http_endpoint.h" 00032 #include "soa/service/active_endpoint.h" 00033 #include "soa/service/passive_endpoint.h" 00034 #include <sys/socket.h> 00035 #include "jml/utils/guard.h" 00036 #include "jml/arch/exception_handler.h" 00037 #include "jml/utils/testing/watchdog.h" 00038 #include "jml/utils/testing/fd_exhauster.h" 00039 #include <poll.h> 00040 00041 using namespace std; 00042 using namespace ML; 00043 using namespace Datacratic; 00044 00045 00046 BOOST_AUTO_TEST_CASE( test_accept_speed ) 00047 { 00048 Watchdog watchdog(5.0); 00049 00050 string connectionError; 00051 00052 PassiveEndpointT<SocketTransport> acceptor("acceptor"); 00053 00054 string error; 00055 00056 struct TestHandler : HttpConnectionHandler { 00057 00058 TestHandler(string & error) 00059 : bytesDone(0), error(error) 00060 { 00061 } 00062 00063 int bytesDone; 00064 string & error; 00065 00066 virtual void handleData(const std::string & data) 00067 { 00068 00069 bytesDone += data.size(); 00070 if (bytesDone > 1000000) 00071 throw ML::Exception("allowed infinite headers"); 00072 HttpConnectionHandler::handleData(data); 00073 } 00074 00075 virtual void handleError(const std::string & error) 00076 { 00077 cerr << "got error " << error << endl; 00078 this->error = error; 00079 } 00080 00081 virtual void 00082 handleHttpHeader(const HttpHeader & header) 00083 { 00084 00085 cerr << "got header " << header << endl; 00086 } 00087 00088 virtual void handleHttpChunk(const HttpHeader & header, 00089 const std::string & chunkHeader, 00090 const std::string & chunk) 00091 { 00092 cerr << "chunkHeader " << chunkHeader << endl; 00093 //cerr << "chunk has " << chunk.length() << " bytes" << endl; 00094 } 00095 00096 }; 00097 00098 acceptor.onMakeNewHandler = [&] () 00099 { 00100 return ML::make_std_sp(new TestHandler(error)); 00101 }; 00102 00103 int port = acceptor.init(); 00104 00105 cerr << "port = " << port << endl; 00106 00107 BOOST_CHECK_EQUAL(acceptor.numConnections(), 0); 00108 00109 Date before = Date::now(); 00110 00111 /* Open a connection */ 00112 int s = socket(AF_INET, SOCK_STREAM, 0); 00113 if (s == -1) 00114 throw Exception("socket"); 00115 00116 //cerr << "i = " << i << " s = " << s << " sockets.size() = " 00117 // << sockets.size() << endl; 00118 00119 struct sockaddr_in addr = { AF_INET, htons(port), { INADDR_ANY } }; 00120 //cerr << "before connect on " << s << endl; 00121 int res = connect(s, reinterpret_cast<const sockaddr *>(&addr), 00122 sizeof(addr)); 00123 //cerr << "after connect on " << s << endl; 00124 00125 if (res == -1) { 00126 cerr << "connect error: " << strerror(errno) << endl; 00127 close(s); 00128 } 00129 00130 /* Try to write 32MB of headers into the socket. */ 00131 const char * buf = "header: 9012345678901234567890\r\n"; 00132 00133 int written = 0; 00134 int writeError = 0; 00135 00136 for (unsigned i = 0; i < 1000000; ++i) { 00137 int res = write(s, buf, strlen(buf)); 00138 if (res > 0) 00139 written += res; 00140 else if (res == 0) 00141 throw ML::Exception("nothing written"); 00142 else { 00143 writeError = errno; 00144 cerr << strerror(errno) << endl; 00145 cerr << "error after writing " << written << " bytes" 00146 << endl; 00147 break; 00148 } 00149 } 00150 00151 // Check we didn't write more than 1MB before the error... 00152 BOOST_CHECK_LT(written, 1000000); 00153 BOOST_CHECK_EQUAL(writeError, ECONNRESET); 00154 BOOST_CHECK_NE(error.find("HTTP header exceeds"), string::npos); 00155 00156 cerr << "wrote " << written << " bytes" << endl; 00157 00158 close(s); 00159 00160 acceptor.shutdown(); 00161 }