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

📄 httpd.c

📁 picoos源码。The RTOS and the TCP/IP stack will be built automatically.
💻 C
📖 第 1 页 / 共 5 页
字号:
  }

  /* all OK -> go to downstream state */

  conn->contenttype = content_html;

  /* if file is empty, handle next transfer */
  if (conn->filesize == 0)
  {
    ht_sendStatus(conn, status_204); /* No Content */
    ht_nextTransfer(conn);
    return;
  }

  ht_sendStatus(conn, status_200); /* OK */

  /* quit now if we shall only transmit the header */
  if (conn->method == method_head)
  {
    ht_nextTransfer(conn);
    return;
  }

  /* set up to download data */
  ht_addWrSocket(conn->socket);
  conn->state = STATE_DOWNSTREAM;
  return;
}


/* print to the stdout of the servlet
 */
sint_t hsl_printf(SERVLET_t *slobj, const char *fmt, ...)
{
  HTTPCONN_t *conn = (HTTPCONN_t*) slobj;
  sint_t len;
  char b, c;
  va_list args;


  if (conn == NULL)
    return -1;
  if ((conn->state != STATE_INIT) ||
      (conn->curoutbuf == NULL))
    return -1;
  
  va_start(args, fmt);
  vsprintf((char*)tempbuf1_g, fmt, args);
  va_end(args);

  if (*tempbuf1_g == 0)
    return 0;

  len = 0;
  b = 0;
  while ((tempbuf1_g[len] != 0) || (b != 0))
  {
    if (conn->stdoutlen >= HTTP_SERVLETMINBUF)
    {
      if (conn->freeSlBufs == NULL)
        break;
      conn->curoutbuf->nextbuf = conn->freeSlBufs;
      conn->freeSlBufs = conn->freeSlBufs->nextbuf;
      conn->curoutbuf = conn->curoutbuf->nextbuf;
      conn->curoutbuf->nextbuf = NULL;
      conn->stdoutlen = 0;
    }
    if (b != 0)
    {
      c = b;
      b = 0;
    }
    else
    {
      c = tempbuf1_g[len++];
      if (c == '\n')
      {
        c = '\r';
        b = '\n';
      }
      else
      if (c < ' ')
        continue;
    }
    conn->curoutbuf->buf[conn->stdoutlen++] = c;
    conn->filesize++;
  }

  return len;
}


/* Request stream buffer memory.
 */
sint_t hsl_setStreamBufSize(SERVLET_t *slobj, u32_t bufsize)
{
  HTTPCONN_t *conn = (HTTPCONN_t*) slobj;
  sint_t blocks;

  if ((bufsize > maxServletMem_g) ||
      (conn->state != STATE_INIT))
    return SLERR_FAIL;

  if (bufsize <= conn->outbufsize)
    return SLERR_OK;

  blocks = ((bufsize - conn->outbufsize) + (HTTP_SERVLETMINBUF - 1)) /
             HTTP_SERVLETMINBUF;
  conn->neededBufs = blocks;

  if (ht_tryAllocateBuffers(conn) != 0)
    return SLERR_NEEDMEM;

  return SLERR_OK;
}


/* Create a new servlet object.
 */
sint_t hsl_create(SERVLETFUNC_t func, const char *filename)
{
  char *f = (char*) filename;
  SLINFO_t *si;

  if (httpd_running_g == 0)
    return -1;

  if ((func == NULL) || (*f == 0))
    return -1;

  while (*f == '/') f++;

  hsl_destroy(func);

  si = (SLINFO_t*) sysMemAlloc(sizeof(SLINFO_t));
  if (si == NULL)
    return -1;

  sysStrcpy(si->filename, f);
  si->func = func;

  SYS_MTASK_LOCK(servletLock_g);
  ht_listAddHead(&servletList_g, &si->list);
  SYS_MTASK_UNLOCK(servletLock_g);

  return 0;
}


/* Destroy a servlet object.
 */
sint_t hsl_destroy(SERVLETFUNC_t func)
{
  SLINFO_t *si;

  if (httpd_running_g == 0)
    return -1;

  SYS_MTASK_LOCK(servletLock_g);

  si = FIRST_LIST_ELEM(&servletList_g, SLINFO_t*);
  while (!END_OF_LIST(&servletList_g, si))
  {
    if (si->func == func)
    {
      ht_listDel(&si->list);
      sysMemFree(si);
      SYS_MTASK_UNLOCK(servletLock_g);
      return 0;
    }
    si = NEXT_LIST_ELEM(&si->list, SLINFO_t*);
  }

  SYS_MTASK_UNLOCK(servletLock_g);
  return -1;
}


/* Get an URI parameter string by name.
 */
char *hsl_getParameterByName(SERVLET_t *slobj, const char *name)
{
  HTTPCONN_t *conn = (HTTPCONN_t*) slobj;
  char *e = conn->optstring;
  int l = sysStrlen(name);

  while (*e != 0)
  {
    if (sysStrnicmp(e, name, l) == 0)
    {
      while ((*e != 0) && (*e != '='))  e++;
      return (*e == 0) ? NULL : e + 1;
    }
    while (*e != 0) e++;
    e++;
  }

  return NULL;
}


#endif /* HTTP_SERVLETS */


/*-------------------------------------------------------------------------*/

/*
#define ENABLE_LOG
#define _MYDEBUG
*/

#ifdef ENABLE_LOG
static FILE* logfile_g = NULL;
void initLog(void)
{
  logfile_g = fopen("httplog.txt", "w+b");
}
void termLog(void)
{
  if (logfile_g != NULL)
  {
    fclose(logfile_g);
    logfile_g = NULL;
  }
}
void log(int socket, const char *str)
{
  if (socket >= 0)  printf("%i: %s", socket, str);
  else  printf("%s", str);
  if (logfile_g != NULL)
  {
    if (socket >= 0)  fprintf(logfile_g, "%i: %s", socket, str);
    else  fprintf(logfile_g, "%s", str);
  }
}
#else
#define log(s,x)   do {} while(0)
#define initLog()  do {} while(0)
#define termLog()  do {} while(0)
#endif

/*-------------------------------------------------------------------------*/


/* Insert an element to the tail of a double linked list.
 */
static void ht_listAddTail(lelem_t *headelem, lelem_t *elem)
{
  elem->prev = headelem->prev;
  elem->next = headelem;
  headelem->prev->next = elem;
  headelem->prev = elem;
}


/* Insert an element to the head of a double linked list.
 */
static void ht_listAddHead(lelem_t *headelem, lelem_t *elem)
{
  elem->next = headelem->next;
  elem->prev = headelem;
  headelem->next->prev = elem;
  headelem->next = elem;
}


/* Remove an element from a double linked list
 * and free its memory.
 */
static void ht_listDel(lelem_t *elem)
{
  lelem_t *next = elem->next;
  lelem_t *prev = elem->prev;
  next->prev = prev;
  prev->next = next;
  INIT_LIST_HEAD(elem);
}


/*-------------------------------------------------------------------------*/


/* build a valid filename
 */
static char* ht_buildFilename(const char* uriOrFile)
{
  char *f = (char*) uriOrFile;

  while (*f == '/') f++;

#if !defined(HAVE_EMBEDDED_FILESYSTEM) || (FS_SUBDIRECTORIES == 0)
  sysStrcpy((char*)tempbuf1_g, httpRootDir_g);
  sysStrcat((char*)tempbuf1_g, f);
#ifdef DOS_PATH
  for (f = (char*)tempbuf1_g; *f != 0; f++)
    if (*f == '/') *f = '\\';
#endif
#else
  do
  {
    sint_t i;

    if (fsys_buildPathName((char*)tempbuf2_g, f, "") < 0)
      return NULL;
    i = sysStrlen((char*)tempbuf2_g);
    if ((i > 0) && (tempbuf2_g[i-1] == '/')) tempbuf2_g[i-1] = 0;
    if (fsys_buildPathName((char*)tempbuf1_g, httpRootDir_g,
                           (char*)tempbuf2_g) < 0)
      return NULL;
  }
  while(0);
#endif

  return (char*)tempbuf1_g;
}


/* read a block of data from a file
 */
static sint_t ht_readFile(HTTPCONN_t *conn, char *buf, u32_t count)
{
#if !HTTP_SERVLETS

  /* handle normal file transfer */
  return fsys_read(conn->filehandle, buf, count);

#else /* HTTP_SERVLETS */

  u32_t   c;
  uint_t  n;
  SLBUF_t *slbuf;

  if (conn->servlet == NULL)
  {
    /* handle normal file transfer */
    return fsys_read(conn->filehandle, buf, count);
  }

  /* handle servlet */
  if (conn->stdoutbuf == NULL)
    return 0;
  c = 0;
  while ((c < count) && (conn->stdoutbuf != NULL))
  {
    n = (conn->stdoutbuf->nextbuf == NULL) ?
          conn->stdoutlen : HTTP_SERVLETMINBUF;
    n -= conn->outbufptr;
    if (n > (uint_t) count)
      n = (uint_t) count;
    if (n > 0)
      sysMemCopy(buf + c, conn->stdoutbuf->buf + conn->outbufptr, n);
    conn->outbufptr += n;
    if ((conn->outbufptr >= HTTP_SERVLETMINBUF) ||
        ((conn->stdoutbuf->nextbuf == NULL) &&
         (conn->outbufptr >= conn->stdoutlen)))
    {
      conn->outbufptr = 0;
      slbuf = conn->stdoutbuf;
      conn->stdoutbuf = slbuf->nextbuf;
      ht_freeServletBuffer(slbuf);
    }
    c += (u32_t) n;
  }
  return (sint_t) c;

#endif /* HTTP_SERVLETS */
}




/* open a file for read
 */
static sint_t ht_openFile(HTTPCONN_t *conn, sint_t mode, u32_t *size)
{
  struct fsys_stat stat;
  char *f;
  sint_t i;

  /*** test if file is a reference to a servlet ***/

#if HTTP_SERVLETS

  SLINFO_t *si;

  f = conn->filename;
  while (*f == '/') f++;

  SYS_MTASK_LOCK(servletLock_g);

  si = FIRST_LIST_ELEM(&servletList_g, SLINFO_t*);
  while (!END_OF_LIST(&servletList_g, si))
  {
    if (sysStricmp(f, si->filename) == 0)
    {
      /* servlet found, initialize it */
      conn->servlet = si;
      conn->neededBufs = 1;
      SYS_MTASK_UNLOCK(servletLock_g);
      return 0;
    }
    si = NEXT_LIST_ELEM(&si->list, SLINFO_t*);
  }

  SYS_MTASK_UNLOCK(servletLock_g);

#endif /* HTTP_SERVLETS */


  /*** open a real file ***/

  /* build initial filename:
     If the client sent us just a directory name,
     we try to figure out if a index.htm(l) is present. */
  if (*conn->filename == 0)
  {
    conn->filename[0] = '/';
    conn->filename[1] = 0;
  }
  i = sysStrlen(conn->filename);
  if (conn->filename[i-1] == '/')
  {
    sysStrcat(conn->filename, "index.htm");
    f = ht_buildFilename(conn->filename);
    if (f == NULL)
    {
      conn->filename[i] = 0;
      return -1;
    }
    if (fsys_stat(f, &stat) < 0)
    {
      sysStrcat(conn->filename, "l");
      f = ht_buildFilename(conn->filename);
      if (f == NULL)
      {
        conn->filename[i] = 0;
        return -1;
      }
      if (fsys_stat(f, &stat) < 0)
      {
        conn->filename[i] = 0;
        return -1;
      }
    }
  }
  else
  {
    f = ht_buildFilename(conn->filename);
    if (fsys_stat(f, &stat) < 0)
      return -1;
  }

  conn->filehandle = fsys_open(f, mode);
  if (conn->filehandle < 0)
    return -1;

  *size = (u32_t) stat.st_size;

  return 0;
}


/* close a file
 */
static void ht_closeFile(HTTPCONN_t *conn)
{
#if HTTP_SERVLETS
  SLBUF_t *buf;

  if (conn->servlet != NULL)
  {
    /* TODO: free all memory assigned to the servlet instance */

    while (conn->stdoutbuf != NULL)
    {
      buf = conn->stdoutbuf;
      conn->stdoutbuf = buf->nextbuf;
      ht_freeServletBuffer(buf);
    }

    while (conn->freeSlBufs != NULL)
    {
      buf = conn->freeSlBufs;
      conn->freeSlBufs = buf->nextbuf;
      ht_freeServletBuffer(buf);
    }

    conn->servlet = NULL;
  }
#endif

  if (conn->filehandle >= 0)
  {
    fsys_close(conn->filehandle);
    conn->filehandle = 0;
  }
}


/*-------------------------------------------------------------------------*/


/* Determine and set the http content type
 * of a downstram file. The content type is
 * determined by evaluating the file extension.
 */
static void ht_setContentType(HTTPCONN_t *conn)
{
  HTTPTYPEDEC_t *dec;
  sint_t i, l;
  char *f;

  /* set default content type: binary (octet-stream) */
  conn->contenttype = content_binary;

  /* get file extension from filename */
  f = conn->filename;
  i = sysStrlen(f);
  while ((i > 0) && (f[i-1] != '.') && (f[i-1] != '/')) i--;

  if (!((i > 0) && (f[i-1] == '.')))
  {
    /* no extension found: unknown content, set to binary type */
    return;
  }
  
  f += i;
  l = 0;
  while ((f[l] != 0) && (f[l] != ' ') && (f[l] != '?')) l++;

  /* get content type from file-extension decoding table */
  dec = contentDecodeTable;
  while (*dec->extension != 0)
  {
    if (((sint_t)sysStrlen(dec->extension) == l) &&

⌨️ 快捷键说明

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