#ifndef SIMGEAR_IO_TEST_HTTP_HXX #define SIMGEAR_IO_TEST_HTTP_HXX #include #include #include #include #include namespace simgear { class TestServerChannel : public NetChat { public: enum State { STATE_IDLE = 0, STATE_HEADERS, STATE_CLOSING, STATE_REQUEST_BODY }; TestServerChannel() { state = STATE_IDLE; setTerminator("\r\n"); } virtual ~TestServerChannel() { } virtual void collectIncomingData(const char* s, int n) { buffer += std::string(s, n); } virtual void foundTerminator(void) { if (state == STATE_IDLE) { state = STATE_HEADERS; string_list line = strutils::split(buffer, NULL, 3); if (line.size() < 3) { std::cerr << "malformed request:" << buffer << std::endl; exit(-1); } method = line[0]; path = line[1]; std::string::size_type queryPos = path.find('?'); if (queryPos != std::string::npos) { parseArgs(path.substr(queryPos + 1)); path = path.substr(0, queryPos); } httpVersion = line[2]; requestHeaders.clear(); buffer.clear(); } else if (state == STATE_HEADERS) { std::string s = strutils::simplify(buffer); if (s.empty()) { buffer.clear(); receivedRequestHeaders(); return; } std::string::size_type colonPos = buffer.find(':'); if (colonPos == std::string::npos) { std::cerr << "test malformed HTTP response header:" << buffer << std::endl; buffer.clear(); return; } std::string key = strutils::simplify(buffer.substr(0, colonPos)); std::string value = strutils::strip(buffer.substr(colonPos + 1)); requestHeaders[key] = value; buffer.clear(); } else if (state == STATE_REQUEST_BODY) { receivedBody(); setTerminator("\r\n"); } else if (state == STATE_CLOSING) { // ignore! } } void parseArgs(const std::string& argData) { string_list argv = strutils::split(argData, "&"); for (unsigned int a=0; a requestHeaders; std::map args; int requestContentLength; }; template class TestServer : public NetChannel { simgear::NetChannelPoller _poller; std::vector _channels; public: TestServer() { Socket::initSockets(); open(); bind(NULL, 2000); // localhost, any port listen(16); _poller.addChannel(this); } virtual ~TestServer() { _poller.removeChannel(this); } virtual bool writable (void) { return false ; } virtual void handleAccept (void) { simgear::IPAddress addr ; int handle = accept ( &addr ) ; T* chan = new T(); chan->setHandle(handle); _channels.push_back(chan); _poller.addChannel(chan); } void poll() { _poller.poll(); auto it = std::remove_if(_channels.begin(), _channels.end(), [&](T* channel) { if (channel->isClosed()) { _poller.removeChannel(channel); delete channel; return true; } return false; }); _channels.erase(it, _channels.end()); } int connectCount() { return _channels.size(); } void disconnectAll() { typename std::vector::iterator it; for (it = _channels.begin(); it != _channels.end(); ++it) { _poller.removeChannel(*it); delete *it; } _channels.clear(); } }; } // of namespace simgear #endif // of SIMGEAR_IO_TEST_HTTP_HXX