Esempio n. 1
0
void fserve_shutdown(void)
{
    if (!__inited)
        return;

    thread_spin_lock (&pending_lock);
    run_fserv = 0;
    while (pending_list)
    {
        fserve_t *to_go = (fserve_t *)pending_list;
        pending_list = to_go->next;

        fserve_client_destroy (to_go);
    }
    while (active_list)
    {
        fserve_t *to_go = active_list;
        active_list = to_go->next;
        fserve_client_destroy (to_go);
    }

    if (mimetypes)
        avl_tree_free (mimetypes, _delete_mapping);

    thread_spin_unlock (&pending_lock);
    thread_spin_destroy (&pending_lock);
    ICECAST_LOG_INFO("file serving stopped");
}
Esempio n. 2
0
int fserve_client_create(client_t *httpclient, char *path)
{
    fserve_t *client = calloc(1, sizeof(fserve_t));
    int bytes;
    int client_limit;
    ice_config_t *config = config_get_config();

    client_limit = config->client_limit;
    config_release_config();

    client->file = fopen(path, "rb");
    if(!client->file) {
        client_send_404(httpclient, "File not readable");
        return -1;
    }

    client->client = httpclient;
    client->offset = 0;
    client->datasize = 0;
    client->ready = 0;
    client->buf = malloc(BUFSIZE);

    global_lock();
    if(global.clients >= client_limit) {
        httpclient->respcode = 504;
        bytes = sock_write(httpclient->con->sock,
                "HTTP/1.0 504 Server Full\r\n"
                "Content-Type: text/html\r\n\r\n"
                "<b>Server is full, try again later.</b>\r\n");
        if(bytes > 0) httpclient->con->sent_bytes = bytes;
        fserve_client_destroy(client);
        global_unlock();
        return -1;
    }
    global.clients++;
    global_unlock();

    httpclient->respcode = 200;
    bytes = sock_write(httpclient->con->sock,
            "HTTP/1.0 200 OK\r\n"
            "Content-Type: %s\r\n\r\n",
            fserve_content_type(path));
    if(bytes > 0) httpclient->con->sent_bytes = bytes;

    sock_set_blocking(client->client->con->sock, SOCK_NONBLOCK);
    sock_set_nodelay(client->client->con->sock);

    thread_mutex_lock (&pending_lock);
    client->next = (fserve_t *)pending_list;
    pending_list = client;
    thread_mutex_unlock (&pending_lock);

    return 0;
}
Esempio n. 3
0
static int _free_client(void *key)
{
    fserve_t *client = (fserve_t *)key;

    fserve_client_destroy(client);
    global_lock();
    global.clients--;
    global_unlock();
    stats_event_dec(NULL, "clients");

    
    return 1;
}
Esempio n. 4
0
static void *fserv_thread_function(void *arg)
{
    fserve_t *fclient, **trail;
    size_t bytes;

    (void)arg;

    while (1)
    {
        if (wait_for_fds() < 0)
            break;

        fclient = active_list;
        trail = &active_list;

        while (fclient)
        {
            /* process this client, if it is ready */
            if (fclient->ready)
            {
                client_t *client = fclient->client;
                refbuf_t *refbuf = client->refbuf;
                fclient->ready = 0;
                if (client->pos == refbuf->len)
                {
                    /* Grab a new chunk */
                    if (fclient->file)
                        bytes = fread (refbuf->data, 1, BUFSIZE, fclient->file);
                    else
                        bytes = 0;
                    if (bytes == 0)
                    {
                        if (refbuf->next == NULL)
                        {
                            fserve_t *to_go = fclient;
                            fclient = fclient->next;
                            *trail = fclient;
                            fserve_client_destroy (to_go);
                            fserve_clients--;
                            client_tree_changed = 1;
                            continue;
                        }
                        refbuf = refbuf->next;
                        client->refbuf->next = NULL;
                        refbuf_release (client->refbuf);
                        client->refbuf = refbuf;
                        bytes = refbuf->len;
                    }
                    refbuf->len = (unsigned int)bytes;
                    client->pos = 0;
                }

                /* Now try and send current chunk. */
                format_generic_write_to_client (client);

                if (client->con->error)
                {
                    fserve_t *to_go = fclient;
                    fclient = fclient->next;
                    *trail = fclient;
                    fserve_clients--;
                    fserve_client_destroy (to_go);
                    client_tree_changed = 1;
                    continue;
                }
            }
            trail = &fclient->next;
            fclient = fclient->next;
        }
    }
    ICECAST_LOG_DEBUG("fserve handler exit");
    return NULL;
}
Esempio n. 5
0
int fserve_client_create(client_t *httpclient, char *path)
{
    fserve_t *client = calloc(1, sizeof(fserve_t));
    int bytes;
    int client_limit;
    ice_config_t *config = config_get_config();
    struct stat file_buf;
    char *range = NULL;
    int64_t new_content_len = 0;
    int64_t rangenumber = 0;
    int rangeproblem = 0;
    int ret = 0;

    client_limit = config->client_limit;
    config_release_config();

    client->file = fopen(path, "rb");
    if(!client->file) {
        client_send_404(httpclient, "File not readable");
        return -1;
    }

    client->client = httpclient;
    client->offset = 0;
    client->datasize = 0;
    client->ready = 0;
    client->content_length = 0;
    client->buf = malloc(BUFSIZE);
    if (stat(path, &file_buf) == 0) {
        client->content_length = (int64_t)file_buf.st_size;
    }

    global_lock();
    if(global.clients >= client_limit) {
        global_unlock();
        httpclient->respcode = 504;
        bytes = sock_write(httpclient->con->sock,
                "HTTP/1.0 504 Server Full\r\n"
                "Content-Type: text/html\r\n\r\n"
                "<b>Server is full, try again later.</b>\r\n");
        if(bytes > 0) httpclient->con->sent_bytes = bytes;
        fserve_client_destroy(client);
        return -1;
    }
    global.clients++;
    global_unlock();

    range = httpp_getvar (client->client->parser, "range");

    if (range != NULL) {
        ret = sscanf(range, "bytes=" FORMAT_INT64 "-", &rangenumber);
        if (ret != 1) {
            /* format not correct, so lets just assume
               we start from the beginning */
            rangeproblem = 1;
        }
        if (rangenumber < 0) {
            rangeproblem = 1;
        }
        if (!rangeproblem) {
            ret = fseek(client->file, rangenumber, SEEK_SET);
            if (ret != -1) {
                new_content_len = client->content_length - rangenumber;
                if (new_content_len < 0) {
                    rangeproblem = 1;
                }
            }
            else {
                rangeproblem = 1;
            }
            if (!rangeproblem) {
                /* Date: is required on all HTTP1.1 responses */
                char currenttime[50];
                time_t now;
                int strflen;
                struct tm result;
                int64_t endpos = rangenumber+new_content_len-1;
                if (endpos < 0) {
                    endpos = 0;
                }
                time(&now);
                strflen = strftime(currenttime, 50, "%a, %d-%b-%Y %X GMT",
                                   gmtime_r(&now, &result));
                httpclient->respcode = 206;
                bytes = sock_write(httpclient->con->sock,
                    "HTTP/1.1 206 Partial Content\r\n"
                    "Date: %s\r\n"
                    "Content-Length: " FORMAT_INT64 "\r\n"
                    "Content-Range: bytes " FORMAT_INT64 \
                    "-" FORMAT_INT64 "/" FORMAT_INT64 "\r\n"
                    "Content-Type: %s\r\n\r\n",
                    currenttime,
                    new_content_len,
                    rangenumber,
                    endpos,
                    client->content_length,
                    fserve_content_type(path));
                if(bytes > 0) httpclient->con->sent_bytes = bytes;
            }
            else {
                httpclient->respcode = 416;
                bytes = sock_write(httpclient->con->sock,
                    "HTTP/1.0 416 Request Range Not Satisfiable\r\n\r\n");
                if(bytes > 0) httpclient->con->sent_bytes = bytes;
                fserve_client_destroy(client);
                return -1;
            }
        }
        else {
            /* If we run into any issues with the ranges
               we fallback to a normal/non-range request */
            httpclient->respcode = 416;
            bytes = sock_write(httpclient->con->sock,
                "HTTP/1.0 416 Request Range Not Satisfiable\r\n\r\n");
            if(bytes > 0) httpclient->con->sent_bytes = bytes;
            fserve_client_destroy(client);
            return -1;
        }
    }
    else {

        httpclient->respcode = 200;
        bytes = sock_write(httpclient->con->sock,
            "HTTP/1.0 200 OK\r\n"
            "Content-Length: " FORMAT_INT64 "\r\n"
            "Content-Type: %s\r\n\r\n",
            client->content_length,
            fserve_content_type(path));
        if(bytes > 0) httpclient->con->sent_bytes = bytes;
    }

    sock_set_blocking(client->client->con->sock, SOCK_NONBLOCK);
    sock_set_nodelay(client->client->con->sock);

    thread_mutex_lock (&pending_lock);
    client->next = (fserve_t *)pending_list;
    pending_list = client;
    thread_mutex_unlock (&pending_lock);

    return 0;
}