Esempio n. 1
0
int CWebServer::CreateMemoryDownloadResponse(IHTTPRequestHandler *handler, struct MHD_Response *&response)
{
  if (handler == NULL)
    return MHD_NO;

  const HTTPRequest &request = handler->GetRequest();
  const HTTPResponseDetails &responseDetails = handler->GetResponseDetails();
  HttpResponseRanges responseRanges = handler->GetResponseData();

  // check if the response is completely empty
  if (responseRanges.empty())
    return CreateMemoryDownloadResponse(request.connection, NULL, 0, false, false, response);

  // check if the response contains more ranges than the request asked for
  if ((request.ranges.IsEmpty() && responseRanges.size() > 1) ||
     (!request.ranges.IsEmpty() && responseRanges.size() > request.ranges.Size()))
  {
    CLog::Log(LOGWARNING, "CWebServer: response contains more ranges (%d) than the request asked for (%d)", (int)responseRanges.size(), (int)request.ranges.Size());
    return SendErrorResponse(request.connection, MHD_HTTP_INTERNAL_SERVER_ERROR, request.method);
  }

  // if the request asked for no or only one range we can simply use MHDs memory download handler
  // we MUST NOT send a multipart response
  if (request.ranges.Size() <= 1)
  {
    CHttpResponseRange responseRange = responseRanges.front();
    // check if the range is valid
    if (!responseRange.IsValid())
    {
      CLog::Log(LOGWARNING, "CWebServer: invalid response data with range start at %" PRId64 " and end at %" PRId64, responseRange.GetFirstPosition(), responseRange.GetLastPosition());
      return SendErrorResponse(request.connection, MHD_HTTP_INTERNAL_SERVER_ERROR, request.method);
    }

    const void* responseData = responseRange.GetData();
    size_t responseDataLength = static_cast<size_t>(responseRange.GetLength());

    switch (responseDetails.type)
    {
    case HTTPMemoryDownloadNoFreeNoCopy:
      return CreateMemoryDownloadResponse(request.connection, responseData, responseDataLength, false, false, response);

    case HTTPMemoryDownloadNoFreeCopy:
      return CreateMemoryDownloadResponse(request.connection, responseData, responseDataLength, false, true, response);

    case HTTPMemoryDownloadFreeNoCopy:
      return CreateMemoryDownloadResponse(request.connection, responseData, responseDataLength, true, false, response);

    case HTTPMemoryDownloadFreeCopy:
      return CreateMemoryDownloadResponse(request.connection, responseData, responseDataLength, true, true, response);

    default:
      return SendErrorResponse(request.connection, MHD_HTTP_INTERNAL_SERVER_ERROR, request.method);
    }
  }

  return CreateRangedMemoryDownloadResponse(handler, response);
}
Esempio n. 2
0
TEST(TestHttpResponseRange, SetData)
{
  const uint64_t validFirstPosition = 1;
  const uint64_t validLastPosition = 2;
  const uint64_t validLength = validLastPosition - validFirstPosition + 1;
  const char* validData = "test";
  const void* invalidData = DefaultData;
  const size_t validDataLength = strlen(validData);
  const size_t invalidDataLength = 1;

  CHttpResponseRange range;
  EXPECT_EQ(DefaultData, range.GetData());
  EXPECT_FALSE(range.IsValid());

  range.SetData(invalidData);
  EXPECT_EQ(invalidData, range.GetData());
  EXPECT_FALSE(range.IsValid());

  range.SetData(validData);
  EXPECT_EQ(validData, range.GetData());
  EXPECT_FALSE(range.IsValid());

  range.SetData(invalidData, 0);
  EXPECT_EQ(validData, range.GetData());
  EXPECT_FALSE(range.IsValid());

  range.SetData(invalidData, invalidDataLength);
  EXPECT_EQ(invalidData, range.GetData());
  EXPECT_FALSE(range.IsValid());

  range.SetData(validData, validDataLength);
  EXPECT_EQ(validData, range.GetData());
  EXPECT_EQ(0U, range.GetFirstPosition());
  EXPECT_EQ(validDataLength - 1, range.GetLastPosition());
  EXPECT_EQ(validDataLength, range.GetLength());
  EXPECT_TRUE(range.IsValid());

  range.SetData(invalidData, 0, 0);
  EXPECT_EQ(invalidData, range.GetData());
  EXPECT_FALSE(range.IsValid());

  range.SetData(validData, validFirstPosition, validLastPosition);
  EXPECT_EQ(validData, range.GetData());
  EXPECT_EQ(validFirstPosition, range.GetFirstPosition());
  EXPECT_EQ(validLastPosition, range.GetLastPosition());
  EXPECT_EQ(validLength, range.GetLength());
  EXPECT_TRUE(range.IsValid());
}