コード例 #1
0
ファイル: rtp_reader.c プロジェクト: 4leavedclover/userland
/**************************************************************************//**
 * Creates and populates a parameter list from a URI structure.
 * The list does not copy the parameter strings themselves, so the URI structure
 * must be retained (and its parameters unmodified) while the list is in use.
 *
 * @param uri  The URI containing the parameters.
 * @return  List created from the parameters of the URI, or NULL on error.
 */
static VC_CONTAINERS_LIST_T *fill_parameter_list(VC_URI_PARTS_T *uri)
{
   uint32_t num_parameters = vc_uri_num_queries(uri);
   VC_CONTAINERS_LIST_T *parameters;
   uint32_t ii;

   parameters = vc_containers_list_create(num_parameters, sizeof(PARAMETER_T), (VC_CONTAINERS_LIST_COMPARATOR_T)parameter_comparator);
   if (!parameters)
      return NULL;

   for (ii = 0; ii < num_parameters; ii++)
   {
      PARAMETER_T param;

      vc_uri_query(uri, ii, &param.name, &param.value);
      if (!vc_containers_list_insert(parameters, &param, false))
      {
         vc_containers_list_destroy(parameters);
         return NULL;
      }
   }

#ifdef RTP_DEBUG
   vc_containers_list_validate(parameters);
#endif

   return parameters;
}
コード例 #2
0
ファイル: io_http.c プロジェクト: DSkywalk/RetroArch
/**************************************************************************//**
 * Reads an HTTP response and parses it into headers and content.
 * The headers and content remain stored in the comms buffer, but referenced
 * by the module's header list. Content uses a special header name that cannot
 * occur in the real headers.
 *
 * @param p_ctx   The HTTP reader context.
 * @return  The resulting status of the function.
 */
static VC_CONTAINER_STATUS_T io_http_read_response(VC_CONTAINER_IO_T *p_ctx)
{
   VC_CONTAINER_IO_MODULE_T *module = p_ctx->module;
   char *next_read = module->comms_buffer;
   size_t space_available = sizeof(module->comms_buffer) - 1; /* Allow for a NUL */
   char *ptr = next_read;
   bool end_response = false;
   HTTP_HEADER_T header;
   const char endstr[] = "\r\n\r\n";
   int endcount = sizeof(endstr) - 1;
   int endchk = 0;

   vc_containers_list_reset(module->header_list);

   /* Response status line doesn't need to be stored, just checked */
   header.name = NULL;
   header.value = next_read;

   /*
    * We need to read just a byte at a time to make sure that we just read the HTTP response and
    * no more. For example, if a GET operation was requested the file being fetched will also
    * be waiting to be read on the socket.
    */

   while (space_available)
   {
      if (io_http_read_from_net(p_ctx, next_read, 1) != 1)
         break;

      next_read++;
      space_available--;

      if (next_read[-1] == endstr[endchk])
      {
         if (++endchk == endcount)
            break;
      }
      else
         endchk = 0;
   }
   if (!space_available)
   {
      LOG_ERROR(NULL, "comms buffer too small for complete HTTP message (%d)",
                sizeof(module->comms_buffer));
      return VC_CONTAINER_ERROR_CORRUPTED;
   }

   *next_read = '\0';

   if (endchk == endcount)
   {
      if (ENABLE_HTTP_EXTRA_LOGGING)
         LOG_DEBUG(NULL, "READ FROM SERVER: %d bytes\n%s\n-----------------------------------------",
                   sizeof(module->comms_buffer) - 1 - space_available, module->comms_buffer);

      while (!end_response && ptr < next_read)
      {
         switch (*ptr)
         {
            case ':':
               if (header.value)
               {
                  /* Just another character in the value */
                  ptr++;
               } else {
                  /* End of name, expect value next */
                  *ptr++ = '\0';
                  header.value = ptr;
               }
               break;

            case '\n':
               if (header.value)
               {
                  /* End of line while parsing the value part of the header, add name/value pair to list */
                  *ptr++ = '\0';
                  header.value = io_http_trim(header.value);
                  if (header.name)
                  {
                     if (!vc_containers_list_insert(module->header_list, &header, false))
                     {
                        LOG_ERROR(NULL, "HTTP: Failed to add <%s> header to list", header.name);
                        return VC_CONTAINER_ERROR_OUT_OF_MEMORY;
                     }
                  } else {
                     /* Check response status line */
                     if (!io_http_successful_response_status(header.value))
                        return VC_CONTAINER_ERROR_FORMAT_INVALID;
                  }
                  /* Ready for next header */
                  header.name  = ptr;
                  header.value = NULL;
               } else {
                  /* End of line while parsing the name of a header */
                  *ptr++ = '\0';
                  if (*header.name && *header.name != '\r')
                  {
                     /* A non-empty name is invalid, so fail */
                     LOG_ERROR(NULL, "HTTP: Invalid name in header - no colon:\n%s", header.name);
                     return VC_CONTAINER_ERROR_FORMAT_INVALID;
                  }

                  /* An empty name signifies the end of the HTTP response */
                  end_response = true;
               }
               break;

            default:
               /* Just another character in either the name or the value */
               ptr++;
         }
      }
   }

   if (!space_available && !end_response)
   {
      /* Ran out of buffer space */
      LOG_ERROR(NULL, "HTTP: Response header section too big");
      return VC_CONTAINER_ERROR_FORMAT_INVALID;
   }

   return p_ctx->status;
}