diff options
-rw-r--r-- | Swiften/Network/HTTPConnectProxiedConnection.cpp | 17 | ||||
-rw-r--r-- | Swiften/Network/HTTPConnectProxiedConnection.h | 3 | ||||
-rw-r--r-- | Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp | 22 |
3 files changed, 35 insertions, 7 deletions
diff --git a/Swiften/Network/HTTPConnectProxiedConnection.cpp b/Swiften/Network/HTTPConnectProxiedConnection.cpp index fc5a6c6..942361e 100644 --- a/Swiften/Network/HTTPConnectProxiedConnection.cpp +++ b/Swiften/Network/HTTPConnectProxiedConnection.cpp @@ -80,13 +80,13 @@ void HTTPConnectProxiedConnection::parseHTTPHeader(const std::string& data, std: if (splitIndex != std::string::npos) { headerFields.push_back(std::pair<std::string, std::string>(headerLine.substr(0, splitIndex), headerLine.substr(splitIndex + 1))); } } } -void HTTPConnectProxiedConnection::sendHTTPRequest(const std::string& statusLine, std::vector<std::pair<std::string, std::string> >& headerFields) { +void HTTPConnectProxiedConnection::sendHTTPRequest(const std::string& statusLine, const std::vector<std::pair<std::string, std::string> >& headerFields) { typedef std::pair<std::string, std::string> HTTPHeaderField; std::stringstream request; request << statusLine << "\r\n"; foreach (const HTTPHeaderField& field, headerFields) { request << field.first << ":" << field.second << "\r\n"; @@ -95,27 +95,33 @@ void HTTPConnectProxiedConnection::sendHTTPRequest(const std::string& statusLine write(createSafeByteArray(request.str())); } void HTTPConnectProxiedConnection::handleProxyInitializeData(boost::shared_ptr<SafeByteArray> data) { std::string dataString = byteArrayToString(ByteArray(data->begin(), data->end())); SWIFT_LOG(debug) << data << std::endl; + httpResponseBuffer_.append(dataString); std::string statusLine; std::vector<std::pair<std::string, std::string> > headerFields; - std::string::size_type headerEnd = dataString.find("\r\n\r\n", 0); + std::string::size_type headerEnd = httpResponseBuffer_.find("\r\n\r\n", 0); + if (headerEnd == std::string::npos) { + if ((httpResponseBuffer_.size() > 4) && (httpResponseBuffer_.substr(0, 4) != "HTTP")) { + setProxyInitializeFinished(false); + } + return; + } - parseHTTPHeader(dataString.substr(0, headerEnd), statusLine, headerFields); + parseHTTPHeader(httpResponseBuffer_.substr(0, headerEnd), statusLine, headerFields); if (trafficFilter_) { std::vector<std::pair<std::string, std::string> > newHeaderFields = trafficFilter_->filterHTTPResponseHeader(headerFields); if (!newHeaderFields.empty()) { std::stringstream statusLine; statusLine << "CONNECT " << getServer().getAddress().toString() << ":" << getServer().getPort(); sendHTTPRequest(statusLine.str(), newHeaderFields); - SWIFT_LOG(debug) << "send HTTP request from traffic filter" << std::endl; return; } } std::vector<std::string> tmp = String::split(statusLine, ' '); if (tmp.size() > 1) { @@ -123,19 +129,20 @@ void HTTPConnectProxiedConnection::handleProxyInitializeData(boost::shared_ptr<S int status = boost::lexical_cast<int>(tmp[1]); SWIFT_LOG(debug) << "Proxy Status: " << status << std::endl; if (status / 100 == 2) { // all 2XX states are OK setProxyInitializeFinished(true); } else { - SWIFT_LOG(debug) << "HTTP Proxy returned an error: " << byteArrayToString(ByteArray(data->begin(), data->end())) << std::endl; + SWIFT_LOG(debug) << "HTTP Proxy returned an error: " << httpResponseBuffer_ << std::endl; setProxyInitializeFinished(false); } } catch (boost::bad_lexical_cast&) { SWIFT_LOG(warning) << "Unexpected response: " << tmp[1] << std::endl; setProxyInitializeFinished(false); } } else { setProxyInitializeFinished(false); } + httpResponseBuffer_.clear(); } diff --git a/Swiften/Network/HTTPConnectProxiedConnection.h b/Swiften/Network/HTTPConnectProxiedConnection.h index 7d83863..11431bf 100644 --- a/Swiften/Network/HTTPConnectProxiedConnection.h +++ b/Swiften/Network/HTTPConnectProxiedConnection.h @@ -38,15 +38,16 @@ namespace Swift { private: HTTPConnectProxiedConnection(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort, const SafeString& authID, const SafeString& authPassword); virtual void initializeProxy(); virtual void handleProxyInitializeData(boost::shared_ptr<SafeByteArray> data); - void sendHTTPRequest(const std::string& statusLine, std::vector<std::pair<std::string, std::string> >& headerFields); + void sendHTTPRequest(const std::string& statusLine, const std::vector<std::pair<std::string, std::string> >& headerFields); void parseHTTPHeader(const std::string& data, std::string& statusLine, std::vector<std::pair<std::string, std::string> >& headerFields); private: SafeByteArray authID_; SafeByteArray authPassword_; boost::shared_ptr<HTTPTrafficFilter> trafficFilter_; + std::string httpResponseBuffer_; }; } diff --git a/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp b/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp index fb6914e..d3db79d 100644 --- a/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp +++ b/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp @@ -46,12 +46,13 @@ namespace { class HTTPConnectProxiedConnectionTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(HTTPConnectProxiedConnectionTest); CPPUNIT_TEST(testConnect_CreatesConnectionToProxy); CPPUNIT_TEST(testConnect_SendsConnectRequest); CPPUNIT_TEST(testConnect_ReceiveConnectResponse); + CPPUNIT_TEST(testConnect_ReceiveConnectChunkedResponse); CPPUNIT_TEST(testConnect_ReceiveMalformedConnectResponse); CPPUNIT_TEST(testConnect_ReceiveErrorConnectResponse); CPPUNIT_TEST(testConnect_ReceiveDataAfterConnect); CPPUNIT_TEST(testWrite_AfterConnect); CPPUNIT_TEST(testDisconnect_AfterConnectRequest); CPPUNIT_TEST(testDisconnect_AfterConnect); @@ -115,12 +116,27 @@ class HTTPConnectProxiedConnectionTest : public CppUnit::TestFixture { CPPUNIT_ASSERT(connectFinished); CPPUNIT_ASSERT(!connectFinishedWithError); CPPUNIT_ASSERT(dataRead.empty()); } + void testConnect_ReceiveConnectChunkedResponse() { + HTTPConnectProxiedConnection::ref testling(createTestling()); + connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345)); + + connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 ")); + eventLoop->processEvents(); + connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("200 Connection established\r\n\r\n")); + eventLoop->processEvents(); + + CPPUNIT_ASSERT(connectFinished); + CPPUNIT_ASSERT(!connectFinishedWithError); + CPPUNIT_ASSERT(dataRead.empty()); + } + + void testConnect_ReceiveMalformedConnectResponse() { HTTPConnectProxiedConnection::ref testling(createTestling()); connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345)); connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("FLOOP")); eventLoop->processEvents(); @@ -200,18 +216,22 @@ class HTTPConnectProxiedConnectionTest : public CppUnit::TestFixture { // set a default response so the server response is answered by the traffic filter httpTrafficFilter->filterResponseReturn.clear(); httpTrafficFilter->filterResponseReturn.push_back(std::pair<std::string, std::string>("Authorization", "Negotiate a87421000492aa874209af8bc028")); connectionFactory->connections[0]->dataWritten.clear(); + // test chunked response + connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef( + "HTTP/1.0 401 Unauthorized\r\n")); + eventLoop->processEvents(); connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef( - "HTTP/1.0 401 Unauthorized\r\n" "WWW-Authenticate: Negotiate\r\n" "\r\n")); eventLoop->processEvents(); + // verify that the traffic filter got called and answered with its response CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), httpTrafficFilter->filterResponses.size()); CPPUNIT_ASSERT_EQUAL(std::string("WWW-Authenticate"), httpTrafficFilter->filterResponses[0][0].first); // remove the default response from the traffic filter httpTrafficFilter->filterResponseReturn.clear(); |