コード例 #1
0
ファイル: httpfs.c プロジェクト: chx/http-fs-wrapper
int _intercept_open(const char *pathname)
{
    int fd;
    CURLcode ret;
    intercept_t *obj;
    long status;

    RESOLVE(open64);
    RESOLVE(close);

#define ERR_RETURN(err)	do { if (fd >= 0) o_close(fd); errno = err; return -1; } while (0);
#define CURL_SETOPT(option, value) if ((ret = curl_easy_setopt(obj->curl, option, value)) != CURLE_OK) ERR_RETURN(EACCES);

    if ((fd = o_open64("/dev/null", O_RDONLY, 0644)) < 0)
	ERR_RETURN(errno);

    DEBUGF("new fd=%d\n", fd);

    if (fd > HIGHEST_FD)
	ERR_RETURN(EMFILE);

    if (!(obj = calloc(1, sizeof(intercept_t))))
	ERR_RETURN(ENOMEM);

    obj->refcount = 1;
    obj->url = strdup(pathname);

    if (!(obj->curl = curl_easy_init()))
	ERR_RETURN(ENOMEM);

    if (getenv("DEBUG"))
	CURL_SETOPT(CURLOPT_VERBOSE, 0x1);

    CURL_SETOPT(CURLOPT_URL, obj->url);
    CURL_SETOPT(CURLOPT_NOBODY, 0x1);
    CURL_SETOPT(CURLOPT_WRITEHEADER, obj);
    CURL_SETOPT(CURLOPT_HEADERFUNCTION, _curl_parse_header);
    CURL_SETOPT(CURLOPT_WRITEFUNCTION, _curl_output_null);

    if ((ret = curl_easy_perform(obj->curl)) != CURLE_OK)
	ERR_RETURN(EACCES);

    if ((ret = curl_easy_getinfo(obj->curl, CURLINFO_RESPONSE_CODE, &status)) != CURLE_OK || status != 200)
	ERR_RETURN(ENOENT);

    DEBUGF("curl_easy_perform succeeded\n");

    if (!obj->size || !(obj->flags & FEAT_RANGE_SUPPORT))
    {
	DEBUGF("unacceptable resource: size=%zu, flags=%d\n", obj->size, obj->flags);
	ERR_RETURN(ENXIO);
    }

    CURL_SETOPT(CURLOPT_WRITEHEADER, NULL);
    CURL_SETOPT(CURLOPT_HEADERFUNCTION, NULL);

#undef CURL_SETOPT

    intercept[fd] = obj;

    errno = 0;
    return fd;
}
コード例 #2
0
ファイル: httpfs.c プロジェクト: chx/http-fs-wrapper
size_t _intercept_read(int fd, void *buf, size_t count)
{
    char range[512];
    char *start, *finish;
    read_buffer_t read_buf;
    CURLcode ret;
    intercept_t *obj = intercept[fd];
    off_t ra_size;
    long status;

    /* no point reading if we're already at the file boundary */
    if (obj->offset >= obj->size)
	return 0;

    /* don't read over file boundary */
    count = min(obj->size - obj->offset, count);

    /* satisfy from existing readahead buffer if possible */
    if (obj->ra_buf
	&& obj->offset >= obj->ra_fileoffset
	&& obj->offset+count <= obj->ra_fileoffset+obj->ra_size)
    {
	off_t bo = obj->offset - obj->ra_fileoffset;
	memcpy(buf, obj->ra_buf+bo, count);
	obj->offset += count;
	return count;
    }

    /* work out how much we'd like to read ahead */
    ra_size = min(obj->size - obj->offset, READAHEAD_MAX);

    /* format string for range request (inclusive) */
    start = strdup(str_off_t(obj->offset));
    finish = strdup(str_off_t(obj->offset+max(ra_size, count)-1));
    snprintf(range, sizeof(range), "%s-%s", start, finish);
    free(start);
    free(finish);

    /* initialize structure used in _curl_output_buf */
    read_buf.fd = fd;
    read_buf.buf = buf;
    read_buf.size = count;
    read_buf.offset = 0;

    /* throw old readahead buffer away, it didn't cut the mustard */
    if (obj->ra_buf)
    {
	free(obj->ra_buf);
	obj->ra_buf = 0;
    }

    /* someone set us up the bomb */
    if (ra_size > count && (obj->ra_buf = calloc(1, ra_size)))
    {
	obj->ra_size = ra_size;
	obj->ra_offset = 0;
	obj->ra_fileoffset = obj->offset;
    }

#define CURL_SETOPT(option, value) if ((ret = curl_easy_setopt(obj->curl, option, value)) != CURLE_OK) return -1;

    /* setup curl and do request */
    CURL_SETOPT(CURLOPT_HTTPGET, 0x1);
    CURL_SETOPT(CURLOPT_NOBODY, 0x0);
    CURL_SETOPT(CURLOPT_RANGE, range);
    CURL_SETOPT(CURLOPT_WRITEDATA, &read_buf);
    CURL_SETOPT(CURLOPT_WRITEFUNCTION, _curl_output_buf);

    if ((ret = curl_easy_perform(obj->curl)) != CURLE_OK)
	return -1;

    if ((ret = curl_easy_getinfo(obj->curl, CURLINFO_RESPONSE_CODE, &status)) != CURLE_OK || status != 206)
	return -1;

#undef CURL_SETOPT

    DEBUGF("read succeeded. length=%s\n", str_off_t(read_buf.offset));

    /* move offset with read */
    obj->offset += read_buf.offset;

    return read_buf.offset;
}
コード例 #3
0
ファイル: proxy.c プロジェクト: uplusplus/libmicrohttpd
static void
standard_request_handler(void *cls,
                        struct SPDY_Request * request,
                        uint8_t priority,
                        const char *method,
                        const char *path,
                        const char *version,
                        const char *host,
                        const char *scheme,
                        struct SPDY_NameValue * headers)
{
	(void)cls;
	(void)priority;
	(void)host;
	(void)scheme;
	
	struct Proxy *proxy;
	int ret;
  struct URI *uri;
  struct SPDY_Session *session;
	
	PRINT_VERBOSE2("received request for '%s %s %s'\n", method, path, version);
  
	if(NULL == (proxy = malloc(sizeof(struct Proxy))))
        DIE("No memory");
	memset(proxy, 0, sizeof(struct Proxy));
  
  session = SPDY_get_session_for_request(request);
  assert(NULL != session);
  proxy->session_alive = SPDY_get_cls_from_session(session);
  assert(NULL != proxy->session_alive);
  
	proxy->request = request;
	if(NULL == (proxy->headers = SPDY_name_value_create()))
        DIE("No memory");
  
  if(glob_opt.transparent)
  {
    if(NULL != glob_opt.http_backend) //use always same host
      ret = asprintf(&(proxy->url),"%s://%s%s", scheme, glob_opt.http_backend, path);
    else //use host header
      ret = asprintf(&(proxy->url),"%s://%s%s", scheme, host, path);
    if(-1 == ret)
        DIE("No memory");
        
    ret = parse_uri(&uri_preg, proxy->url, &uri);
    if(ret != 0)
      DIE("parsing built uri failed");
  }
  else
  {
    ret = parse_uri(&uri_preg, path, &uri);
    PRINT_INFO2("path %s '%s' '%s'", path, uri->scheme, uri->host);
    if(ret != 0 || !strlen(uri->scheme) || !strlen(uri->host))
      DIE("parsing received uri failed");
      
    if(NULL != glob_opt.http_backend) //use backend host
    {
      ret = asprintf(&(proxy->url),"%s://%s%s", uri->scheme, glob_opt.http_backend, uri->path_and_more);
      if(-1 == ret)
        DIE("No memory");
    }
    else //use request path
      if(NULL == (proxy->url = strdup(path)))
        DIE("No memory");
  }
  
  free_uri(uri);
  
  PRINT_VERBOSE2("curl will request '%s'", proxy->url);
    
  SPDY_name_value_iterate(headers, &iterate_cb, proxy);
	
	if(NULL == (proxy->curl_handle = curl_easy_init()))
    {
		PRINT_INFO("curl_easy_init failed");
		abort();
	}
	
	if(glob_opt.curl_verbose)
    CURL_SETOPT(proxy->curl_handle, CURLOPT_VERBOSE, 1);
	CURL_SETOPT(proxy->curl_handle, CURLOPT_URL, proxy->url);
	if(glob_opt.http10)
		CURL_SETOPT(proxy->curl_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
	CURL_SETOPT(proxy->curl_handle, CURLOPT_WRITEFUNCTION, curl_write_cb);
	CURL_SETOPT(proxy->curl_handle, CURLOPT_WRITEDATA, proxy);
	CURL_SETOPT(proxy->curl_handle, CURLOPT_HEADERFUNCTION, curl_header_cb);
	CURL_SETOPT(proxy->curl_handle, CURLOPT_HEADERDATA, proxy);
	CURL_SETOPT(proxy->curl_handle, CURLOPT_PRIVATE, proxy);
	CURL_SETOPT(proxy->curl_handle, CURLOPT_HTTPHEADER, proxy->curl_headers);
  CURL_SETOPT(proxy->curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
  CURL_SETOPT(proxy->curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);
  if(glob_opt.ipv4 && !glob_opt.ipv6)
    CURL_SETOPT(proxy->curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
  else if(glob_opt.ipv6 && !glob_opt.ipv4)
    CURL_SETOPT(proxy->curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
	
	if(CURLM_OK != (ret = curl_multi_add_handle(multi_handle, proxy->curl_handle)))
	{
		PRINT_INFO2("curl_multi_add_handle failed (%i)", ret);
		abort();
	}
    
  //~5ms additional latency for calling this
	if(CURLM_OK != (ret = curl_multi_perform(multi_handle, &still_running))
		&& CURLM_CALL_MULTI_PERFORM != ret)
	{
		PRINT_INFO2("curl_multi_perform failed (%i)", ret);
		abort();
	}
  
  call_curl_run = true;
}