⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 50a731bed5b9001c180780c9bab1766d

📁 基于UCOS的嵌入式系统的应用
💻
📖 第 1 页 / 共 3 页
字号:
    return -1;
      
  if((socket = accept(listen_socket,(struct sockaddr*)&rem,&len)) < 0)
  {
    //fprintf(stderr, "[http_handle_accept] accept failed (%d)\n", socket);
    return socket;
  }

  (conn+i)->fd = socket;
  (conn+i)->activity_time = alt_nticks();

  return ret_code;
}

/*
 * http_read_line()
 * 
 * This routine will scan the RX data buffer for a newline, allowing us to
 * parse an in-coming HTTP request line-by-line.
 */
int http_read_line(http_conn* conn)
{
  alt_u8* lf_addr;
  int ret_code = 0;

  /* Find the Carriage return which marks the end of the header */
  lf_addr = strchr(conn->rx_rd_pos, '\n');
  
  if (lf_addr == NULL)
  {
    ret_code = -1;
  }
  else
  {
    /* 
     * Check that the line feed has a matching CR, if so zero that
     * else zero the LF so we can use the string searching functions.
     */
    if ((lf_addr > conn->rx_buffer) && (*(lf_addr-1) == '\r'))
    {
      *(lf_addr-1) = 0;
    }

    *lf_addr = 0;
    conn->rx_rd_pos = lf_addr+1;
  }

  return ret_code;
}

/*
 * http_process_headers()
 * 
 * This routine looks for HTTP header commands, specified by a ":" character.
 * We will look for "Connection: Close" and "Content-length: <len>" strings. 
 * A more advanced server would parse far more header information.
 * 
 * This routine should be modified in the future not to use strtok() as its
 * a bit invasive and is not thread-safe!
 */
int http_process_headers(http_conn* conn)
{
  alt_u8* option;
  alt_u8* orig_read_pos = conn->rx_rd_pos;
  alt_u8* temp;
  
  /* Skip the next section we'll chop with strtok(). Perl for Nios, anyone? */
  if( (temp = strstr(conn->rx_rd_pos, ":")) )
  {
    conn->rx_rd_pos = temp + 1;
  }
  else
  {
    return -1;
  }
    
  option = strtok(orig_read_pos, ":");

  if(stricmp(option,"Connection") == 0)
  {
    alt_u8 temp = *(option + 17);
    *(option + 17) = 0;
    
    if(stricmp((option+12), "close") == 0)
    {
      conn->close = 1;
    }
    *(option + 17) = temp;
  }
  else if (stricmp(option, "Content-Length") == 0)
  {
   conn->content_length = atoi(option+16);
  }

  return 0;
}

/*
 * http_process_request()
 * 
 * This routine parses the beginnings of an HTTP request to extract the
 * command, version, and URI. Unsupported commands/versions/etc. will cause
 * us to error out drop the connection.
 */
int http_process_request(http_conn* conn)
{
  alt_u8* uri = 0;
  alt_u8* version = 0;
  alt_u8* temp = 0;
  if( (temp = strstr(conn->rx_rd_pos, "GET")) )
  {
    conn->action = GET;
    conn->rx_rd_pos = temp;
  }
  else if( (temp = strstr(conn->rx_rd_pos, "POST")) )
  {
    conn->action = POST;
    conn->rx_rd_pos = temp;
  }
  else
  {
    //fprintf(stderr, "Unsupported (for now) request\n");
    conn->action = UNKNOWN;
    return -1;
  }
  
  /* First space char separates action from URI */
  if( (conn->rx_rd_pos = strstr(conn->rx_rd_pos, " ")) )
  {
    conn->rx_rd_pos++;
    uri = conn->rx_rd_pos;
  }
  else
  {
    return -1;
  }
    
  /* Second space char separates URI from HTTP version. */
  if( (conn->rx_rd_pos = strstr(conn->rx_rd_pos, " ")) )
  {
    *conn->rx_rd_pos = 0;
    conn->rx_rd_pos++;
    version = conn->rx_rd_pos;
  }
  else
  {
    return -1;
  }
  
  /* Is this a HTTP version we support? */
  if ((version == NULL) || (strncmp(version, "HTTP/", 5) != 0))
  {
    return -1;
  }

  if (!isdigit(version[5]) || version[6] != '.' || !isdigit(version[7]))
  {
    return -1;
  }

  /* Before v1.1 we close the connection after responding to the request */
  if ( (((version[5] - '0')*10) + version[7] - '0') < 11)
  {
    conn->close = 1;
  }

  strcpy(conn->uri, uri);
  return 0;
}

/*
 * http_send_file_chunk()
 * 
 * This routine will send the next chunk of a file during an open HTTP session
 * where a file is being sent back to the client. This routine is called 
 * repeatedly until the file is completely sent, at which time the connection
 * state will go to "COMPLETE". Doing this rather than sending the entire
 * file allows us (in part) to multiplex between connections "simultaneously".
 */
int http_send_file_chunk(http_conn* conn)
{
  int chunk_sent = 0, ret_code = 0, file_chunk_size = 0, result = 0;
  alt_u8* tx_ptr;
  
  if(conn->data_sent < conn->file_length)
  {
    file_chunk_size = hyread(conn->tx_buffer, 1, 
      MIN(HTTP_TX_BUF_SIZE, (conn->file_length - conn->data_sent)), 
      conn->file_handle);
    
    tx_ptr = conn->tx_buffer;
    
    while(chunk_sent < file_chunk_size)
    {
      result = send(conn->fd, tx_ptr, file_chunk_size, MSG_DONTWAIT);
      
      /* Error - get out of here! */
      if(result < 0)
      {
        //fprintf(stderr, "[http_send_file] file send returned %d\n", result);
        ALT_DEBUG_ASSERT(1);
        conn->state = RESET;
        return result;
      }

      /*
       * No errors, but the number of bytes sent might be less than we wanted.
       */
      else
      {
        conn->activity_time = alt_nticks();
        chunk_sent += result;
        conn->data_sent += result;
        tx_ptr += result;
        file_chunk_size -= result;
      }
    } /* while(chunk_sent < file_chunk_size) */
  } /* if(conn->data_sent < conn->file_length) */
  
  /* 
   * We managed to send all of the file contents to the IP stack successfully.
   * At this point we can mark our connection info as complete.
   */
  if(conn->data_sent >= conn->file_length)
  {
    conn->state = COMPLETE;
  }

  return ret_code;
}

/*
 * http_send_file_header()
 *
 * Construct and send an HTTP header describing the now-opened file that is
 * about to be sent to the client.
 */
int http_send_file_header(http_conn* conn, const alt_u8* name, int code)
{
  int     result = 0, ret_code = 0;
  alt_u8* tx_wr_pos = conn->tx_buffer;
  fpos_t  end, start;
  const alt_u8* ext = strchr(name, '.');

  tx_wr_pos += sprintf(tx_wr_pos, HTTP_VERSION_STRING);

  switch(code)
  {
    /* HTTP Code: "200 OK\r\n" (we have opened the file successfully) */
    case HTTP_OK:
    {
      tx_wr_pos += sprintf(tx_wr_pos, HTTP_OK_STRING);
      break;
    }
    /* HTTP Code: "404 Not Found\r\n" (couldn't find requested file) */
    case HTTP_NOT_FOUND:
    {
      tx_wr_pos += sprintf(tx_wr_pos, HTTP_NOT_FOUND_STRING);
      break;
    }
    default:
    {
      //fprintf(stderr, "[http_send_file_header] Invalid HTTP code: %d\n", code);
      conn->state = RESET;
      return -1;
      break;
    }
  }

  /* Handle the various content types */
  tx_wr_pos += sprintf(tx_wr_pos, HTTP_CONTENT_TYPE);

  if (!strcasecmp(ext, ".html"))
  {
    tx_wr_pos += sprintf(tx_wr_pos, HTTP_CONTENT_TYPE_HTML);
  }
  else if (!strcasecmp(ext, ".jpg"))
  {
    tx_wr_pos += sprintf(tx_wr_pos, HTTP_CONTENT_TYPE_JPG);
  }
  else if (!strcasecmp(ext, ".gif"))
  {
    tx_wr_pos += sprintf(tx_wr_pos, HTTP_CONTENT_TYPE_GIF);
  }
  else if (!strcasecmp(ext, ".js"))
  {
    tx_wr_pos += sprintf(tx_wr_pos, HTTP_CONTENT_TYPE_JS);
  }
  else if (!strcasecmp(ext, ".css"))
  {
    tx_wr_pos += sprintf(tx_wr_pos, HTTP_CONTENT_TYPE_CSS);
  }
  else if (!strcasecmp(ext, ".swf"))
  {
    tx_wr_pos += sprintf(tx_wr_pos, HTTP_CONTENT_TYPE_SWF);
  }
  else
// ++ hychu
  {
    tx_wr_pos += sprintf(tx_wr_pos, "application/x-javascript\r\n");
  } // of unknown content type
  
#if 0
  {
    //fprintf(stderr, "[http_send_file] Unknown content type: \"%s\"\n", ext);
    conn->state = RESET;
    ALT_DEBUG_ASSERT(1);
    return -1;
  }
#endif

  /* Get the file length and stash it into our connection info */
  hyseek(conn->file_handle, 0, SEEK_END);
  hygetpos(conn->file_handle, &end);
  hyseek(conn->file_handle, 0, SEEK_SET);
  hygetpos(conn->file_handle, &start);
  conn->file_length = end - start;

  /* "Content-Length: <length bytes>\r\n" */
  tx_wr_pos += sprintf(tx_wr_pos, HTTP_CONTENT_LENGTH);
  tx_wr_pos += sprintf(tx_wr_pos, "%d\r\n", conn->file_length);

  /* 
   * 'close' will be set during header parsing if the client either specified
   * that they wanted the connection closed ("Connection: Close"), or if they
   * are using an HTTP version prior to 1.1. Otherwise, we will keep the 
   * connection alive. 
   * 
   * We we send a specified number of files in a single keep-alive connection,
   * we'll also close the connection. Its best to be polite and tell the client,
   * though.
   */
  if(!conn->keep_alive_count)
  {
    conn->close = 1;
  }
  
  if(conn->close)
  {
    tx_wr_pos += sprintf(tx_wr_pos, HTTP_CLOSE);
  }
  else
  {
    tx_wr_pos += sprintf(tx_wr_pos, HTTP_KEEP_ALIVE);
  }

  /* "\r\n" (two \r\n's in a row means end of headers */
  tx_wr_pos += sprintf(tx_wr_pos, HTTP_CR_LF);

  /* Send the reply header */
  result = send(conn->fd, conn->tx_buffer, (tx_wr_pos - conn->tx_buffer), 
                MSG_DONTWAIT);  
                
  if(result < 0)
  {
    //fprintf(stderr, "[http_send_file] header send returned %d\n", result);
    conn->state = RESET;
    return result;
  }
  else
  {
    conn->activity_time = alt_nticks();
  }
  
  return ret_code;
}


/*
 * http_find_file()
 *
 * Try to find the file requested. If nothing is requested you get /index.html
 * If we can't find it, send a "404 - Not found" message.
 */
int http_find_file(http_conn* conn)
{
  alt_u8  filename[256];
  int     ret_code = 0;

  strncpy( filename, ALTERA_RO_ZIPFS_NAME, strlen(ALTERA_RO_ZIPFS_NAME));

  /* URI of "/" means get the default, usually index.html */
  if ( (conn->uri[0] == '/') && (conn->uri[1] == '\0') )
  {
    strcpy(filename+strlen(ALTERA_RO_ZIPFS_NAME), HTTP_DEFAULT_FILE);
  }
  else
  {
    strcpy( filename+strlen(ALTERA_RO_ZIPFS_NAME), conn->uri);
  }
  
// ++ hychu
  /* Try to open the file */
  // was: conn->file_handle = fopen(filename, "r");
  //if(!strncmp(filename, "file?", 5))
  conn->file_handle = hyopen(filename, "r");
  //else    conn->file_handle = fopen(filename, "r");
// -- hychu

  /* Can't find the requested file? Try for a 404-page. */
  if (conn->file_handle == NULL)
  {
    strcpy(filename, ALTERA_RO_ZIPFS_NAME);
    strcpy(filename+strlen(ALTERA_RO_ZIPFS_NAME), HTTP_NOT_FOUND_FILE);
    conn->file_handle = hyopen(filename, "r");
    
    /* We located the specified "404: Not-Found" page */
    if (conn->file_handle != NULL)
    {
      ALT_DEBUG_ASSERT(fd != NULL);
      ret_code = http_send_file_header(conn, filename, HTTP_NOT_FOUND);
    }
    /* Can't find the 404 page: This likely means there is no file system */
    else
    {
      //fprintf(stderr, "Can't open the Not found file.\n");
      //fprintf(stderr, "Have you programmed the filing system into flash?\n");
      send(conn->fd,(void*)canned_http_response,strlen(canned_http_response),0);
      
      hyclose(conn->file_handle);
      conn->state = RESET;
      return -1;  
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -