Back to index

avfs  1.0.1
Classes | Defines | Functions
http.c File Reference
#include "avfs.h"
#include "version.h"
#include "cache.h"
#include "filebuf.h"
#include "socket.h"
#include "serialfile.h"
#include "internal.h"
#include <stdlib.h>
#include <unistd.h>

Go to the source code of this file.

Classes

struct  httplocalfile
struct  httpentry
struct  httpfs
struct  httpfile

Defines

#define HTTP_READ_TIMEOUT   20000

Functions

static int write_socket (int sock, const char *buf, avsize_t buflen)
static void strip_crlf (char *line)
static int http_get_line (struct httplocalfile *lf, char **linep)
static char * http_split_header (char *line)
static void http_process_header_line (struct httplocalfile *lf, char *line)
static int http_check_header_line (struct httplocalfile *lf)
static int http_ignore_header (struct httplocalfile *lf)
static int http_process_status_line (struct httplocalfile *lf, char *line)
static int http_check_status_line (struct httplocalfile *lf)
static int http_wait_response (struct httplocalfile *lf)
static const char * http_strip_resource_type (const char *url)
static char * http_url_path (const char *url)
static char * http_url_host (const char *url)
static int http_request_get (int sock, struct httpfile *fil)
static void http_stop (struct httplocalfile *lf)
static int http_start (void *data, void **resp)
static avssize_t http_sread (void *data, char *buf, avsize_t nbyte)
static struct sfilehttp_get_serialfile (struct httpfile *fil)
static void http_set_size (struct httpfile *fil, struct sfile *sf)
static struct httpentryhttp_get_entry (struct httpfs *fs, const char *url)
static int begins_with (const char *str, const char *beg)
static char * http_ventry_url (ventry *ve)
static int http_open (ventry *ve, int flags, avmode_t mode, void **resp)
static int http_close (vfile *vf)
static avssize_t http_read (vfile *vf, char *buf, avsize_t nbyte)
static int http_getattr (vfile *vf, struct avstat *buf, int attrmask)
static int http_access (ventry *ve, int amode)
static void http_destroy (struct avfs *avfs)
static int http_proxy_get (struct entry *ent, const char *param, char **retp)
static int http_proxy_set (struct entry *ent, const char *param, const char *val)
static void http_default_proxy (struct httpfs *fs)
int av_init_module_http (struct vmodule *module)

Class Documentation

struct httplocalfile

Definition at line 24 of file http.c.

Collaboration diagram for httplocalfile:
Class Members
struct httpentry * ent
struct filebuf * sockfb
struct httpentry

Definition at line 29 of file http.c.

Collaboration diagram for httpentry:
Class Members
struct cacheobj * cobj
struct httpentry * next
avoff_t size
char * url
struct httpfs

Definition at line 36 of file http.c.

Collaboration diagram for httpfs:
Class Members
struct httpentry * ents
char * proxyname
struct httpfile

Definition at line 41 of file http.c.

Collaboration diagram for httpfile:
Class Members
struct httpentry * ent
struct httpfs * fs

Define Documentation

#define HTTP_READ_TIMEOUT   20000

Definition at line 20 of file http.c.


Function Documentation

int av_init_module_http ( struct vmodule module)

Definition at line 678 of file http.c.

{
    int res;
    struct avfs *avfs;
    struct httpfs *fs;
    struct statefile statf;

    res = av_new_avfs("http", NULL, AV_VER, AVF_ONLYROOT, module, &avfs);
    if(res < 0)
        return res;

    AV_NEW(fs);
    fs->ents = NULL;
    fs->proxyname = NULL;
    
    http_default_proxy(fs);
    statf.get = http_proxy_get;
    statf.set = http_proxy_set;
    statf.data = avfs;
    av_avfsstat_register("http_proxy", &statf);

    avfs->data = (void *) fs;

    avfs->destroy   = http_destroy;
    avfs->open      = http_open;
    avfs->close     = http_close;
    avfs->getattr   = http_getattr;
    avfs->read      = http_read;
    avfs->access    = http_access;

    av_add_avfs(avfs);
    
    return 0;
}

Here is the call graph for this function:

static int begins_with ( const char *  str,
const char *  beg 
) [static]

Definition at line 459 of file http.c.

{
    if(strncmp(str, beg, strlen(beg)) == 0)
        return 1;
    else
        return 0;
}

Here is the caller graph for this function:

static int http_access ( ventry *  ve,
int  amode 
) [static]

Definition at line 584 of file http.c.

{
    if((amode & AVW_OK) != 0)
        return -EACCES;
    
    return 0;
}

Here is the caller graph for this function:

static int http_check_header_line ( struct httplocalfile lf) [static]

Definition at line 142 of file http.c.

{
    int res;
    char *line;

    res = http_get_line(lf, &line);
    if(res < 0)
        return res;

    if(line[0] == '\0')
        res = 0;
    else {
        http_process_header_line(lf, line);
        res = 1;
    }
    av_free(line);

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int http_check_status_line ( struct httplocalfile lf) [static]

Definition at line 222 of file http.c.

{
    int res;
    char *line;

    do {
        res = http_get_line(lf, &line);
        if(res < 0)
            return res;
        
        res = http_process_status_line(lf, line);
        av_free(line);
    } while(res == 0);

    if(res < 0)
        return res;

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int http_close ( vfile *  vf) [static]

Definition at line 518 of file http.c.

{
    struct httpfile *fil = (struct httpfile *) vf->data;

    av_free(fil);

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void http_default_proxy ( struct httpfs fs) [static]

Definition at line 660 of file http.c.

{
    const char *proxyenv;

    proxyenv = getenv("http_proxy");
    if(proxyenv == NULL)
        return;

    if(begins_with(proxyenv, "http://"))
        proxyenv = http_strip_resource_type(proxyenv);
    
    fs->proxyname = av_strdup(proxyenv);

    av_log(AVLOG_DEBUG, "HTTP: proxy = %s", fs->proxyname);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void http_destroy ( struct avfs avfs) [static]

Definition at line 592 of file http.c.

{
    struct httpentry *ent;
    struct httpentry *nextent;
    struct httpfs *fs = (struct httpfs *) avfs->data;

    ent = fs->ents;
    while(ent != NULL) {
        nextent = ent->next;
        av_free(ent->url);
        av_unref_obj(ent->cobj);
        av_free(ent);
        ent = nextent;
    }

    av_free(fs->proxyname);
    av_free(fs);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct httpentry* http_get_entry ( struct httpfs fs,
const char *  url 
) [static, read]

Definition at line 438 of file http.c.

{
    struct httpentry **ep;
    struct httpentry *ent;

    for(ep = &fs->ents; *ep != NULL; ep = &(*ep)->next) {
        ent = *ep;
        if(strcmp(ent->url, url) == 0)
            return ent;
    }

    AV_NEW(ent);
    ent->url = av_strdup(url);
    ent->cobj = NULL;
    ent->next = NULL;
    
    *ep = ent;

    return ent;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int http_get_line ( struct httplocalfile lf,
char **  linep 
) [static]

Definition at line 74 of file http.c.

{
    int res;
    char *line;

    while(1) {        
        res = av_filebuf_readline(lf->sockfb, &line);
        if(res < 0)
            return res;
        if(res == 1)
            break;

        if(av_filebuf_eof(lf->sockfb)) {
            av_log(AVLOG_ERROR, "HTTP: connection closed in header");
            return -EIO;
        }

        res = av_filebuf_check(&lf->sockfb, 1, HTTP_READ_TIMEOUT);
        if(res < 0)
            return res;

        if(res == 0) {
            av_log(AVLOG_ERROR, "HTTP: timeout in header");
            return -EIO;
        }
    }
    
    strip_crlf(line);

    av_log(AVLOG_DEBUG, "HTTP: %s", line);
    *linep = line;

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct sfile* http_get_serialfile ( struct httpfile fil) [static, read]

Definition at line 403 of file http.c.

{
    struct sfile *sf;
    struct httpfile *filcpy;
    struct httpentry *ent = fil->ent;
    static struct sfilefuncs func = {
        http_start,
        http_sread
    };

    sf = (struct sfile *) av_cacheobj_get(ent->cobj);
    if(sf != NULL)
        return sf;

    AV_NEW_OBJ(filcpy, NULL);
    *filcpy = *fil;

    sf = av_sfile_new(&func, filcpy, 0);

    av_unref_obj(ent->cobj);
    ent->cobj = av_cacheobj_new(sf, ent->url);

    return sf;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int http_getattr ( vfile *  vf,
struct avstat buf,
int  attrmask 
) [static]

Definition at line 545 of file http.c.

{
    avoff_t size = -1;
    struct httpfile *fil = (struct httpfile *) vf->data;

    if(attrmask & AVA_SIZE) {
        int res;
        struct sfile *sf;

        sf = http_get_serialfile(fil);
        res = av_sfile_startget(sf);
        if(res < 0)
            return res;

        size = fil->ent->size;
        if(size == -1)
            size = av_sfile_size(sf);

        http_set_size(fil, sf);
        av_unref_obj(sf);
    }

    buf->dev = 1;
    buf->ino = 1;
    buf->mode = AV_IFREG | 0777;
    buf->nlink = 1;
    buf->uid = 0;
    buf->gid = 0;
    buf->size = size;
    buf->blksize = 512;
    buf->blocks = AV_BLOCKS(size);
    buf->atime.sec = 0;
    buf->atime.nsec = 0;
    buf->mtime = buf->atime;
    buf->ctime = buf->atime;

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int http_ignore_header ( struct httplocalfile lf) [static]

Definition at line 162 of file http.c.

{
    int res;
    char *line;
    int end = 0;

    do {
        res = http_get_line(lf, &line);
        if(res < 0)
            return res;

        if(line[0] == '\0')
            end = 1;

        av_free(line);
    } while(!end);

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int http_open ( ventry *  ve,
int  flags,
avmode_t  mode,
void **  resp 
) [static]

Definition at line 488 of file http.c.

{
    int res;
    char *url;
    struct httpfs *fs = (struct httpfs *) ve->mnt->avfs->data;
    struct httpfile *fil;
    struct sfile *sf;

    url = http_ventry_url(ve);
    if(url == NULL)
        return -ENOENT;

    AV_NEW(fil);
    fil->ent = http_get_entry(fs, url);
    fil->fs = fs;
    av_free(url);

    sf = http_get_serialfile(fil);
    res = av_sfile_startget(sf);
    http_set_size(fil, sf);
    av_unref_obj(sf);

    if(res == 0) 
        *resp = (void *) fil;
    else 
        av_free(fil);

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void http_process_header_line ( struct httplocalfile lf,
char *  line 
) [static]

Definition at line 124 of file http.c.

{
    char *s;

    s = http_split_header(line);

    if(strcasecmp("content-length:", line) == 0) {
        char *end;
        avoff_t size;
        size = strtol(s, &end, 10);
        while(*end && isspace((unsigned char) *end))
            end++;
        
        if(!*end)
            lf->ent->size = size;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int http_process_status_line ( struct httplocalfile lf,
char *  line 
) [static]

Definition at line 182 of file http.c.

{
    const char *s;
    int statuscode;
    int res;

    for(s = line; *s && *s != ' '; s++);

    if(s[0] != ' ' || 
       !isdigit((unsigned char) s[1]) || 
       !isdigit((unsigned char) s[2]) || 
       !isdigit((unsigned char) s[3])) {
        av_log(AVLOG_ERROR, "HTTP: bad status code: %s", s);
        return -EIO;
    }
    
    statuscode = (s[1] - '0') * 100 + (s[2] - '0') * 10 + (s[3] - '0');
    
    av_log(AVLOG_DEBUG, "HTTP: status code: %i", statuscode);

    if(statuscode / 100 == 1) {
        res = http_ignore_header(lf);
        if(res < 0)
            return res;
        
        return 0;
    }
    
    if(statuscode / 100 == 2)
        return 1;

    av_log(AVLOG_WARNING, "HTTP: error: %s", s);
    http_ignore_header(lf);

    if(statuscode / 100 == 3 || statuscode / 100 == 4)
        return -ENOENT;

    return -EIO;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int http_proxy_get ( struct entry ent,
const char *  param,
char **  retp 
) [static]

Definition at line 611 of file http.c.

{
    struct statefile *sf = (struct statefile *) av_namespace_get(ent);
    struct avfs *avfs = (struct avfs *) sf->data;
    struct httpfs *fs = (struct httpfs *) avfs->data;
    char *s;
    
    AV_LOCK(avfs->lock);
    if(fs->proxyname != NULL)
        s = av_stradd(NULL, fs->proxyname, "\n", NULL);
    else
        s = av_strdup("");
    AV_UNLOCK(avfs->lock);

    *retp = s;

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int http_proxy_set ( struct entry ent,
const char *  param,
const char *  val 
) [static]

Definition at line 630 of file http.c.

{
    struct statefile *sf = (struct statefile *) av_namespace_get(ent);
    struct avfs *avfs = (struct avfs *) sf->data;
    struct httpfs *fs = (struct httpfs *) avfs->data;
    char *s;
    unsigned int len;

    if(begins_with(val, "http://"))
        val = http_strip_resource_type(val);

    s = av_strdup(val);
    len = strlen(s);
    if(len > 0 && s[len-1] == '\n')
        s[len-1] = '\0';
    
    if(s[0] == '\0') {
        av_free(s);
        s = NULL;
    }
    
    AV_LOCK(avfs->lock);
    av_free(fs->proxyname);
    fs->proxyname = s;
    AV_UNLOCK(avfs->lock);

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static avssize_t http_read ( vfile *  vf,
char *  buf,
avsize_t  nbyte 
) [static]

Definition at line 528 of file http.c.

{
    avssize_t res;
    struct httpfile *fil = (struct httpfile *) vf->data;
    struct sfile *sf;

    sf = http_get_serialfile(fil);
    res = av_sfile_pread(sf, buf, nbyte, vf->ptr);
    http_set_size(fil, sf);
    av_unref_obj(sf);

    if(res > 0)
        vf->ptr += res;

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int http_request_get ( int  sock,
struct httpfile fil 
) [static]

Definition at line 293 of file http.c.

{
    int res;
    char *req;
    char *url;
    char *host;
    
    if(fil->fs->proxyname != NULL)
        url = av_strdup(fil->ent->url);
    else
        url = http_url_path(fil->ent->url);

    host = http_url_host(fil->ent->url);

    req = av_stradd(NULL, 
                      "GET ", url, " HTTP/1.1\r\n",
                      "Host: ", host, "\r\n"
                      "Connection: close\r\n"
                      "\r\n",
                      NULL);

    av_free(url);
    av_free(host);

    av_log(AVLOG_DEBUG, "HTTP: %s", req);

    res = write_socket(sock, req, strlen(req));
    av_free(req);

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void http_set_size ( struct httpfile fil,
struct sfile sf 
) [static]

Definition at line 428 of file http.c.

{
    struct httpentry *ent = fil->ent;
    avoff_t du;

    du = av_sfile_diskusage(sf);
    if(du >= 0)
        av_cacheobj_setsize(ent->cobj, du);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* http_split_header ( char *  line) [static]

Definition at line 109 of file http.c.

{
    char *s;

    for(s = line; *s && !isspace((unsigned char) *s); s++);
    if(*s) {
        do {
            *s = '\0';
            s++;
        } while(isspace((unsigned char) *s));
    }
    
    return s;
}

Here is the caller graph for this function:

static avssize_t http_sread ( void *  data,
char *  buf,
avsize_t  nbyte 
) [static]

Definition at line 380 of file http.c.

{
    avssize_t res;
    struct httplocalfile *lf = (struct httplocalfile *) data;

    do {
        res = av_filebuf_read(lf->sockfb, buf, nbyte);
        if(res != 0)
            return res;
        
        if(av_filebuf_eof(lf->sockfb))
            return 0;
        
        res = av_filebuf_check(&lf->sockfb, 1, HTTP_READ_TIMEOUT);
        if(res < 0)
            return res;
        
    } while(res == 1);

    av_log(AVLOG_ERROR, "HTTP: timeout in body");
    return -EIO;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int http_start ( void *  data,
void **  resp 
) [static]

Definition at line 331 of file http.c.

{
    int res;
    int sock;
    int defaultport;
    char *host;
    struct httpfile *fil = (struct httpfile *) data;
    struct httplocalfile *lf;

    if(fil->fs->proxyname != NULL) {
        host = av_strdup(fil->fs->proxyname);
        defaultport = 8000;
    }
    else {
        host = http_url_host(fil->ent->url);
        defaultport = 80;
    }

    res = av_sock_connect(host, defaultport);
    av_free(host);
    if(res < 0)
        return res;

    sock = res;
    av_registerfd(sock);

    res = http_request_get(sock, fil);
    if(res < 0) {
        close(sock);
        return res;
    }

    fil->ent->size = -1;

    AV_NEW_OBJ(lf, http_stop);
    lf->sockfb = av_filebuf_new(sock, 0);
    lf->ent = fil->ent;

    res = http_wait_response(lf);
    if(res < 0) {
        av_unref_obj(lf);
        return res;
    }

    *resp = lf;
    
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void http_stop ( struct httplocalfile lf) [static]

Definition at line 326 of file http.c.

{
    av_unref_obj(lf->sockfb);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static const char* http_strip_resource_type ( const char *  url) [static]

Definition at line 256 of file http.c.

{
    const char *s;

    for(s = url; *s && *s != ':'; s++);
    if(*s)
        s++;
    for(; *s == '/'; s++);
    
    return s;
}

Here is the caller graph for this function:

static char* http_url_host ( const char *  url) [static]

Definition at line 280 of file http.c.

{
    const char *s;
    const char *t;
    
    s = http_strip_resource_type(url);
    t = strchr(s, '/');
    if(t == NULL)
        return av_strdup(s);
    else
        return av_strndup(s, t - s);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* http_url_path ( const char *  url) [static]

Definition at line 268 of file http.c.

{
    const char *s;

    s = http_strip_resource_type(url);
    s = strchr(s, '/');
    if(s == NULL)
        return av_strdup("/");
    else
        return av_strdup(s);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* http_ventry_url ( ventry *  ve) [static]

Definition at line 467 of file http.c.

{
    char *url = av_strdup((char *) ve->data);
    char *s;

    for(s = url; *s; s++) {
        if(*s == '|')
            *s = '/';
    }
    
    if(!begins_with(url, "http://") && !begins_with(url, "ftp://")) {
        char *newurl;

        newurl = av_stradd(NULL, "http://", url, NULL);
        av_free(url);
        url = newurl;
    }

    return url;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int http_wait_response ( struct httplocalfile lf) [static]

Definition at line 242 of file http.c.

{
    int res;

    res = http_check_status_line(lf);
    if(res < 0)
        return res;

    do res = http_check_header_line(lf);
    while(res == 1);

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void strip_crlf ( char *  line) [static]

Definition at line 62 of file http.c.

{
    avsize_t len = strlen(line);
    
    if(len > 0 && line[len-1] == '\n') {
        if(len > 1 && line[len-2] == '\r')
            line[len-2] = '\0';
        else
            line[len-1] = '\0';
    }
}

Here is the caller graph for this function:

static int write_socket ( int  sock,
const char *  buf,
avsize_t  buflen 
) [static]

Definition at line 46 of file http.c.

{
    int res;

    while(buflen > 0) {
        res = write(sock, buf, buflen);
        if(res == -1)
            return -errno;
        
        buf += res;
        buflen -= res;
    }

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function: