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

📄 50a731bed5b9001c180780c9bab1766d

📁 基于UCOS的嵌入式系统的应用
💻
📖 第 1 页 / 共 3 页
字号:
  }
  /* We've found the requested file; send its header and move on. */  
  else
  {
    ret_code = http_send_file_header(conn, filename, HTTP_OK);
  }

  return ret_code;
}

/*
 * http_handle_post()
 *
 * Process the post request and take the appropriate action.
 */
int http_handle_post(http_conn* conn)
{
  alt_u8* tx_wr_pos = conn->tx_buffer;
  int ret_code = 0;

  tx_wr_pos += sprintf(tx_wr_pos, HTTP_VERSION_STRING);
  tx_wr_pos += sprintf(tx_wr_pos, HTTP_NO_CONTENT_STRING);

  conn->close = 1;

  tx_wr_pos += sprintf(tx_wr_pos, HTTP_CLOSE);

  tx_wr_pos += sprintf(tx_wr_pos, HTTP_END_OF_HEADERS);

  send(conn->fd, conn->tx_buffer, (tx_wr_pos - conn->tx_buffer), 0);  

  if (!strcmp(conn->uri, mapping.name))
  {
    mapping.func();
  }
  
  return ret_code;
}


/*
 * http_prepare_response()
 * 
 * Service the various HTTP commands, calling the relevant subroutine. 
 * We only handle GET and POST.
 */
int http_prepare_response(http_conn* conn)
{
  int ret_code = 0;
  
  switch (conn->action)
  {
    case GET:
    {
      /* Find file from uri */
      ret_code = http_find_file(conn);
      break;
    }
    case POST:
    {
      /* Find file from uri */
      ret_code = http_handle_post(conn);
      break;
    }
    default:
    {
      break;
    }
  } /* switch (conn->action) */
  
  return ret_code;
}

/*
 * http_handle_receive()
 *
 * Work out what the request we received was, and handle it.
 */
void http_handle_receive(http_conn* conn, int http_instance)
{
  int data_used, rx_code;
 
  if (conn->state == READY)
  {
    rx_code = recv(conn->fd, conn->rx_wr_pos, 
              (HTTP_RX_BUF_SIZE - (conn->rx_wr_pos - conn->rx_buffer) -1), 
              MSG_DONTWAIT);
        
    /* 
     * If a valid data received, take care of buffer pointer & string 
     * termination and more on. Otherwise, we need to return and wait for more
     * data to arrive (until we time out).
     */
    if(rx_code > 0)
    {
      conn->rx_wr_pos += rx_code;
      *(conn->rx_wr_pos+1) = 0;
      
      if(strstr(conn->rx_buffer, HTTP_END_OF_HEADERS))
      {
        conn->state = PROCESS;
      }
    }
  }
  
  if(conn->state == PROCESS)
  {
    /* 
     * If we (think) we have valid headers, keep the connection alive a bit
     * longer.
     */
    conn->activity_time = alt_nticks();
    
    /* 
     * Attempt to process the fundamentals of the HTTP request. We may 
     * error out and reset if the request wasn't complete, or something
     * was asked from us that we can't handle.
     */
    if (http_process_request(conn))
    {
      //fprintf(stderr, "[http_handle_receive] http_process_request failed\n");
      conn->state = RESET;
      http_manage_connection(conn, http_instance);
    }
    
    /* 
     * Step through the headers to see if there is any other useful 
     * information about our pending transaction to extract. After that's 
     * done, send some headers of our own back to let the client know 
     * what's happening. Also, once all in-coming headers have been parsed
     * we can manage our RX buffer to prepare for the next in-coming 
     * connection.
     */
    while(conn->state == PROCESS)
    {
      if(http_read_line(conn))
      {
        //fprintf(stderr, "[http_handle_receive] error reading headers\n");
        conn->state = RESET;
        http_manage_connection(conn, http_instance);
        break;
      }
      if(http_process_headers(conn))
      {
        if( (conn->rx_rd_pos = strstr(conn->rx_rd_pos, HTTP_CR_LF)) )
        {
          conn->rx_rd_pos += 2;
          conn->state = DATA;
          conn->activity_time = alt_nticks();
        }
        else
        {
          //fprintf(stderr, "[http_handle_receive] Can't find end of headers!\n");
          conn->state = RESET;
          http_manage_connection(conn, http_instance);
          break;
        }
      } 
    } /* while(conn->state == PROCESS) */
    
    if( http_prepare_response(conn) )
    {
      conn->state = RESET;
      //fprintf(stderr, "[http_handle_receive] Error preparing response\n");
      http_manage_connection(conn, http_instance);
    }
              
    /* 
     * Manage RX Buffer: Slide any un-read data in our input buffer 
     * down over previously-read data that can now be overwritten, and 
     * zero-out any bytes in question at the top of our new un-read space. 
     */
    if(conn->rx_rd_pos > (conn->rx_buffer + HTTP_RX_BUF_SIZE))
    {
      conn->rx_rd_pos = conn->rx_buffer + HTTP_RX_BUF_SIZE;
    }
        
    data_used = conn->rx_rd_pos - conn->rx_buffer;
    memmove(conn->rx_buffer,conn->rx_rd_pos,conn->rx_wr_pos-conn->rx_rd_pos);
    conn->rx_rd_pos = conn->rx_buffer;
    conn->rx_wr_pos -= data_used;
    memset(conn->rx_wr_pos, 0, data_used);
   } 
}

/* 
 * http_handle_transmit()
 * 
 * Transmit a chunk of a file in an active HTTP connection. This routine
 * will be called from the thread's main loop when ever the socket is in 
 * the 'DATA' state and the socket is marked as available for writing (free
 * buffer space). 
 */
void http_handle_transmit(http_conn* conn, int http_instance)
{
  if( http_send_file_chunk(conn) )
  {
    //fprintf(stderr, "[http_handle_transmit]: Send file chunk failed\n");
  }
}

/*
 * http_task()
 * 
 * This MicroC/OS-II thread spins forever after first establishing a listening
 * socket for HTTP connections, binding them, and listening. Once setup,
 * it perpetually waits for incoming data to either a listening socket, or
 * (if there is an active connection), an HTTP data socket. When data arrives, 
 * the approrpriate routine is called to either accept/reject a connection 
 * request, or process incoming data.
 * 
 * This routine calls "select()" to determine which sockets are ready for
 * reading or writing. This, in conjunction with the use of non-blocking 
 * send() and recv() calls and sending responses broken up into chunks lets
 * us handle multiple active HTTP requests.
 */
void http_task()
{
  int     i, fd_listen, max_socket;
  struct  sockaddr_in addr;
  struct  timeval select_timeout;
  fd_set  readfds, writefds;
  static  http_conn     conn[HTTP_NUM_CONNECTIONS];

  /*
   * Sockets primer...
   * The socket() call creates an endpoint for TCP of UDP communication. It 
   * returns a descriptor (similar to a file descriptor) that we call fd_listen,
   * or, "the socket we're listening on for connection requests" in our web
   * server example.
   */ 
   printf("http_task is called\n");
   printf("create socket\n");
  if ((fd_listen = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  {
    die_with_error("[http_task] Listening socket creation failed");
  }
  
  /*
   * Sockets primer, continued...
   * Calling bind() associates a socket created with socket() to a particular IP
   * port and incoming address. In this case we're binding to HTTP_PORT and to
   * INADDR_ANY address (allowing anyone to connect to us. Bind may fail for 
   * various reasons, but the most common is that some other socket is bound to
   * the port we're requesting. 
   */ 
  addr.sin_family = AF_INET;
  addr.sin_port = htons(HTTP_PORT);
  addr.sin_addr.s_addr = INADDR_ANY;
  printf("bind socket\n");  
  if ((bind(fd_listen,(struct sockaddr *)&addr,sizeof(addr))) < 0)
  {
    die_with_error("[http_task] Bind failed");
  }
    
  /*
   * Sockets primer, continued...
   * The listen socket is a socket which is waiting for incoming connections.
   * This call to listen will block (i.e. not return) until someone tries to 
   * connect to this port.
   */ 
   printf("listen socket\n"); 
  if ((listen(fd_listen,1)) < 0)
  {
    die_with_error("[http_task] Listen failed");
  }

  /* 
   * At this point we have successfully created a socket which is listening
   * on HTTP_PORT for connection requests from any remote address.
   */
  for(i=0; i<HTTP_NUM_CONNECTIONS; i++)
  {
    printf("http_reset_connection socket\n"); 
    http_reset_connection(&conn[i], i);
    printf("conn[%d]=%d\n",i,conn[i].fd);
  }
  printf("while(1)  fd_listen=%d\n",fd_listen); 
  while(1)
  {
    /* 
     * The select() call below tells the LWIP stack to return  from this call 
     * when any of the events we have expressed an interest in happen (it 
     * blocks until our call to select() is satisfied). 
     * 
     * In the call below we're only interested in either someone trying to 
     * connect to us, or when an existing (active) connection has new receive 
     * data, or when an existing connection is in the "DATA" state meaning that
     * we're in the middle of processing an HTTP request. If none of these 
     * conditions are satisfied, select() blocks until a timeout specified 
     * in the select_timeout struct.
     * 
     * The sockets we're interested in (for RX) are passed in inside the 
     * readfds parameter, while those we're interested in for TX as passed in 
     * inside the writefds parameter. The format of readfds and writefds is 
     * implementation dependant, hence there are standard macros for 
     * setting/reading the values:
     * 
     *   FD_ZERO  - Zero's out the sockets we're interested in
     *   FD_SET   - Adds a socket to those we're interested in
     *   FD_ISSET - Tests whether the chosen socket is set 
     */
    
    FD_ZERO(&readfds);
    FD_ZERO(&writefds);
    FD_SET(fd_listen, &readfds);
    
    max_socket = fd_listen+1;
    
    for(i=0; i<HTTP_NUM_CONNECTIONS; i++)
    {
      if (conn[i].fd != -1)
      {
        printf("conn[%d].fd=%d\n",i,conn[i].fd);
        /* We're interested in reading any of our active sockets */
        FD_SET(conn[i].fd, &readfds);
        
        /* 
         * We're interested in writing to any of our active sockets in the DATA
         * state
         */
        if(conn[i].state == DATA)
        {
          printf("conn[%d].state == DATA\n",i);
          FD_SET(conn[i].fd, &writefds);
        }
        
        /*
         * select() must be called with the maximum number of sockets to look 
         * through. This will be the largest socket number + 1 (since we start
         * at zero).
         */
        if (max_socket <= conn[i].fd)
        {
          max_socket = conn[i].fd+1;
        }
      }
    }

    /* 
     * Set timeout value for select. This must be reset for each select()
     * call.
     */
    select_timeout.tv_sec = 0;
    select_timeout.tv_usec = 500000;

    select(max_socket, &readfds, &writefds, NULL, &select_timeout);

    /* 
     * If fd_listen (the listening socket we originally created in this thread
     * is "set" in readfds, then we have an incoming connection request. 
     * We'll call a routine to explicitly accept or deny the incoming connection 
     * request.
     */
    if (FD_ISSET(fd_listen, &readfds))
    {
      printf("we have an incoming connection request.\n");
      http_handle_accept(fd_listen, conn);
      printf("http_handle_accept.\n");
    }

    /*
     * If http_handle_accept() accepts the connection, it creates *another*
     * socket for sending/receiving data. This socket is independant of the 
     * listening socket we created above. This socket's descriptor is stored 
     * in conn[i].fd. Therefore if conn[i].fd is set in readfs, we have
     * incoming data for our HTTP server, and we call our receive routine
     * to process it. Likewise, if conn[i].fd is set in writefds, we have
     * an open connection that is *capable* of being written to.
     */
    for(i=0; i<HTTP_NUM_CONNECTIONS; i++)
    {
      if (conn[i].fd != -1)
      { 
        if(FD_ISSET(conn[i].fd,&readfds))
        {
          http_handle_receive(&conn[i], i);
        }
        
        if(FD_ISSET(conn[i].fd,&writefds))
        {
          http_handle_transmit(&conn[i], i);
        }
        
        http_manage_connection(&conn[i], i);
      }
    }  
  } /* while(1) */
}

/******************************************************************************
*                                                                             *
* License Agreement                                                           *
*                                                                             *
* Copyright (c) 2004 Altera Corporation, San Jose, California, USA.           *
* All rights reserved.                                                        *
*                                                                             *
* Permission is hereby granted, free of charge, to any person obtaining a     *
* copy of this software and associated documentation files (the "Software"),  *
* to deal in the Software without restriction, including without limitation   *
* the rights to use, copy, modify, merge, publish, distribute, sublicense,    *
* and/or sell copies of the Software, and to permit persons to whom the       *
* Software is furnished to do so, subject to the following conditions:        *
*                                                                             *
* The above copyright notice and this permission notice shall be included in  *
* all copies or substantial portions of the Software.                         *
*                                                                             *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,    *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER      *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING     *
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER         *
* DEALINGS IN THE SOFTWARE.                                                   *
*                                                                             *
* This agreement shall be governed in all respects by the laws of the State   *
* of California and by the laws of the United States of America.              *
* Altera does not recommend, suggest or require that this reference design    *
* file be used in conjunction or combination with any other product.          *
******************************************************************************/

⌨️ 快捷键说明

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