bool RequestHandler::parsePutFileParams()

in host/cxpslib/requesthandler.cpp [663:852]


bool RequestHandler::parsePutFileParams(boost::system::error_code const & error, size_t bytesTransferred)
{
    cancelTimeout();

    // putfile post params have following format
    //
    //    token=value[&token=value]*&data=
    //
    // data= must be the last parameter (well it will be treated as if it were last even if it is not)
    // set up things that might need to be done on exit

    ON_BLOCK_EXIT(boost::bind(&RequestHandler::clearAsyncQueued, this));

    SCOPE_GUARD sessionLogoutGuard = MAKE_SCOPE_GUARD(boost::bind(&RequestHandler::sessionLogout, this));
    SCOPE_GUARD logXferGuard = MAKE_SCOPE_GUARD(boost::bind(&RequestHandler::logXferPutFile, this, (char const*)0));
    SCOPE_GUARD resetGuard = MAKE_SCOPE_GUARD(boost::bind(&RequestHandler::reset, this));
    SCOPE_GUARD replyAbortGuard = MAKE_SCOPE_GUARD(boost::bind(&HttpTraits::reply_t::abort, m_reply.get()));
    SCOPE_GUARD logRequestFailedGuard = MAKE_SCOPE_GUARD(boost::bind(&RequestHandler::logRequestFailed, this));
    bool wasSessionGuardDismissed = false;

    try {
        timeStop();
        if (m_connection->isTimedOut()) {
            return false;
        }

        if (!error) {
            m_requestTelemetryData.CompletingNwRead(bytesTransferred);

            m_requestInfo.m_bufferLen = bytesTransferred;
            m_putFileInfo.m_totalBytesLeftToRead -= m_requestInfo.m_bufferLen;
            m_putFileInfo.m_bytesProcessed += m_putFileInfo.m_idx;
            m_putFileInfo.m_idx = 0;
            while (m_putFileInfo.m_bytesProcessed < m_requestInfo.m_dataSize) {
                if (m_putFileInfo.m_idx < m_requestInfo.m_bufferLen) {
                    if (m_putFileInfo.m_readingToken) {
                        while (m_putFileInfo.m_idx < m_requestInfo.m_bufferLen && '=' != m_putFileInfo.m_buffer[m_putFileInfo.m_idx]
                               && m_putFileInfo.m_bytesChecked < MAX_TOKEN_BYTES_TO_CHECK) {
                            m_putFileInfo.m_token += m_putFileInfo.m_buffer[m_putFileInfo.m_idx];
                            ++m_putFileInfo.m_idx;
                            ++m_putFileInfo.m_bytesChecked;
                        }

                        if (m_putFileInfo.m_bytesChecked >= MAX_TOKEN_BYTES_TO_CHECK) {
                            m_requestTelemetryData.SetRequestFailure(RequestFailure_PutFileNoParam);

                            std::string msg("did not find parameter with in check range ");
                            msg += boost::lexical_cast<std::string>(MAX_TOKEN_BYTES_TO_CHECK);
                            badRequest(AT_LOC, msg.c_str());
                            return false;
                        }

                        if (m_putFileInfo.m_idx <  m_requestInfo.m_bufferLen) {
                            if ('=' == m_putFileInfo.m_buffer[m_putFileInfo.m_idx]) {
                                ++m_putFileInfo.m_idx;
                                m_putFileInfo.m_bytesChecked = 0;
                                m_putFileInfo.m_readingToken = false;

                                if (HTTP_PARAM_TAG_DATA == m_putFileInfo.m_token) {
                                    // have all params dimiss all guards and get file data portion
                                    logXferGuard.dismiss();
                                    resetGuard.dismiss();
                                    replyAbortGuard.dismiss();
                                    logRequestFailedGuard.dismiss();
                                    sessionLogoutGuard.dismiss();
                                    wasSessionGuardDismissed = true;
                                    putFileGetData();
                                    return true;
                                }
                            }
                        }
                    } else {
                        while (m_putFileInfo.m_idx < m_requestInfo.m_bufferLen && '&' != m_putFileInfo.m_buffer[m_putFileInfo.m_idx]
                               && m_putFileInfo.m_bytesChecked < MAX_VALUE_BYTES_TO_CHECK) {
                            m_putFileInfo.m_value += m_putFileInfo.m_buffer[m_putFileInfo.m_idx];
                            ++m_putFileInfo.m_idx;
                            ++m_putFileInfo.m_bytesChecked;
                        }

                        if (m_putFileInfo.m_bytesChecked >= MAX_VALUE_BYTES_TO_CHECK) {
                            m_requestTelemetryData.SetRequestFailure(RequestFailure_PutFileNoParamVal);

                            std::string msg("did not find value for  ");
                            msg += m_putFileInfo.m_token;
                            msg += " with in check range ";
                            msg += boost::lexical_cast<std::string>(MAX_VALUE_BYTES_TO_CHECK);
                            badRequest(AT_LOC, msg.c_str());
                            return false;
                        }

                        if (m_putFileInfo.m_idx <  m_requestInfo.m_bufferLen) {
                            if ('&' == m_putFileInfo.m_buffer[m_putFileInfo.m_idx]) {
                                ++m_putFileInfo.m_idx;
                                m_putFileInfo.m_bytesChecked = 0;
                                m_requestInfo.m_params.insert(std::make_pair(m_putFileInfo.m_token, urlDecode(m_putFileInfo.m_value)));
                                m_putFileInfo.m_token.clear();
                                m_putFileInfo.m_value.clear();
                                m_putFileInfo.m_readingToken = true;
                            }
                        }
                    }
                } else {
                    if (m_putFileInfo.m_totalBytesLeftToRead > 0) {
                        try {
                            // still working on params dismiss all guards
                            CXPS_LOG_MONITOR(MONITOR_LOG_LEVEL_2,
                                             "PARSING POST PARAMS\t"
                                             << "(sid: " << m_sessionId << ")\t"
                                             << m_hostId << '\t'
                                             << m_connection->endpointInfoAsString() << '\t'
                                             << getRequestInfoAsString(true)
                                             << ": need to read more data from socket");
                            logXferGuard.dismiss();
                            resetGuard.dismiss();
                            replyAbortGuard.dismiss();
                            logRequestFailedGuard.dismiss();
                            sessionLogoutGuard.dismiss();
                            m_putFileInfo.m_buffer = &m_buffer[0];
                            if (!m_connection->isTimedOut()) {
                                timeStart();
                                setTimeout();

                                m_requestTelemetryData.StartingNwRead();

                                m_connection->asyncRead(&m_buffer[0],
                                                        (m_putFileInfo.m_totalBytesLeftToRead < m_buffer.size() ? m_putFileInfo.m_totalBytesLeftToRead : m_buffer.size()),
                                                        boost::bind(&RequestHandler::parsePutFileParams,
                                                                    shared_from_this(),
                                                                    boost::asio::placeholders::error,
                                                                    boost::asio::placeholders::bytes_transferred));
                                return true;
                            }
                        } catch (std::exception const& e) {
                            m_requestTelemetryData.SetRequestFailure(RequestFailure_PutFileParamsReadTimedOut);

                            CXPS_LOG_ERROR(AT_LOC << "(sid: " << m_sessionId << ") "
                                           << m_connection->endpointInfoAsString()
                                           << ": timed out reading putfile parameters\n");
                            badRequest(AT_LOC, "timed out reading putfile parameters\n");
                            return false;
                        }
                    } else {
                        m_requestTelemetryData.SetRequestFailure(RequestFailure_PutFileInvalidParams);
                        badRequest(AT_LOC, "invalid parameters\n");
                        return false;
                    }
                }
            }
        } else {
            m_requestTelemetryData.SetRequestFailure(RequestFailure_NwReadFailure);

            std::stringstream errStr;
            errStr << m_putFileInfo.m_name.string() << " socket error: " << error;
            CXPS_LOG_ERROR(AT_LOC << "(sid: " << m_sessionId << ") "
                           << m_connection->endpointInfoAsString()
                           << ": " << errStr.str());
        }
    } catch (std::exception const& e) {
        if (!wasSessionGuardDismissed)
        {
            // Otherwise, set and also logged by SessionLogOut() at the putFileGetData().
            m_requestTelemetryData.SetRequestFailure(RequestFailure_PutFileParamsFailed);
        }

        std::stringstream errStr;
        errStr << m_putFileInfo.m_name.string() << " error: " << e.what();
        CXPS_LOG_ERROR(AT_LOC << "(sid: " << m_sessionId << ") "
                       << m_connection->endpointInfoAsString() << ": "
                       << errStr.str());
        sendError(ResponseCode::RESPONSE_INTERNAL_ERROR, errStr.str().c_str(), errStr.str().size());
        logRequestDone("(failed)");
        m_connection->disconnect();
    } catch (...) {
        if (!wasSessionGuardDismissed)
        {
            // Otherwise, set and also logged by SessionLogOut() at the putFileGetData().
            m_requestTelemetryData.SetRequestFailure(RequestFailure_PutFileParamsFailed);
        }

        std::stringstream errStr;
        errStr << m_putFileInfo.m_name.string() << " unknown exception";
        CXPS_LOG_ERROR(AT_LOC << "(sid: " << m_sessionId << ") "
                       << m_connection->endpointInfoAsString() << ": "
                       << errStr.str());
        sendError(ResponseCode::RESPONSE_INTERNAL_ERROR, errStr.str().c_str(), errStr.str().size());
        logRequestDone("(failed)");
        m_connection->disconnect();
    }
    return false;
}