コード例 #1
0
ファイル: httpreply.c プロジェクト: gnb/Droplet
/**
 * read http reply simple version
 *
 * @param fd
 * @param expect_data
 * @param buffer_provided if 1 then caller provides buffer and length in *data_bufp and *data_lenp
 * @param data_bufp caller must free it
 * @param data_lenp
 * @param headersp caller must free it
 *
 * @return dpl_status
 */
dpl_status_t
dpl_read_http_reply_ext(dpl_conn_t *conn,
                        int expect_data,
                        int buffer_provided,
                        char **data_bufp,
                        unsigned int *data_lenp,
                        dpl_dict_t **headersp,
                        int *connection_closep)
{
  int ret, ret2;
  struct httreply_conven hc;
  int connection_close = 0;
  int http_status;

  memset(&hc, 0, sizeof (hc));

  if (buffer_provided)
    {
      hc.data_buf = *data_bufp;
      hc.max_len = *data_lenp;
    }

  ret2 = dpl_read_http_reply_buffered(conn,
                                      expect_data, 
                                      &http_status, 
                                      cb_httpreply_header, 
                                      buffer_provided ? cb_httpreply_buffer_noalloc : cb_httpreply_buffer, 
                                      &hc);
  if (DPL_SUCCESS != ret2)
    {
      //on I/O failure close connection
      connection_close = 1;

      //blacklist host
      dpl_blacklist_host(conn->ctx, conn->host, conn->port);

      ret = ret2;
      goto end;
    }

  //connection_close might explicitely be requested
  if (dpl_connection_close(hc.headers))
    connection_close = 1;

  //some servers does not send explicit connection information and does not support keep alive
  if (!conn->ctx->keep_alive)
    connection_close = 1;

  //blacklist host with server errors
  if (http_status / 100 == 5)
    dpl_blacklist_host(conn->ctx, conn->host, conn->port);

  //map http_status to relevant value
  ret = dpl_map_http_status(http_status);
  printf("http_status: %d\n", http_status);

 end:

  if (NULL != data_bufp)
    {
      *data_bufp = hc.data_buf;
      hc.data_buf = NULL; //consumed
    }
  
  if (NULL != data_lenp)
    *data_lenp = hc.data_len;
  
  if (NULL != headersp)
    {
      *headersp = hc.headers;
      hc.headers = NULL; //consumed
    }
  
  //if not consumed
  if (NULL != hc.data_buf)
    free(hc.data_buf);

  if (NULL != hc.headers)
    dpl_dict_free(hc.headers);

  if (NULL != connection_closep)
    *connection_closep = connection_close;

  return ret;
}
コード例 #2
0
ファイル: backend.c プロジェクト: pozdnychev/Droplet
dpl_status_t
dpl_s3_get_buffered(dpl_ctx_t *ctx,
                    const char *bucket,
                    const char *resource,
                    const char *subresource,
                    const dpl_option_t *option,
                    dpl_ftype_t object_type,
                    const dpl_condition_t *condition,
                    const dpl_range_t *range,
                    dpl_metadatum_func_t metadatum_func,
                    dpl_dict_t **metadatap,
                    dpl_sysmd_t *sysmdp,
                    dpl_buffer_func_t buffer_func,
                    void *cb_arg,
                    char **locationp)
{
  int           ret, ret2;
  dpl_conn_t   *conn = NULL;
  char          header[dpl_header_size];
  u_int         header_len;
  struct iovec  iov[10];
  int           n_iov = 0;
  dpl_dict_t    *headers_request = NULL;
  dpl_req_t     *req = NULL;
  struct get_conven gc;
  int http_status;
  dpl_s3_req_mask_t req_mask = 0u;

  DPL_TRACE(ctx, DPL_TRACE_BACKEND, "");

  memset(&gc, 0, sizeof (gc));
  gc.metadata = dpl_dict_new(13);
  if (NULL == gc.metadata)
    {
      ret = DPL_ENOMEM;
      goto end;
    }
  gc.sysmdp = sysmdp;
  gc.metadatum_func = metadatum_func;
  gc.buffer_func = buffer_func;
  gc.cb_arg = cb_arg;

  req = dpl_req_new(ctx);
  if (NULL == req)
    {
      ret = DPL_ENOMEM;
      goto end;
    }

  dpl_req_set_method(req, DPL_METHOD_GET);

  if (NULL == bucket)
    {
      ret = DPL_EINVAL;
      goto end;
    }

  ret2 = dpl_req_set_bucket(req, bucket);
  if (DPL_SUCCESS != ret2)
    {
      ret = ret2;
      goto end;
    }

  ret2 = dpl_req_set_resource(req, resource);
  if (DPL_SUCCESS != ret2)
    {
      ret = ret2;
      goto end;
    }

  if (NULL != subresource)
    {
      ret2 = dpl_req_set_subresource(req, subresource);
      if (DPL_SUCCESS != ret2)
        {
          ret = ret2;
          goto end;
        }
    }

  if (NULL != condition)
    {
      dpl_req_set_condition(req, condition);
    }

  //build request
  ret2 = dpl_s3_req_build(req, req_mask, &headers_request);
  if (DPL_SUCCESS != ret2)
    {
      ret = ret2;
      goto end;
    }

  ret2 = dpl_try_connect(ctx, req, &conn);
  if (DPL_SUCCESS != ret2)
    {
      ret = ret2;
      goto end;
    }

  ret2 = dpl_add_host_to_headers(req, headers_request);
  if (DPL_SUCCESS != ret2)
    {
      ret = ret2;
      goto end;
    }

  ret2 = dpl_req_gen_http_request(ctx, req, headers_request, NULL, header, sizeof (header), &header_len);
  if (DPL_SUCCESS != ret2)
    {
      ret = ret2;
      goto end;
    }

  iov[n_iov].iov_base = header;
  iov[n_iov].iov_len = header_len;
  n_iov++;

  //final crlf
  iov[n_iov].iov_base = "\r\n";
  iov[n_iov].iov_len = 2;
  n_iov++;

  ret2 = dpl_conn_writev_all(conn, iov, n_iov, conn->ctx->write_timeout);
  if (DPL_SUCCESS != ret2)
    {
      DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "writev failed");
      gc.connection_close = 1;
      ret = ret2;
      goto end;
    }

  ret2 = dpl_read_http_reply_buffered(conn, 1, &http_status, cb_get_header, cb_get_buffer, &gc);
  if (DPL_SUCCESS != ret2)
    {
      DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "read http answer failed");
      gc.connection_close = 1;
      ret = ret2;
      goto end;
    }

  if (!conn->ctx->keep_alive)
    gc.connection_close = 1;

  if (NULL != metadatap)
    {
      *metadatap = gc.metadata;
      gc.metadata = NULL;
    }
  
  //map http_status to relevant value
  ret = dpl_map_http_status(http_status);

  //caller is responsible for logging the event

 end:

  if (NULL != conn)
    {
      if (1 == gc.connection_close)
        dpl_conn_terminate(conn);
      else
        dpl_conn_release(conn);
    }

  if (NULL != gc.metadata)
    dpl_dict_free(gc.metadata);

  if (NULL != headers_request)
    dpl_dict_free(headers_request);

  if (NULL != req)
    dpl_req_free(req);

  DPL_TRACE(ctx, DPL_TRACE_BACKEND, "ret=%d", ret);

  return ret;
}