Ejemplo n.º 1
0
int connection_bufs_send (connection_t *con, struct connection_bufs *vectors, int skip)
{
    IOVEC *p = vectors->block, old_vals;
    int i = vectors->count,  offset = 0, ret = -1;

    i = connbufs_locate_start (vectors, skip, &old_vals, &offset);
    p = vectors->block + i;

    if (i >= 0)
    {
        if (not_ssl_connection (con))
        {
            ret = sock_writev (con->sock, p, vectors->count - i);
            if (ret < 0 && !sock_recoverable (sock_error()))
                con->error = 1;
        }
#ifdef HAVE_OPENSSL
        else
        {
            IOVEC *io = p;
            int bytes = 0;
            for (; i < vectors->count; i++, io++)
            {
               int v = connection_send_ssl (con, IO_VECTOR_BASE(io), IO_VECTOR_LEN(io));
               if (v > 0) bytes += v;
               if (v < IO_VECTOR_LEN(io)) break;
            }
            if (bytes > 0)  ret = bytes;
        }
#endif
        if (offset)
            *p = old_vals;
        if (ret > 0)
            con->sent_bytes += ret;
    }
    return ret;
}
Ejemplo n.º 2
0
/* client has requested a file, so check for it and send the file.  Do not
 * refer to the client_t afterwards.  return 0 for success, -1 on error.
 */
int fserve_client_create (client_t *httpclient, const char *path)
{
    struct stat file_buf;
    char *fullpath;
    int m3u_requested = 0, m3u_file_available = 1;
    int xspf_requested = 0, xspf_file_available = 1;
    int ret = -1;
    ice_config_t *config;
    fbinfo finfo;
    char fsize[20];

    fullpath = util_get_path_from_normalised_uri (path, 0);
    DEBUG2 ("checking for file %s (%s)", path, fullpath);

    if (strcmp (util_get_extension (fullpath), "m3u") == 0)
        m3u_requested = 1;

    if (strcmp (util_get_extension (fullpath), "xspf") == 0)
        xspf_requested = 1;

    /* check for the actual file */
    if (stat (fullpath, &file_buf) != 0)
    {
        /* the m3u can be generated, but send an m3u file if available */
        if (m3u_requested == 0 && xspf_requested == 0)
        {
            if (redirect_client (path, httpclient) == 0)
            {
                if ((httpclient->flags & CLIENT_SKIP_ACCESSLOG) == 0)
                    WARN2 ("req for file \"%s\" %s", fullpath, strerror (errno));
                ret = client_send_404 (httpclient, "The file you requested could not be found");
            }
            free (fullpath);
            return ret;
        }
        m3u_file_available = 0;
        xspf_file_available = 0;
    }

    client_set_queue (httpclient, NULL);
    httpclient->refbuf = refbuf_new (4096);

    if (m3u_requested && m3u_file_available == 0)
    {
        const char  *host = httpp_getvar (httpclient->parser, "host"),
                    *args = httpp_getvar (httpclient->parser, HTTPP_VAR_QUERYARGS),
                    *at = "", *user = "", *pass ="";
        char *sourceuri = strdup (path);
        char *dot = strrchr (sourceuri, '.');
        char *protocol = not_ssl_connection (&httpclient->connection) ? "http" : "https";
        const char *agent = httpp_getvar (httpclient->parser, "user-agent");
        int x;
        char scratch[1000];

        if (agent)
        {
            if (strstr (agent, "QTS") || strstr (agent, "QuickTime"))
                protocol = "icy";
        }
        /* at least a couple of players (fb2k/winamp) are reported to send a 
         * host header but without the port number. So if we are missing the
         * port then lets treat it as if no host line was sent */
        if (host && strchr (host, ':') == NULL)
            host = NULL;

        *dot = 0;
        if (httpclient->username && httpclient->password)
        {
            at = "@";
            user = httpclient->username;
            pass = httpclient->password;
        }
        httpclient->respcode = 200;
        if (host == NULL)
        {
            config = config_get_config();
            x = snprintf (scratch, sizeof scratch,
                    "%s://%s%s%s%s%s:%d%s%s\r\n",
                    protocol,
                    user, at[0]?":":"", pass, at,
                    config->hostname, config->port,
                    sourceuri,
                    args?args:"");
            config_release_config();
        }
        else
        {
            x = snprintf (scratch, sizeof scratch,
                    "%s://%s%s%s%s%s%s%s\r\n",
                    protocol,
                    user, at[0]?":":"", pass, at,
                    host,
                    sourceuri,
                    args?args:"");
        }
        snprintf (httpclient->refbuf->data, BUFSIZE,
                "HTTP/1.0 200 OK\r\n"
                "Content-Length: %d\r\n"
                "%s\r\n"
                "Content-Type: audio/x-mpegurl\r\n\r\n%s",
                x, client_keepalive_header (httpclient), scratch);
        httpclient->refbuf->len = strlen (httpclient->refbuf->data);
        free (sourceuri);
        free (fullpath);
        return fserve_setup_client_fb (httpclient, NULL);
    }
    if (xspf_requested && xspf_file_available == 0)
    {
        xmlDocPtr doc;
        char *reference = strdup (path);
        char *eol = strrchr (reference, '.');
        if (eol)
            *eol = '\0';
        doc = stats_get_xml (0, reference);
        free (reference);
        free (fullpath);
        return admin_send_response (doc, httpclient, XSLT, "xspf.xsl");
    }

    /* on demand file serving check */
    config = config_get_config();
    if (config->fileserve == 0)
    {
        config_release_config();
        DEBUG1 ("on demand file \"%s\" refused", fullpath);
        free (fullpath);
        return client_send_404 (httpclient, "The file you requested could not be found");
    }
    config_release_config();

    if (S_ISREG (file_buf.st_mode) == 0)
    {
        WARN1 ("found requested file but there is no handler for it: %s", fullpath);
        free (fullpath);
        return client_send_404 (httpclient, "The file you requested could not be found");
    }

    free (fullpath);
    finfo.flags = 0;
    finfo.mount = (char *)path;
    finfo.fallback = NULL;
    finfo.limit = 0;
    finfo.type = FORMAT_TYPE_UNDEFINED;
    snprintf (fsize, 20, "%" PRId64, (int64_t)file_buf.st_size);
    httpp_setvar (httpclient->parser, "__FILESIZE", fsize);
    stats_event_inc (NULL, "file_connections");

    return fserve_setup_client_fb (httpclient, &finfo);
}