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

📄 50a731bed5b9001c180780c9bab1766d

📁 基于UCOS的嵌入式系统的应用
💻
📖 第 1 页 / 共 3 页
字号:
/******************************************************************************
* Copyright ? 2004 Altera Corporation, San Jose, California, USA.             *
* All rights reserved. All use of this software and documentation is          *
* subject to the License Agreement located at the end of this file below.     *
*******************************************************************************
* Author - PRR/JRK                                                            *
*                                                                             *
* File: http.c                                                                *
*                                                                             *
* A rough imlementation of HTTP. This is not intended to be a complete        *
* implementation, just enough for a demo simple web server. This example      *
* application is more complex than the telnet serer example in that it uses   *
* non-blocking IO & multiplexing to allow for multiple simultaneous HTTP      *
* sessions.                                                                   *            
*                                                                             *
* LWIP has two API's, a callback interface and "standard" sockets this        *
* example uses the sockets interface. A good introduction to sockets          *
* programming is the book Unix Network Programming by Richard Stevens         *
*                                                                             *
* Please refer to file readme.txt for notes on this software example.         *
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/param.h>
#include <sys/fcntl.h>
#include "lwip/netif.h"
#include "lwip/sockets.h"
#include "arch/sys_arch.h"
#include "sys/alt_alarm.h"
#include "alt_types.h"
#include "http.h"
#include "user.h"


// ++ hychu
#if 0
struct __sFILE {
  unsigned char *_p;  /* current position in (some) buffer */
  int _r;   /* read space left for getc() */
  int _w;   /* write space left for putc() */
  short _flags;   /* flags, below; this FILE is free if 0 */
  short _file;    /* fileno, if Unix descriptor, else -1 */
  struct __sbuf _bf;  /* the buffer (at least 1 byte, if !NULL) */
  int _lbfsize; /* 0 or -_bf._size, for inline putc */

  /* operations */
  _PTR  _cookie;  /* cookie passed to io functions */

  _READ_WRITE_RETURN_TYPE _EXFUN((*_read),(_PTR _cookie, char *_buf, int _n));
  _READ_WRITE_RETURN_TYPE _EXFUN((*_write),(_PTR _cookie, const char *_buf,             int _n));
  _fpos_t _EXFUN((*_seek),(_PTR _cookie, _fpos_t _offset, int _whence));
  int _EXFUN((*_close),(_PTR _cookie));

  /* separate buffer for long sequences of ungetc() */
  struct __sbuf _ub;  /* ungetc buffer */
  unsigned char *_up; /* saved _p when _p is doing ungetc data */
  int _ur;    /* saved _r when _r is counting ungetc data */

  /* tricks to meet minimum requirements even when malloc() fails */
  unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */
  unsigned char _nbuf[1]; /* guarantee a getc() buffer */

  /* separate buffer for fgetline() when line crosses buffer boundary */
  struct __sbuf _lb;  /* buffer for fgetline() */

  /* Unix stdio files get aligned to block boundaries on hyseek() */
  int _blksize; /* stat.st_blksize (may be != _bf._size) */
  int _offset;  /* current lseek offset */

#ifndef __SINGLE_THREAD__
  _flock_t _lock; /* for thread-safety locking */
#endif
};
#endif

#define MAX_CONCURRENT_HYPER  64
#define HYPER_FID_START     0x7000
FILE  _gFiles[MAX_CONCURRENT_HYPER];
int _ghy_initd = 0;

#define HY_CHK_FP(fp) ((fp) && ((fp)->_file >= HYPER_FID_START))

FILE * hy_allocate_fp(void)
{
  int i;
  for(i=0;i<MAX_CONCURRENT_HYPER;i++)
  {
    if(_gFiles[i]._flags != 0) continue;
    _gFiles[i]._flags = 0xbeef;
    return &_gFiles[i];
  } // of for i
  
  return NULL;
}

void hy_release_fp(FILE *fp)
{
  fp->_flags = 0;
}

FILE * hyopen(const char * pfname, const char * pmode)
{
  // bypass if ordinary file
  if(strncmp(pfname+strlen(ALTERA_RO_ZIPFS_NAME), "/file?", 5)) return fopen(pfname, pmode);

  // initialization
  if(!_ghy_initd)
  {
    int i;
    _ghy_initd = 1;
    for(i=0;i<MAX_CONCURRENT_HYPER;i++)
    {
      _gFiles[i]._file = HYPER_FID_START + i;
      _gFiles[i]._flags = 0;
    } // of for i
  } // of not init'd
  
  FILE * fp;
  
  if(!(fp = hy_allocate_fp())) return NULL;
  
  int flen=0;
  char * ptr;
  
  // seek for size
  if((ptr=strstr(pfname, "size="))) flen = atoi(ptr+5);
  
  // seek for unit
  for(ptr+=5; *ptr ; ptr++)
    if(*ptr < '0' || *ptr > '9') break;
  
  switch (*ptr)
  {
    case 'k': // 1000
      flen *= 1000;
      break;
    case 'K': // 1024
      flen *= 1024;
      break;
    case 'm': // 1,000,000
      flen *= 1000000;
      break;
    case 'M': // 1024*1024
      flen *= 1024*1024;
      break;
    default:
      break;
  } // of switch
  
  fp->_cookie = flen ? (void*)flen:(void*)(1024*1024);
  
  return fp;
}

int hygetpos(FILE * fp, fpos_t * offset)
{
  if(!HY_CHK_FP(fp)) return fgetpos(fp, offset);
  
  *offset = (int)fp->_offset;
  
  return 0;
}

int hyseek(FILE * fp, long offset, int origin)
{
  if(!HY_CHK_FP(fp)) return fseek(fp, offset, origin);
  
  switch(origin)
  {
    case SEEK_SET:
      fp->_offset = offset;
      break;
      
    case SEEK_CUR: // is it right ?
      fp->_offset += offset;
      break;
      
    case SEEK_END:
      fp->_offset = (int)(fp->_cookie) + offset;
      break;
      
    default:
      return -1;
  } // of switch(origin)
  
  return 0;
}


int hyclose(FILE * fp)
{
  if(!HY_CHK_FP(fp)) return fclose(fp);
  
  hy_release_fp(fp);
  
  return 0;
}

int hyread(void * pbuffer, size_t size, size_t count, FILE * fp)
{
  if(!HY_CHK_FP(fp)) return fread(pbuffer, size, count, fp);
  
  int total, remains;
  
  remains = (int)(fp->_cookie) - fp->_offset;
  total = (remains >= size*count)? size*count:remains;
  fp->_offset += total;
  return total;
}

// -- hychu

#ifdef DEBUG1
  #include alt_debug.h
#else
  #define ALT_DEBUG_ASSERT(a) 
#endif /* DEBUG */

/* 
 * TX & RX buffers. 
 * 
 * These are declared globally to prevent the MicroC/OS-II thread from
 * consuming too much OS-stack space
 */
alt_u8 http_rx_buffer[HTTP_NUM_CONNECTIONS][HTTP_RX_BUF_SIZE];
alt_u8 http_tx_buffer[HTTP_NUM_CONNECTIONS][HTTP_TX_BUF_SIZE];

/* 
 * This canned HTTP reply will serve as a "404 - Not Found" Web page. HTTP
 * headers and HTML embedded into the single string.
 */
static const alt_8 canned_http_response[] = {"\
HTTP/1.0 404 Not Found\r\n\
Content-Type: text/html\r\n\
Content-Length: 272\r\n\r\n\
<HTML><HEAD><TITLE>Nios II Web Server Demonstration</TITLE></HEAD>\
<title>LWIP on Nios II</title><BODY><h1>HTTP Error 404</h1>\
<center><h2>Nios II Web Server Demonstration</h2>\
Can't find the requested file file. \
Have you programmed the flash filing system into flash?</html>\
"};

// hychu
static const alt_8 hello_http_response[] = {"\
HTTP/1.0 200\r\n\
Content-Type: text/html\r\n\
Content-Length: 203\r\n\r\n\
<HTML><HEAD><TITLE>Nios II Web Server Demonstration</TITLE></HEAD>\
<title>LWIP on Nios II</title>\
<BODY>\
<br><br>\
<center>\
<h1>Nios II Web Server Demonstration</h1><br>\
<h2>Hello World</h2><br>\
</center>\
</html>\
"};

/* 
 * Mapping between pages to post to and functions to call: This allows us to
 * have the HTTP server respond to a POST requset saying "print" by calling
 * a "print" routine (below).
 */
typedef struct funcs
{
  alt_u8*  name;
  void (*func)(); 
}post_funcs;

/* 
 * print()
 * 
 * This routine is called to demonstrate doing something server-side when an
 * HTTP "POST" command is received.
 */
void print()
{
  printf("HTTP POST received.\n");
}

/* 
 * The mapping (using our struct defined above) between HTTP POST commands
 * that we will service and the subroutine called to service that POST
 * command.
 */
post_funcs mapping =
{
  "/PRINT",
  print
};

/*
 * http_reset_connection()
 * 
 * This routine will clear our HTTP connection structure & prepare it to handle
 * a new HTTP connection.
 */
void http_reset_connection(http_conn* conn, int http_instance)
{
  memset(conn, 0, sizeof(http_conn));

  conn->fd = -1;
  conn->state = READY;
  conn->keep_alive_count = HTTP_KEEP_ALIVE_COUNT;
  
  conn->rx_buffer = (alt_u8 *) &http_rx_buffer[http_instance][0];
  conn->tx_buffer = (alt_u8 *) &http_tx_buffer[http_instance][0];
  conn->rx_wr_pos = (alt_u8 *) &http_rx_buffer[http_instance][0];
  conn->rx_rd_pos = (alt_u8 *) &http_rx_buffer[http_instance][0];
}

/*
 * http_manage_connection()
 * 
 * This routine performs house-keeping duties for a specific HTTP connection
 * structure. It is called from various points in the HTTP server code to
 * ensure that connections are reset properly on error, completion, and
 * to ensure that "zombie" connections are dealt with.
 */
void http_manage_connection(http_conn* conn, int http_instance)
{
  alt_u32 current_time = 0;
  
  /*
   * Keep track of whether an open connection has timed out. This will be
   * determined by comparing the current time with that of the most recent
   * activity.
   */
  if(conn->state == READY || conn->state == PROCESS || conn->state == DATA)
  {
    current_time = alt_nticks();
    
    if( (current_time - conn->activity_time) >= HTTP_KEEP_ALIVE_TIME )
    {
      conn->state = RESET;
    }
  }
  
  /*
   * The reply has been sent. Is is time to drop this connection, or 
   * should we persist? We'll keep track of these here and mark our
   * state machine as ready for additional connections... or not.
   *  - Only send so many files per connection. 
   *  - Stop when we reach a timeout.
   *  - If someone (like the client) asked to close the connection, do so.
   */
  if(conn->state == COMPLETE)
  {
    if(conn->file_handle != NULL)
    {
      hyclose(conn->file_handle);
    }
      
    conn->keep_alive_count--;
    conn->data_sent = 0;
  
    if(conn->keep_alive_count == 0)
    {
      conn->close = 1;
    }
    
    conn->state = conn->close ? CLOSE : READY;
  }
  
  /* 
   * Some error occured. http_reset_connection() will take care of most
   * things, but the RX buffer still needs to be cleared, and any open
   * files need to be closed. We do this in a separate state to maintain 
   * efficiency between successive (error-free) connections.
   */
  if(conn->state == RESET)
  {
    if(conn->file_handle != NULL)
    {
      hyclose(conn->file_handle);
    }
      
    memset(conn->rx_buffer, 0, HTTP_RX_BUF_SIZE);
    conn->state = CLOSE;
  }
  
  /* Close the TCP connection */
  if(conn->state == CLOSE)
  {
    close(conn->fd);
    http_reset_connection(conn, http_instance);
  }
}

/*
 * http_handle_accept()
 * 
 * A listening socket has detected someone trying to connect to us. If we have 
 * any open connection slots we will accept the connection (this creates a 
 * new socket for the data transfer), but if all available connections are in 
 * use we'll ignore the client's incoming connection request.
 */
int http_handle_accept(int listen_socket, http_conn* conn)
{
  int ret_code = 0, i, socket, len;
  struct sockaddr_in  rem;

  len = sizeof(rem);

  /* 
   * Loop through available connection slots to determine the first available
   * connection.
   */
  for(i=0; i<HTTP_NUM_CONNECTIONS; i++)
  {
    if((conn+i)->fd == -1)
    {
      break;
    }
  }
  
  /* 
   * There are no more connection slots available. Ignore the connection
   * request for now.
   */
  if(i == HTTP_NUM_CONNECTIONS)

⌨️ 快捷键说明

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