Exemple #1
0
void ShellTaskInit() {
  TaskHandle_t xHandle = NULL;

  read_line_init(&read_line_config);
  ConsoleInit();
  xTaskCreate(ShellTask, "shell", configMINIMAL_STACK_SIZE + 200, NULL, 1, &xHandle);
  assert(xHandle);
}
Exemple #2
0
/**
 * read http reply
 *
 * TODO: use a callback instead of expect_data
 *
 * @param conn
 * @param expect_data // always set to 1, expect for HEAD-like methods!
 * @param http_statusp returns the http status
 * @param header_func
 * @param buffer_func
 * @param cb_arg
 *
 * @return dpl_status
 */
dpl_status_t
dpl_read_http_reply_buffered(dpl_conn_t *conn,
                             int expect_data,
                             int *http_statusp,
                             dpl_header_func_t header_func,
                             dpl_buffer_func_t buffer_func,
                             void *cb_arg)
{
  int ret, ret2;
  struct dpl_http_reply http_reply;
  char *line = NULL;
  size_t chunk_len = 0;
  ssize_t chunk_remain = 0;
  ssize_t chunk_off = 0;
  int chunked = 0;
#define MODE_REPLY  0
#define MODE_HEADER  1
#define MODE_CHUNK   2
#define MODE_CHUNKED 3
  int mode;

  DPRINTF("read_http_reply fd=%d flags=0x%x\n", conn->fd, flags);

  http_reply.code = 0;

  read_line_init(conn);

  mode = MODE_REPLY;
  ret = DPL_SUCCESS;

  while (1)
    {
      if (MODE_CHUNK == mode)
        {
          DPRINTF("chunk_len=%ld chunk_off=%ld\n", chunk_len, chunk_off);

          if (chunk_off < chunk_len)
            {
              chunk_remain = chunk_len - chunk_off;

              DPL_TRACE(conn->ctx, DPL_TRACE_IO, "read conn=%p https=%d size=%ld (remain %ld)", conn, conn->ctx->use_https, conn->read_buf_size, chunk_remain);

              if (0 == conn->ctx->use_https)
                {
                  struct pollfd fds;

                  int recvfl = 0;

                retry:
                  memset(&fds, 0, sizeof (fds));
                  fds.fd = conn->fd;
                  fds.events = POLLIN;

                  ret2 = poll(&fds, 1, conn->ctx->read_timeout*1000);
                  if (-1 == ret2)
                    {
                      if (errno == EINTR)
                        goto retry;
                      DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "poll"); 
                      ret = DPL_FAILURE;
                      goto end;
                    }

                  if (0 == ret2)
                    {
                      DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "read timeout");
                      ret = DPL_FAILURE;
                      goto end;
                    }
                  else if (!(fds.revents & POLLIN))
                    {
                      DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "socket error");
                      ret = DPL_FAILURE;
                      goto end;
                    }

                  recvfl = (chunk_remain >= conn->read_buf_size) ? MSG_WAITALL : 0;

                  conn->cc = recv(conn->fd, conn->read_buf, conn->read_buf_size, recvfl);
                  if (-1 == conn->cc)
                    {
                      DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "recv");
                      ret = DPL_FAILURE;
                      goto end;
                    }
                }
              else
                {
                  conn->cc = SSL_read(conn->ssl, conn->read_buf, conn->read_buf_size);
                  if (conn->cc <= 0)
                    {
                      DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "SSL_read");
                      ret = DPL_FAILURE;
                      goto end;
                    }
                }

              DPL_TRACE(conn->ctx, DPL_TRACE_IO, "read conn=%p https=%d cc=%ld", conn, conn->ctx->use_https, conn->cc);

              if (0 == conn->cc)
                {
                  DPRINTF("no more data to read\n");
                  break ;
                }

              if (conn->ctx->trace_buffers)
                dpl_dump_simple(conn->read_buf, conn->cc, conn->ctx->trace_binary);

              chunk_remain = MIN(conn->cc, chunk_len - chunk_off);
              ret2 = buffer_func(cb_arg, conn->read_buf, chunk_remain);
              if (DPL_SUCCESS != ret2)
                {
                  DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "buffer_func");
                  ret = DPL_FAILURE;
                  goto end;
                }
              conn->read_buf_pos = chunk_remain;
              chunk_off += chunk_remain;

              continue ;
            }

          DPL_TRACE(conn->ctx, DPL_TRACE_HTTP, "conn=%p chunk done", conn);

          if (1 == chunked)
            {
              mode = MODE_HEADER; //skip crlf
              continue ;
            }
          else
            {
              ret = DPL_SUCCESS;
              break ;
            }
        }
      else
        {
          line = read_line(conn);
          if (NULL == line)
            {
              DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "read line: %s", dpl_status_str(conn->status));
              ret = DPL_FAILURE;
              goto end;
            }

          switch (mode)
            {
            case MODE_REPLY:

              if (http_parse_reply(line, &http_reply) != 0)
                {
                  DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "bad http reply: %.*s...", 100, line);
                  ret = DPL_FAILURE;
                  goto end;
                }

              DPL_TRACE(conn->ctx, DPL_TRACE_HTTP, "conn=%p http_status=%d", conn, http_reply.code);

              mode = MODE_HEADER;

              break ;

            case MODE_HEADER:

              if (line[0] == '\r')
                {
                  if (1 == chunked)
                    {
                      mode = MODE_CHUNKED;
                    }
                  else
                    {
                      //one big chunk
                      mode = MODE_CHUNK;
                      chunk_off = 0;
                      if (conn->read_buf_pos < conn->cc)
                        {
                          chunk_remain = MIN(conn->cc - conn->read_buf_pos, chunk_len);
                          ret2 = buffer_func(cb_arg, conn->read_buf + conn->read_buf_pos, chunk_remain);
                          if (DPL_SUCCESS != ret2)
                            {
                              DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "buffer_func");
                              ret = DPL_FAILURE;
                              goto end;
                            }
                          conn->read_buf_pos += chunk_remain;
                          chunk_off += chunk_remain;
                        }
                    }

                  break ;
                }

              //headers
              {
                char *p, *p2;

                p = index(line, ':');
                if (NULL == p)
                  {
                    DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "bad header: %.*s...", 100, line);
                    break ;
                  }
                *p++ = 0;

                //skip ws
                for (;*p;p++)
                  if (!isspace(*p))
                    break ;

                //remove '\r'
                p2 = index(p, '\r');
                if (NULL != p2)
                  *p2 = 0;

                DPL_TRACE(conn->ctx, DPL_TRACE_HTTP, "conn=%p header='%s' value='%s'", conn, line, p);

                if (expect_data && !strcasecmp(line, "Content-Length"))
                  {
                    chunk_len = atoi(p);
                  }
                else if (!strcasecmp(line, "Transfer-Encoding"))
                  {
                    if (expect_data)
                      {
                        if (!strcasecmp(p, "chunked"))
                          chunked = 1;
                      }
                  }
                else
                  {
                    ret2 = header_func(cb_arg, line, p);
                    if (DPL_SUCCESS != ret2)
                      {
                        DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "header_func");
                        ret = DPL_FAILURE;
                        goto end;
                      }
                  }
                break ;
              }

            case MODE_CHUNKED:

              chunk_len = strtoul(line, NULL, 16);

              DPL_TRACE(conn->ctx, DPL_TRACE_IO, "chunk_len=%d", chunk_len);

              if (0 == chunk_len)
                {
                  DPRINTF("data done\n");
                  ret = DPL_SUCCESS;
                  goto end;
                }

              mode = MODE_CHUNK;
              chunk_off = 0;
              if (conn->read_buf_pos < conn->cc)
                {
                  chunk_remain = MIN(conn->cc - conn->read_buf_pos, chunk_len);
                  ret2 = buffer_func(cb_arg, conn->read_buf + conn->read_buf_pos, chunk_remain);
                  if (DPL_SUCCESS != ret2)
                    {
                      DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "buffer_func");
                      ret = DPL_FAILURE;
                      goto end;
                    }
                  conn->read_buf_pos += chunk_remain;
                  chunk_off += chunk_remain;
                }
              break ;

            default:
              assert(0);
            }

          free(line);
          line = NULL;
        }
    }

 end:

  if (NULL != line)
    free(line);

  if (DPL_SUCCESS == ret)
    {
      if (NULL != http_statusp)
        *http_statusp = http_reply.code;
    }

  return ret;
}