// Test that only cookies we manually add to the header are sent. void HttpClientTest::testCookies() { bp::url::Url url(m_testServer.getEchoUrl()); RequestPtr ptrReq(new Request(Method::HTTP_POST, url)); // Tell the test server to echo request headers in response body. QueryString qs; qs.add("EchoHeaders", bp::conv::toString(1)); ptrReq->url.setQuery(qs.toString()); // Add some cookie headers. string sCookie = "kind=oatmeal"; Headers hdrs; hdrs.add( Headers::ksCookie, "kind=oatmeal" ); ptrReq->headers = hdrs; // Dummy body. const string ksBody = "Cookies are delicious"; ptrReq->body.assign(ksBody); // Execute the transaction. SyncTransactionPtr tran = SyncTransaction::alloc(ptrReq); SyncTransaction::FinalStatus results; ResponsePtr ptrResp = tran->execute(results); CPPUNIT_ASSERT(results.code == SyncTransaction::FinalStatus::eOk); CPPUNIT_ASSERT(ptrResp->status.code() == Status::OK); string sBody = ptrResp->body.toString(); string sCookieHdr = "Cookie: " + sCookie; string::size_type nIdx = sBody.find( sCookieHdr ); CPPUNIT_ASSERT( nIdx != string::npos); }
Request* Request::clone(ExceptionState& exceptionState) const { if (bodyUsed()) { exceptionState.throwTypeError("Request body is already used"); return nullptr; } FetchRequestData* request = m_request->clone(); if (blobDataHandle() && isBodyConsumed()) { // Currently the only methods that can consume body data without // setting 'body passed' flag consume entire body (e.g. text()). Thus // we can set an empty blob to the new request instead of creating a // draining stream. // TODO(yhirano): Fix this once Request.body is introduced. OwnPtr<BlobData> blobData = BlobData::create(); blobData->setContentType(blobDataHandle()->type()); request->setBlobDataHandle(BlobDataHandle::create(blobData.release(), 0)); } Headers* headers = Headers::create(request->headerList()); headers->setGuard(m_headers->guard()); Request* r = new Request(executionContext(), request, headers); r->suspendIfNeeded(); return r; }
bool HttpServerResponse::writeHead(int statusCode, const QByteArray &reasonPhrase, const Headers &headers) { if (priv->formattingState != Priv::STATUS_LINE) return false; if (priv->options.testFlag(HttpServerResponse::HTTP_1_0)) { static const char chunk[] = "HTTP/1.0 "; priv->device.write(chunk, sizeof(chunk) - 1); } else { static const char chunk[] = "HTTP/1.1 "; priv->device.write(chunk, sizeof(chunk) - 1); } priv->device.write(QByteArray::number(statusCode)); priv->device.write(" ", 1); priv->device.write(reasonPhrase); priv->device.write(CRLF); for (Headers::const_iterator i = headers.constBegin() ;i != headers.end();++i) { priv->device.write(i.key()); priv->device.write(": ", 2); priv->device.write(i.value()); priv->device.write(CRLF); } priv->formattingState = Priv::HEADERS; return true; }
void HTTPConnection::respondWithStatusAndHeaders(const char* code, const char* contentType, const Headers& headers, qint64 contentLength) { _socket->write("HTTP/1.1 "); _socket->write(code); _socket->write("\r\n"); for (Headers::const_iterator it = headers.constBegin(), end = headers.constEnd(); it != end; it++) { _socket->write(it.key()); _socket->write(": "); _socket->write(it.value()); _socket->write("\r\n"); } if (contentLength > 0) { _socket->write("Content-Length: "); _socket->write(QByteArray::number(contentLength)); _socket->write("\r\n"); _socket->write("Content-Type: "); _socket->write(contentType); _socket->write("\r\n"); } _socket->write("Connection: close\r\n\r\n"); }
Headers::const_iterator findHeader(const Headers& headers, const std::string& name) { return std::find_if(headers.begin(), headers.end(), HeaderNamePredicate(name)); }
void HTTPConnection::respond(const char* code, const QByteArray& content, const char* contentType, const Headers& headers) { _socket->write("HTTP/1.1 "); _socket->write(code); _socket->write("\r\n"); int csize = content.size(); for (Headers::const_iterator it = headers.constBegin(), end = headers.constEnd(); it != end; it++) { _socket->write(it.key()); _socket->write(": "); _socket->write(it.value()); _socket->write("\r\n"); } if (csize > 0) { _socket->write("Content-Length: "); _socket->write(QByteArray::number(csize)); _socket->write("\r\n"); _socket->write("Content-Type: "); _socket->write(contentType); _socket->write("\r\n"); } _socket->write("Connection: close\r\n\r\n"); if (csize > 0) { _socket->write(content); } // make sure we receive no further read notifications _socket->disconnect(SIGNAL(readyRead()), this); _socket->disconnectFromHost(); }
bool HttpServerResponse::addTrailers(const Headers &headers) { if (priv->options.testFlag(HttpServerResponse::HTTP_1_0)) return false; switch (priv->formattingState) { case Priv::STATUS_LINE: case Priv::END: case Priv::HEADERS: return false; case Priv::MESSAGE_BODY: priv->device.write("0\r\n"); priv->formattingState = Priv::TRAILERS; case Priv::TRAILERS: { for (Headers::const_iterator i = headers.constBegin() ;i != headers.end();++i) { priv->device.write(i.key()); priv->device.write(": ", 2); priv->device.write(i.value()); priv->device.write(CRLF); } } } // switch (priv->formattingState) return true; }
void QPalringoConnection::onPingReceived( const Headers, const QByteArray /* body */ ) { Headers h; if( protocolVersion_ == 2 ) { h.insert( qpHeaderAttribute::PS, packetSeq_ ); } sendCmd( qpCommand::PING, h, ""); }
std::string headerValue(const Headers& headers, const std::string& name) { Headers::const_iterator it = std::find_if(headers.begin(), headers.end(), HeaderNamePredicate(name)) ; if ( it != headers.end() ) return (*it).value ; else return std::string() ; }
Response* Response::clone(ExceptionState& exceptionState) { if (isBodyLocked() || bodyUsed()) { exceptionState.throwTypeError("Response body is already used"); return nullptr; } FetchResponseData* response = m_response->clone(executionContext()); Headers* headers = Headers::create(response->headerList()); headers->setGuard(m_headers->guard()); return new Response(executionContext(), response, headers); }
void assign(const Message& message, const Headers& extraHeaders) { body_ = message.body_; httpVersionMajor_ = message.httpVersionMajor_; httpVersionMinor_ = message.httpVersionMinor_; headers_ = message.headers_; overrideHeader_ = message.overrideHeader_; httpVersion_ = message.httpVersion_; std::for_each(extraHeaders.begin(), extraHeaders.end(), boost::bind(&Message::setExtraHeader, this, _1)); }
void P2pRpcConnection::onNotifyEvent(cstring event, const ObjectList& args) { if(eventMap.contain(event)){ //remote method name String method = eventMap.getDefault(event, ""); //this->cast(method, args); Headers headers; headers.put(KEY_RESPONSE, "true"); headers.put(KEY_CONTENT_TYPE, this->serializerType); ; sendEvent(headers, method, args); } }
/** * @brief * * @param headers * @param payload * @param statusCode * @param statusText * * @return */ bool RtspConnection::sendResponse( Headers &headers, std::string payload, int statusCode, std::string statusText ) { std::string response; response = stringtf( "RTSP/1.0 %d %s\r\n", statusCode, statusText.c_str() ); //headers.insert( Headers::value_type( "Server", "ZoneMinder Streamer V2.0" ) ); headers.insert( Headers::value_type( "Date", datetimeInet() ) ); for ( Headers::iterator iter = headers.begin(); iter != headers.end(); iter++ ) { response += iter->first+": "+iter->second+"\r\n"; } response += "\r\n"; if ( payload.size() ) { response += payload; } Debug( 2, "Sending RTSP response: %s", response.c_str() ); if ( mSocket->send( response.c_str(), response.size() ) != (int)response.length() ) { Error( "Unable to send response '%s': %s", response.c_str(), strerror(errno) ); return( false ); } #if 0 // Not currently used. If RTSP over HTTP ever required then will need to do something like this if ( mMethod == RTP_OZ_RTSP_HTTP ) { response = base64Encode( response ); Debug( 2, "Sending encoded RTSP response: %s", response.c_str() ); if ( mRtspSocket2.send( response.c_str(), response.size() ) != (int)response.length() ) { Error( "Unable to send response '%s': %s", response.c_str(), strerror(errno) ); return( false ); } } else { if ( mRtspSocket.send( response.c_str(), response.size() ) != (int)response.length() ) { Error( "Unable to send response '%s': %s", response.c_str(), strerror(errno) ); return( false ); } } #endif return( true ); }
// ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- size_t ChValidation::ReadDataFile(const std::string& filename, char delim, Headers& headers, Data& data) { std::ifstream ifile(filename.c_str()); std::string line; // Count the number of lines in the file then rewind the input file stream. size_t num_lines = std::count(std::istreambuf_iterator<char>(ifile), std::istreambuf_iterator<char>(), '\n'); ifile.seekg(0, ifile.beg); size_t num_data_points = num_lines - 3; // Skip the first two lines. std::getline(ifile, line); std::getline(ifile, line); // Read the line with column headers. std::getline(ifile, line); std::stringstream iss1(line); std::string col_header = ""; while (std::getline(iss1, col_header, delim)) headers.push_back(col_header); size_t num_cols = headers.size(); // Resize data data.resize(num_cols); for (size_t col = 0; col < num_cols; col++) data[col].resize(num_data_points); // Read the actual data, one line at a time. size_t row = 0; while (std::getline(ifile, line)) { std::stringstream iss(line); for (size_t col = 0; col < num_cols; col++) iss >> data[col][row]; row++; } return row; }
bool CWsgiEngine::finalizeHeadersWrite(Context *c, quint16 status, const Headers &headers, void *engineData) { auto conn = static_cast<QIODevice*>(engineData); conn->write("HTTP/1.1 ", 9); int msgLen; const char *msg = httpStatusMessage(status, &msgLen); conn->write(msg, msgLen); auto sock = qobject_cast<TcpSocket*>(conn); const auto headersData = headers.data(); if (sock->headerClose == 1) { sock->headerClose = 0; } bool hasDate = false; auto it = headersData.constBegin(); const auto endIt = headersData.constEnd(); while (it != endIt) { const QString key = it.key(); const QString value = it.value(); if (sock->headerClose == 0 && key == QLatin1String("connection")) { if (value.compare(QLatin1String("close"), Qt::CaseInsensitive) == 0) { sock->headerClose = 2; } else { sock->headerClose = 1; } } else if (!hasDate && key == QLatin1String("date")) { hasDate = true; } QString ret(QLatin1String("\r\n") + camelCaseHeader(key) + QLatin1String(": ") + value); conn->write(ret.toLatin1()); ++it; } if (!hasDate) { static QByteArray lastDate = dateHeader(); static QElapsedTimer timer = timerSetup(); if (timer.hasExpired(1000)) { lastDate = dateHeader(); timer.restart(); } conn->write(lastDate); } static QByteArray server = serverHeader(); conn->write(server); return conn->write("\r\n\r\n", 4) == 4; }
JSON::Dict &Request::parseJSONArgs() { Headers hdrs = getInputHeaders(); if (hdrs.hasContentType() && String::startsWith(hdrs.getContentType(), "application/json")) { Buffer buf = getInputBuffer(); if (buf.getLength()) { Event::BufferStream<> stream(buf); JSON::Reader reader(stream); // Find start of dict & parse keys into request args if (reader.next() == '{') { JSON::ValuePtr argsPtr = JSON::ValuePtr::Phony(&args); JSON::Builder builder(argsPtr); reader.parseDict(builder); } } } return args; }
void makeNodesHeader(const boost::filesystem::path& output, const Builder& builder, const Headers& headerFileNames) { boost::filesystem::path hpath = output, spath = output; hpath /= "nodes.hpp"; spath /= "nodes.cpp"; boost::filesystem::ofstream h(hpath.c_str()); boost::filesystem::ofstream s(spath.c_str()); h << "/* Automatically generated by ast-gen. DO NOT MODIFY. */\n"; h << "#pragma once\n"; for (Headers::const_iterator it = headerFileNames.begin(); it != headerFileNames.end(); it++) { h << "#include \"maxwell/ast/nodes/" << *it << "\"\n"; } h << "#include <string>\n"; s << "/* Automatically generated by ast-gen. DO NOT MODIFY. */\n"; s << "#include \"maxwell/ast/nodes/nodes.hpp\"\n\n"; // Generate the node factory class. h << "\nnamespace ast {\n\n"; // h << "class NodeFactory\n{\npublic:\n"; // h << "\tstatic NodePtr make(const std::string& name);\n"; // h << "};\n"; h << "NodePtr makeNode(const std::string& name);\n\n"; h << "} // namespace ast\n\n"; // s << "NodePtr NodeFactory::make(const std::string& name) {\n"; s << "ast::NodePtr ast::makeNode(const std::string& name) {\n"; s << "\tsize_t size = name.size();\n"; NodeNames names; for (Builder::Nodes::const_iterator it = builder.nodes.begin(); it != builder.nodes.end(); it++) { names.insert(it->first); } generateFactoryBody(s, names, 1); s << "\tthrow std::runtime_error(\"Node class name '\" + name + \"' not known to NodeFactory.\");\n"; s << "}\n"; }
bool uWSGI::finalizeHeaders(Context *ctx) { struct wsgi_request *wsgi_req = static_cast<wsgi_request*>(ctx->request()->engineData()); Response *res = ctx->res(); QByteArray status = statusCode(res->status()); if (uwsgi_response_prepare_headers(wsgi_req, status.data(), status.size())) { return false; } if (!Engine::finalizeHeaders(ctx)) { return false; } const Headers headers = res->headers(); auto it = headers.constBegin(); auto endIt = headers.constEnd(); while (it != endIt) { QByteArray key = camelCaseHeader(it.key()).toLatin1(); QByteArray value = it.value().toLatin1(); if (uwsgi_response_add_header(wsgi_req, key.data(), key.size(), value.data(), value.size())) { return false; } ++it; } return true; }
void getResponseHeaders(Headers& headers) { while (true) { istream line(input.readLine()); Header newHeader; getline(line, newHeader.first, ':'); // Only read up until the ':' trim(newHeader.first); to_lower(newHeader.first); if (newHeader.first.empty()) break; getline(line, newHeader.second); // Read the rest of the line trim(newHeader.second); headers.insert(newHeader); } }
void RequestParser::parseHeaders(const Item& aItem, Headers& aHeaders) { Item lKey; String lName; String lValue; zorba::Iterator_t lIterator = aItem.getObjectKeys(); lIterator->open(); while (lIterator->next(lKey)) { lName = lKey.getStringValue(); getString(aItem, lName, true, lValue); aHeaders.push_back(std::pair<String, String>(lName, lValue)); } lIterator->close(); }
void process_properties(Feature & feature, Headers const& headers, Values const& values, Locator const& locator, Transcoder const& tr) { auto val_beg = values.begin(); auto val_end = values.end(); auto num_headers = headers.size(); for (std::size_t i = 0; i < num_headers; ++i) { std::string const& fld_name = headers.at(i); if (val_beg == val_end) { feature.put(fld_name,tr.transcode("")); continue; } std::string value = mapnik::util::trim_copy(*val_beg++); int value_length = value.length(); if (locator.index == i && (locator.type == geometry_column_locator::WKT || locator.type == geometry_column_locator::GEOJSON) ) continue; bool matched = false; bool has_dot = value.find(".") != std::string::npos; if (value.empty() || (value_length > 20) || (value_length > 1 && !has_dot && value[0] == '0')) { matched = true; feature.put(fld_name,std::move(tr.transcode(value.c_str()))); } else if (csv_utils::is_likely_number(value)) { bool has_e = value.find("e") != std::string::npos; if (has_dot || has_e) { double float_val = 0.0; if (mapnik::util::string2double(value,float_val)) { matched = true; feature.put(fld_name,float_val); } } else { mapnik::value_integer int_val = 0; if (mapnik::util::string2int(value,int_val)) { matched = true; feature.put(fld_name,int_val); } } } if (!matched) { if (csv_utils::ignore_case_equal(value, "true")) { feature.put(fld_name, true); } else if (csv_utils::ignore_case_equal(value, "false")) { feature.put(fld_name, false); } else // fallback to string { feature.put(fld_name,std::move(tr.transcode(value.c_str()))); } } } }
void clear () { myHead.clear(); myBody.clear(); }
void HeadersTest::caseInsensitivity() { QFETCH(QByteArray, qbytearray1); QFETCH(QByteArray, qbytearray2); const IByteArray ibytearray1 = IByteArray{qbytearray1.constData()}; const IByteArray ibytearray2 = qbytearray2; Headers headers; headers.insert(ibytearray1, qbytearray2); headers.insert(ibytearray2, qbytearray2); QCOMPARE(headers.count(ibytearray1), 2); QCOMPARE(headers.count(ibytearray2), 2); QVERIFY(headers.values(ibytearray1)[0] == headers.values(ibytearray2)[1]); /* ====================================================================== */ headers.clear(); headers.insert(ibytearray1, qbytearray2); headers.replace(ibytearray1, qbytearray1); headers.insert(ibytearray2, qbytearray2); QCOMPARE(headers.count(ibytearray1), 2); QCOMPARE(headers.count(ibytearray2), 2); QVERIFY(headers.values(ibytearray1)[0] != headers.values(ibytearray2)[1]); }
void addHeader( Header const & header ) { assert( !fromCache() ); includedHeaders_.insert( header ); }
Uploads MultiPartFormDataParserPrivate::execute(char *buffer, int bufferSize) { Uploads ret; QByteArray header; Headers headers; qint64 startOffset; int boundaryPos = 0; ParserState state = FindBoundary; while (!body->atEnd()) { qint64 len = body->read(buffer, bufferSize); int i = 0; while (i < len) { switch (state) { case FindBoundary: i += findBoundary(buffer + i, len - i, state, boundaryPos); break; case EndBoundaryCR: // TODO the "--" case if (buffer[i] != '\r') { // qCDebug(CUTELYST_MULTIPART) << "EndBoundaryCR return!"; return ret; } state = EndBoundaryLF; break; case EndBoundaryLF: if (buffer[i] != '\n') { // qCDebug(CUTELYST_MULTIPART) << "EndBoundaryLF return!"; return ret; } header.clear(); state = StartHeaders; break; case StartHeaders: // qCDebug(CUTELYST_MULTIPART) << "StartHeaders" << body->pos() - len + i; if (buffer[i] == '\r') { state = EndHeaders; } else if (buffer[i] == '-') { // qCDebug(CUTELYST_MULTIPART) << "StartHeaders return!"; return ret; } else { char *pch = strchr(buffer + i, '\r'); if (pch == NULL) { header.append(buffer + i, len - i); i = len; } else { header.append(buffer + i, pch - buffer - i); i = pch - buffer; state = FinishHeader; } } break; case FinishHeader: // qCDebug(CUTELYST_MULTIPART) << "FinishHeader" << header; if (buffer[i] == '\n') { int dotdot = header.indexOf(':'); headers.setHeader(QString::fromLatin1(header.left(dotdot)), QString::fromLatin1(header.mid(dotdot + 1).trimmed())); header.clear(); state = StartHeaders; } else { // qCDebug(CUTELYST_MULTIPART) << "FinishHeader return!"; return ret; } break; case EndHeaders: // qCDebug(CUTELYST_MULTIPART) << "EndHeaders"; if (buffer[i] == '\n') { state = StartData; } else { // qCDebug(CUTELYST_MULTIPART) << "EndHeaders return!"; return ret; } break; case StartData: // qCDebug(CUTELYST_MULTIPART) << "StartData" << body->pos() - len + i; startOffset = body->pos() - len + i; state = EndData; case EndData: i += findBoundary(buffer + i, len - i, state, boundaryPos); if (state == EndBoundaryCR) { // qCDebug(CUTELYST_MULTIPART) << "EndData" << body->pos() - len + i - boundaryLength - 1; UploadPrivate *priv = new UploadPrivate(body); priv->headers = headers; headers.clear(); priv->startOffset = startOffset; priv->endOffset = body->pos() - len + i - boundaryLength - 1; ret << new Upload(priv); } } ++i; } } return ret; }
void uWSGI::processRequest(wsgi_request *req) { CachedRequest *cache = static_cast<CachedRequest *>(req->async_environ); // wsgi_req->uri containg the whole URI it /foo/bar?query=null // so we use path_info, maybe it would be better to just build our // Request->uri() from it, but we need to run a performance test uint16_t pos = notSlash(req->path_info, req->path_info_len); const QString path = QString::fromLatin1(req->path_info + pos, req->path_info_len - pos); const QString serverAddress = QString::fromLatin1(req->host, req->host_len); const QByteArray query = QByteArray::fromRawData(req->query_string, req->query_string_len); const QString method = QString::fromLatin1(req->method, req->method_len); const QString protocol = QString::fromLatin1(req->protocol, req->protocol_len); const QString remoteAddress = QString::fromLatin1(req->remote_addr, req->remote_addr_len); const QString remoteUser = QString::fromLatin1(req->remote_user, req->remote_user_len); quint16 remotePort = 0; Headers headers; // we scan the table in reverse, as updated values are at the end for (int i = req->var_cnt - 1; i > 0; i -= 2) { struct iovec &name = req->hvec[i - 1]; struct iovec &value = req->hvec[i]; if (!uwsgi_startswith(static_cast<char *>(name.iov_base), const_cast<char *>("HTTP_"), 5)) { headers.setHeader(QString::fromLatin1(static_cast<char *>(name.iov_base) + 5, name.iov_len - 5), QString::fromLatin1(static_cast<char *>(value.iov_base), value.iov_len)); } else if (!remotePort && !uwsgi_strncmp(const_cast<char *>("REMOTE_PORT"), 11, static_cast<char *>(name.iov_base), name.iov_len)) { remotePort = QByteArray::fromRawData(static_cast<char *>(value.iov_base), value.iov_len).toUInt(); } } if (req->content_type_len > 0) { headers.setContentType(QString::fromLatin1(req->content_type, req->content_type_len)); } if (req->encoding_len > 0) { headers.setContentEncoding(QString::fromLatin1(req->encoding, req->encoding_len)); } QIODevice *body; if (req->post_file) { // qCDebug(CUTELYST_UWSGI) << "Post file available:" << req->post_file; QFile *upload = cache->bodyFile; if (upload->open(req->post_file, QIODevice::ReadOnly)) { body = upload; } else { // qCDebug(CUTELYST_UWSGI) << "Could not open post file:" << upload->errorString(); body = cache->bodyBufferedUWSGI; body->open(QIODevice::ReadOnly | QIODevice::Unbuffered); } } else if (uwsgi.post_buffering) { // qCDebug(CUTELYST_UWSGI) << "Post buffering size:" << uwsgi.post_buffering; body = cache->bodyUWSGI; body->reset(); } else { // BodyBufferedUWSGI is an IO device which will // only consume the body when some of it's functions // is called, this is because here we can't seek // the body. body = cache->bodyBufferedUWSGI; body->open(QIODevice::ReadOnly | QIODevice::Unbuffered); } Engine::processRequest(method, path, query, protocol, req->https_len, serverAddress, remoteAddress, remotePort, remoteUser, headers, req->start_of_request, body, req); body->close(); }
/** * @brief * * @param request * * @return */ bool RtspConnection::handleRequest( const std::string &request ) { Debug( 2, "Handling RTSP request: %s (%zd bytes)", request.c_str(), request.size() ); StringTokenList lines( request, "\r\n" ); if ( lines.size() <= 0 ) { Error( "Unable to split request '%s' into tokens", request.c_str() ); return( false ); } StringTokenList parts( lines[0], " " ); if ( parts.size() != 3 ) { Error( "Unable to split request part '%s' into tokens", lines[0].c_str() ); return( false ); } std::string requestType = parts[0]; Debug( 4, "Got request '%s'", requestType.c_str() ); std::string requestUrl = parts[1]; Debug( 4, "Got requestUrl '%s'", requestUrl.c_str() ); std::string requestVer = parts[2]; Debug( 4, "Got requestVer '%s'", requestVer.c_str() ); if ( requestVer != "RTSP/1.0" ) { Error( "Unexpected RTSP version '%s'", requestVer.c_str() ); return( false ); } // Extract headers from request Headers requestHeaders; for ( int i = 1; i < lines.size(); i++ ) { StringTokenList parts( lines[i], ": " ); if ( parts.size() != 2 ) { Error( "Unable to split request header '%s' into tokens", lines[i].c_str() ); return( false ); } Debug( 4, "Got header '%s', value '%s'", parts[0].c_str(), parts[1].c_str() ); requestHeaders.insert( Headers::value_type( parts[0], parts[1] ) ); } if ( requestHeaders.find("CSeq") == requestHeaders.end() ) { Error( "No CSeq header found" ); return( false ); } Debug( 4, "Got sequence number %s", requestHeaders["CSeq"].c_str() ); uint32_t session = 0; if ( requestHeaders.find("Session") != requestHeaders.end() ) { Debug( 4, "Got session header, '%s', passing to session", requestHeaders["Session"].c_str() ); session = strtol( requestHeaders["Session"].c_str(), NULL, 16 ); } Headers responseHeaders; responseHeaders.insert( Headers::value_type( "CSeq", requestHeaders["CSeq"] ) ); if ( requestType == "OPTIONS" ) { responseHeaders.insert( Headers::value_type( "Public", "DESCRIBE, SETUP, PLAY, GET_PARAMETER, TEARDOWN" ) ); return( sendResponse( responseHeaders ) ); } else if ( requestType == "DESCRIBE" ) { FeedProvider *provider = validateRequestUrl( requestUrl ); if ( !provider ) { sendResponse( responseHeaders, "", 404, "Not Found" ); return( false ); } const VideoProvider *videoProvider = dynamic_cast<const VideoProvider *>(provider); int codec = AV_CODEC_ID_MPEG4; int width = videoProvider->width(); int height = videoProvider->height(); FrameRate frameRate = 15; //FrameRate frameRate = videoProvider->frameRate(); int bitRate = 90000; int quality = 70; std::string sdpFormatString = "v=0\r\n" "o=- %jd %jd IN IP4 %s\r\n" "s=ZoneMinder Stream\r\n" "i=Media Streamers\r\n" "c=IN IP4 0.0.0.0\r\n" "t=0 0\r\n" "a=control:*\r\n" "a=range:npt=0.000000-\r\n"; uint64_t now64 = time64(); char hostname[HOST_NAME_MAX] = ""; if ( gethostname( hostname, sizeof(hostname) ) < 0 ) Fatal( "Can't gethostname: %s", strerror(errno) ); std::string sdpString = stringtf( sdpFormatString, now64, now64, hostname ); if ( codec == AV_CODEC_ID_H264 ) { if ( provider->cl4ss() == "RawH264Input" ) { std::string encoderKey = H264Relay::getPoolKey( provider->identity(), width, height, frameRate, bitRate, quality ); if ( !(mEncoder = Encoder::getPooledEncoder( encoderKey )) ) { H264Relay *h264Relay = NULL; mEncoder = h264Relay = new H264Relay( provider->identity(), width, height, frameRate, bitRate, quality ); mEncoder->registerProvider( *provider ); Encoder::poolEncoder( mEncoder ); h264Relay->start(); } sdpString += mEncoder->sdpString( 1 ); // XXX - Should be variable responseHeaders.insert( Headers::value_type( "Content-length", stringtf( "%zd", sdpString.length() ) ) ); } else { std::string encoderKey = H264Encoder::getPoolKey( provider->identity(), width, height, frameRate, bitRate, quality ); if ( !(mEncoder = Encoder::getPooledEncoder( encoderKey )) ) { H264Encoder *h264Encoder = NULL; mEncoder = h264Encoder = new H264Encoder( provider->identity(), width, height, frameRate, bitRate, quality ); mEncoder->registerProvider( *provider ); Encoder::poolEncoder( mEncoder ); h264Encoder->start(); } sdpString += mEncoder->sdpString( 1 ); // XXX - Should be variable responseHeaders.insert( Headers::value_type( "Content-length", stringtf( "%zd", sdpString.length() ) ) ); } } else if ( codec == AV_CODEC_ID_MPEG4 ) { std::string encoderKey = MpegEncoder::getPoolKey( provider->identity(), width, height, frameRate, bitRate, quality ); if ( !(mEncoder = Encoder::getPooledEncoder( encoderKey )) ) { MpegEncoder *mpegEncoder = NULL; mEncoder = mpegEncoder = new MpegEncoder( provider->identity(), width, height, frameRate, bitRate, quality ); mEncoder->registerProvider( *provider ); Encoder::poolEncoder( mEncoder ); mpegEncoder->start(); } sdpString += mEncoder->sdpString( 1 ); // XXX - Should be variable responseHeaders.insert( Headers::value_type( "Content-length", stringtf( "%zd", sdpString.length() ) ) ); } return( sendResponse( responseHeaders, sdpString ) ); } else if ( requestType == "SETUP" ) { // These commands are handled by RTSP session so pass them on and send any required responses RtspSession *rtspSession = 0; if ( session ) { rtspSession = mRtspController->getSession( session ); } else { rtspSession = mRtspController->newSession( this, mEncoder ); } if ( rtspSession->recvRequest( requestType, requestUrl, requestHeaders, responseHeaders ) ) return( sendResponse( responseHeaders ) ); return( false ); } else if ( requestType == "PLAY" || requestType == "GET_PARAMETER" || requestType == "TEARDOWN" ) { // These commands are handled by RTSP session so pass them on and send any required responses RtspSession *rtspSession = 0; if ( session ) { rtspSession = mRtspController->getSession( session ); if ( rtspSession && rtspSession->recvRequest( requestType, requestUrl, requestHeaders, responseHeaders ) ) return( sendResponse( responseHeaders ) ); } return( sendResponse( responseHeaders, "", 454, "Session Not Found" ) ); } Error( "Unrecognised RTSP command '%s'", requestType.c_str() ); return( sendResponse( responseHeaders, "", 405, "Method not implemented" ) ); }
bool containsHeader(const Headers& headers, const std::string& name) { return findHeader(headers, name) != headers.end(); }
int main(int argc, char *argv[]) { // Parse command line arguments. boost::filesystem::path output("."); if (argc >= 2) output = argv[1]; // Create the output directory if required. if (!boost::filesystem::exists(output)) { cout << "Creating output directory " << output << '\n'; boost::filesystem::create_directories(output); } // Build the AST. Builder builder; buildAST(builder); // Determine implemented interfaces and child nodes. determineImplementedInterfaces(builder); determineChildNodes(builder); // Generate the code for the nodes. Headers headerFileNames; Headers sourceFileNames; for (Builder::Nodes::iterator it = builder.nodes.begin(); it != builder.nodes.end(); it++) { const std::string &name = it->first; Node &node = it->second; //cout << "- Generating \033[36;1m" << name << "\033[0m" << '\n'; std::string headerName = name + ".hpp"; std::string sourceName = name + ".cpp"; // Generate the header and source file. boost::filesystem::path hpath = output, spath = output; hpath /= headerName; spath /= sourceName; std::ofstream h(hpath.c_str()); std::ofstream s(spath.c_str()); h << "/* Automatically generated by ast-gen. DO NOT MODIFY. */\n"; h << "#pragma once\n"; h << "#include \"maxwell/ast/Node.hpp\"\n"; h << "#include \"maxwell/ast/nodes/interfaces.hpp\"\n"; h << "#include \"maxwell/ast/nodes/types.hpp\"\n"; if (node.parent != "Node") h << "#include \"maxwell/ast/nodes/" << node.parent << ".hpp\"\n"; h << '\n'; s << "/* Automatically generated by ast-gen. DO NOT MODIFY. */\n"; s << "#include \"maxwell/ast/nodes/" << headerName << "\"\n"; s << "#include \"maxwell/ast/Coder.hpp\"\n"; s << "#include <cstdio>\n"; s << "#include <sstream>\n"; s << "#include <stdexcept>\n"; s << "using ast::" << name << ";\n"; s << "using ast::NodePtr;\n"; s << "using ast::NodeVector;\n\n"; h << "namespace ast {\n\n"; h << "class Encoder;\n"; h << "class Decoder;\n\n"; h << "class " << name << " : public Node\n{\npublic:\n"; // Generate the constructor. h << "\t// constructor\n"; h << "\t" << name << "();\n\n"; s << name << "::" << name << "() : Node()"; for (Node::Interfaces::iterator it = node.interfaces.begin(); it != node.interfaces.end(); it++) { const Node& intf = **it; s << ",\n\tinterface" << intf.name << "(this)"; } s << " {}\n\n"; // Generate auxiliary functions. h << "\t// auxiliary functions\n"; h << "\tvirtual bool isKindOf(Kind k);\n"; h << "\tvirtual bool implements(Interface i);\n"; h << "\tvirtual std::string getClassName() const { return \"" << node.name << "\"; }\n"; h << "\tvirtual NodePtr copy();\n"; h << "\tvirtual bool equalTo(const NodePtr& o);\n"; h << "\tvirtual std::string describe(int depth = -1);\n"; h << '\n'; // isKindOf s << "bool " << name << "::isKindOf(Kind k) {\n"; s << "\tif (" << node.parent << "::isKindOf(k)) return true;\n"; s << "\treturn k == k" << node.name << ";\n"; s << "}\n\n"; // implements s << "bool " << name << "::implements(Interface i) {\n"; s << "\tif (" << node.parent << "::implements(i)) return true;\n"; for (Node::Interfaces::iterator it = node.interfaces.begin(); it != node.interfaces.end(); it++) { const Node& intf = **it; s << "\tif (i == k" << intf.intfName << ") return true;\n"; } s << "\treturn false;\n"; s << "}\n\n"; // copy s << "NodePtr " << name << "::copy() {\n"; s << "\tPtr c (new " << name << ");\n"; for (Node::Fields::iterator f = node.attributes.begin(); f != node.attributes.end(); f++) { s << "\tNode::copy(this->" << (*f).name << ", c->" << (*f).name << ");\n"; } s << "\treturn c;\n"; s << "}\n\n"; // equalTo s << "bool " << name << "::equalTo(const NodePtr& o) {\n"; s << "\tconst shared_ptr<" << node.name << ">& other = boost::dynamic_pointer_cast<" << node.name << ">(o);\n"; s << "\tif (!other) return false;\n"; for (Node::Fields::iterator fit = node.attributes.begin(); fit != node.attributes.end(); fit++) { Node::Field& f = *fit; s << "\tif (!equal(this->" << f.name << ", other->" << f.name << ")) return false;\n"; } s << "\treturn true;\n"; s << "}\n\n"; // describe s << "std::string " << name << "::describe(int depth) {\n"; s << "\tstd::stringstream str, b;\n"; if (node.descriptionBody.empty()) { s << "\tif (depth == 0) return \"" << name << "{…}\";\n"; s << "\tstr << \"" << name << "{\";\n"; for (Node::Fields::iterator fit = node.attributes.begin(); fit != node.attributes.end(); fit++) { Node::Field& f = *fit; // Don't print empty strings and arrays. s << "\t"; if (f.isString || f.isArray) s << "if (!this->" <<f.name<< ".empty()) "; if (f.isNode) s << "if (this->" << f.name << ") "; // Print the field name. s << "b << \"\\n \\033[1m" << f.name << "\\033[0m = "; // Print the actual data. if (f.isString) s << "\\033[33m\\\"\" << this->" << f.name << " << \"\\\"\\033[0m\";"; if (f.isBool) s << "\\033[34m\" << (this->" << f.name << " ? \"true\" : \"false\") << \"\\033[0m\";"; if (f.isInt) s << "\\033[35m\" << this->" << f.name << " << \"\\033[0m\";"; if (f.isNode) { if (f.ref) { s << "\\033[36m\" << this->" << f.name << ".id << \"\\033[0m\";"; } else { s << "\" << indent(this->" << f.name << "->describe(depth-1));"; } } if (f.isArray) s << "\" << indent(describeVector(this->" << f.name << ", depth-1));"; s << "\n"; } s << "\tstring bs = b.str();\n"; s << "\tif (!bs.empty()) str << bs << '\\n';\n"; s << "\tstr << \"}\";\n"; } else { string body(node.descriptionBody); boost::algorithm::replace_all(body, "\n", "\n\t\t"); s << "\t" << body << "\n"; } s << "\treturn str.str();\n"; s << "}\n\n"; s << '\n'; // Generate the accessor functions. h << "\t// accessor functions\n"; for (Node::Fields::iterator fit = node.attributes.begin(); fit != node.attributes.end(); fit++) { Node::Field& f = *fit; string ref = "const " + f.cpp_type + "&"; string upper = f.name; if (!upper.empty()) upper[0] = toupper(upper[0]); h << "\tvoid set" << upper << "(" << ref << " v);\n"; s << "void " << name << "::set" << upper << "(" << ref << " v) {\n"; vector<string> ifcomponents; string allowedNodes; string allowedInterfaces; for (unsigned i = 0; i < f.allowedNodes.size(); i++) { ifcomponents.push_back("!v->isKindOf(k" + f.allowedNodes[i] + ")"); if (!allowedNodes.empty()) allowedNodes += ", "; allowedNodes += f.allowedNodes[i]; } for (unsigned i = 0; i < f.allowedInterfaces.size(); i++) { ifcomponents.push_back("!v->implements(k" + builder.interfaces[f.allowedInterfaces[i]].intfName + ")"); if (!allowedInterfaces.empty()) allowedInterfaces += ", "; allowedInterfaces += f.allowedInterfaces[i]; } if (!ifcomponents.empty()) { s << "\tif (v"; for (unsigned i = 0; i < ifcomponents.size(); i++) { s << " && " << ifcomponents[i]; } s << ") {\n"; s << "\t\tthrow std::runtime_error(\"'" << f.name << "' of \" + id.str() + \" needs to be of kind {" << allowedNodes << "} or implement interface {" << allowedInterfaces << "}, got \" + v->getClassName() + \" (\" + v->getId().str() + \") instead.\");\n"; s << "\t}\n"; } if (f.ref) { s << "\tif (!v && " << f.name << ") {\n"; s << "\t\tmodify(\"" << f.name << "\");\n"; s << "\t\t" << f.name << ".reset();\n"; s << "\t}\n"; s << "\tif (!" << f.name << " || v->getId() != " << f.name << ".id) {\n"; } else { s << "\tif (!equal(v, " << f.name << ")) {\n"; } s << "\t\tmodify(\"" << f.name << "\");\n"; if (f.ref) { s << "\t\t" << f.name << ".set(v);\n"; } else { s << "\t\t" << f.name << " = v;\n"; } s << "\t}\n"; s << "}\n\n"; // special setter for references if (f.ref) { h << "\tvoid set" << upper << "(const NodeId& v);\n"; s << "void " << name << "::set" << upper << "(const NodeId& v) {\n"; s << "\tif (v != " << f.name << ".id) {\n"; s << "\t\tmodify(\"" << f.name << "\");\n"; s << "\t\t" << f.name << ".set(v);\n"; s << "\t}\n"; s << "}\n\n"; } h << "\t" << ref << " get" << upper << "(bool required = true);\n\n"; s << ref << " " << name << "::get" << upper << "(bool required) {\n"; s << "\tconst " << f.cpp_type << "& v = "; if (f.ref) { s << f.name << ".get(repository);\n"; } else { s << f.name << ";\n"; } if (f.isNode) { s << "\tif (required && !v) {\n"; s << "\t\tthrow std::runtime_error(\"Node \" + getId().str() + \" is required to have " << f.name << " set to a non-null value.\");\n"; s << "\t}\n"; } else if (f.isString) { s << "\tif (required && v.empty()) {\n"; s << "\t\tthrow std::runtime_error(\"Node \" + getId().str() + \" is required to have a non-empty string " << f.name << " set.\");\n"; s << "\t}\n"; } s << "\treturn v;\n"; s << "}\n\n\n"; } // Generate the encode() and decode() function. h << "\t// encoding and decoding\n"; h << "\tvirtual void encode(Encoder& e);\n"; h << "\tvirtual void decode(Decoder& d);\n"; h << '\n'; s << "void " << name << "::encode(Encoder& e) {\n"; s << "\te.encode(this->range);\n"; s << "\te.encode(this->referenceRange);\n"; for (Node::Fields::iterator f = node.attributes.begin(); f != node.attributes.end(); f++) { s << "\te.encode(this->" << (*f).name << ");\n"; } s << "}\n\n"; s << "void " << name << "::decode(Decoder& d) {\n"; s << "\td.decode(this->range);\n"; s << "\td.decode(this->referenceRange);\n"; for (Node::Fields::iterator f = node.attributes.begin(); f != node.attributes.end(); f++) { s << "\td.decode(this->" << (*f).name << ");\n"; } s << "}\n\n"; s << '\n'; // Generate the hierarchy functions. h << "\t// hierarchy functions\n"; h << "\tvirtual void updateHierarchyOfChildren();\n"; h << "\tvirtual const NodePtr& resolvePath(const std::string& path);\n"; // updateHierarchy s << "void " << name << "::updateHierarchyOfChildren() {\n"; for (Node::Fields::iterator fit = node.attributes.begin(); fit != node.attributes.end(); fit++) { Node::Field& f = *fit; if (f.isNode && !f.ref) { s << "\tif (this->"<<f.name<<") this->"<<f.name<<"->updateHierarchy(id + \""<<f.name<<"\", repository, this);\n"; } else if (f.isNodeArray) { s << "\tfor (unsigned i = 0; i < this->"<<f.name<<".size(); i++) {\n"; s << "\t\tchar buf[32]; snprintf(buf, 31, \"%i\", i);\n"; s << "\t\tthis->"<<f.name<<"[i]->updateHierarchy((id + \""<<f.name<<"\") + buf, repository, this);\n"; s << "\t}\n"; } } s << "}\n\n"; // resolvePath s << "const NodePtr& " << name << "::resolvePath(const std::string& path) {\n"; FieldNames fields, arrayFields; for (Node::Fields::iterator fit = node.attributes.begin(); fit != node.attributes.end(); fit++) { Node::Field& f = *fit; if (f.isNode) { fields.insert(f.name); } else if (f.isNodeArray) { fields.insert(f.name); arrayFields.insert(f.name); } } if (!fields.empty()) { s << "\tsize_t size = path.size();\n"; generateResolvePathBody(s, fields, arrayFields, 1); } s << "\tthrow std::runtime_error(\"Node path '\" + path + \"' does not point to a node or array of nodes.\");\n"; s << "}\n\n"; // getChildren if (!node.children.empty()) { h << "\tvirtual NodeVector getChildren();\n"; s << "NodeVector " << name << "::getChildren() {\n"; s << "\tNodeVector v;\n"; for (Node::Children::iterator c = node.children.begin(); c != node.children.end(); c++) { Node::Field& f = **c; if (f.isNode) { string upper = (char)toupper(f.name[0]) + f.name.substr(1); s << "\tif (const NodePtr& n = this->get" << upper << "(false)) v.push_back(n);\n"; } else if (f.isArray) { s << "\tv.insert(v.end(), this->" << f.name << ".begin(), this->" << f.name << ".end());\n"; } } s << "\treturn v;\n"; s << "}\n\n"; } h << '\n'; // Generate the interface accessors. if (!node.interfaces.empty()) { h << "\t// interfaces\n"; for (Node::Interfaces::iterator it = node.interfaces.begin(); it != node.interfaces.end(); it++) { const Node& intf = **it; h << "\tvirtual " << intf.intfName << "* as" << intf.name << "() { return &this->interface" << intf.name << "; }\n"; } h << "\n"; } // Generate boost::shared_ptr convenience typedef. h << "\t// shared_ptr convenience\n"; h << "\ttypedef boost::shared_ptr<" << node.name << "> Ptr;\n"; h << "\ttemplate<typename T> static Ptr from(const T& n) { return boost::dynamic_pointer_cast<" << node.name << ">(n); }\n"; h << "\ttemplate<typename T> static Ptr needFrom(const T& n) {\n"; h << "\t\tPtr r = boost::dynamic_pointer_cast<" << node.name << ">(n);\n"; h << "\t\tif (!r)\n"; h << "\t\t\tthrow std::runtime_error(\"Node \" + n->getId().str() + \" (a \" + n->getClassName() + \") cannot be dynamically cast to " << node.name << ".\");\n"; h << "\t\treturn r;\n"; h << "\t}\n"; h << '\n'; h << "protected:\n"; for (Node::Fields::iterator f = node.attributes.begin(); f != node.attributes.end(); f++) { if ((*f).ref) { h << "\tNodeRef " << (*f).name << ";\n"; } else { h << "\t" << (*f).cpp_type << " " << (*f).name << ";\n"; } } if (!node.interfaces.empty()) { h << "\n\t// interfaces\n"; for (Node::Interfaces::iterator it = node.interfaces.begin(); it != node.interfaces.end(); it++) { const Node& intf = **it; h << "\t" << intf.intfName << "Impl<" << node.name << "> interface" << intf.name << ";\n"; } } h << "};\n\n"; h << "} // namespace ast\n"; headerFileNames.push_back(headerName); sourceFileNames.push_back(sourceName); } // Generate the header file containing general typedefs. makeTypesHeader(output, builder); makeNodesHeader(output, builder, headerFileNames); makeInterfacesHeader(output, builder); // Generate the base header file for ast::Node which implements default interface accessors. makeBaseNodeHeader(output, builder); // Generate the header file aggregating all AST things. boost::filesystem::path ahpath = output; ahpath /= "ast.hpp"; ofstream ah(ahpath.c_str()); ah << "/* Automatically generated by ast-gen. DO NOT MODIFY. */\n"; ah << "#pragma once\n\n"; ah << "#include \"maxwell/ast/nodes/types.hpp\"\n"; ah << "#include \"maxwell/ast/nodes/nodes.hpp\"\n"; ah << "#include \"maxwell/ast/nodes/interfaces.hpp\"\n"; return 0; }