예제 #1
0
/**
 * This handles requests that are daap-related.  For example,
 * /server-info, /login, etc.  This should really be split up
 * into multiple functions, and perhaps moved into daap.c
 *
 * \param pwsc Webserver connection info, passed from the webserver
 *
 * \todo Decomplexify this!
 */
void daap_handler(WS_CONNINFO *pwsc) {
    int close;
    DAAP_BLOCK *root;
    int clientrev;

    /* for the /databases URI */
    char *uri;
    unsigned long int db_index;
    unsigned long int playlist_index;
    unsigned long int item=0;
    char *first, *last;
    char* index = 0;
    int streaming=0;
    int compress =0;
    int start_time;
    int end_time;
    int bytes_written;

    MP3FILE *pmp3;
    int file_fd;
    int session_id=0;

    int img_fd;
    struct stat sb;
    long img_size;

    off_t offset=0;
    off_t real_len;
    off_t file_len;

    int bytes_copied=0;

    GZIP_STREAM *gz;

    close=pwsc->close;
    pwsc->close=1;  /* in case we have any errors */
    root=NULL;

    ws_addresponseheader(pwsc,"Accept-Ranges","bytes");
    ws_addresponseheader(pwsc,"DAAP-Server","mt-daapd/%s",VERSION);
    ws_addresponseheader(pwsc,"Content-Type","application/x-dmap-tagged");

    if(ws_getvar(pwsc,"session-id")) {
        session_id=atoi(ws_getvar(pwsc,"session-id"));
    }

    if(!strcasecmp(pwsc->uri,"/server-info")) {
        config_set_status(pwsc,session_id,"Sending server info");
        root=daap_response_server_info(config.servername,
                                       ws_getrequestheader(pwsc,"Client-DAAP-Version"));
    } else if (!strcasecmp(pwsc->uri,"/content-codes")) {
        config_set_status(pwsc,session_id,"Sending content codes");
        root=daap_response_content_codes();
    } else if (!strcasecmp(pwsc->uri,"/login")) {
        config_set_status(pwsc,session_id,"Logging in");
        root=daap_response_login(pwsc->hostname);
    } else if (!strcasecmp(pwsc->uri,"/update")) {
        if(!ws_getvar(pwsc,"delta")) { /* first check */
            clientrev=db_version() - 1;
            config_set_status(pwsc,session_id,"Sending database");
        } else {
            clientrev=atoi(ws_getvar(pwsc,"delta"));
            config_set_status(pwsc,session_id,"Waiting for DB updates");
        }
        root=daap_response_update(pwsc->fd,clientrev);
        if((ws_getvar(pwsc,"delta")) && (root==NULL)) {
            DPRINTF(E_LOG,L_WS,"Client %s disconnected\n",pwsc->hostname);
            config_set_status(pwsc,session_id,NULL);
            pwsc->close=1;
            return;
        }
    } else if (!strcasecmp(pwsc->uri,"/logout")) {
        config_set_status(pwsc,session_id,NULL);
        ws_returnerror(pwsc,204,"Logout Successful");
        return;
    } else if(strcmp(pwsc->uri,"/databases")==0) {
        config_set_status(pwsc,session_id,"Sending database info");
        root=daap_response_dbinfo(config.servername);
        if(0 != (index = ws_getvar(pwsc, "index")))
            daap_handle_index(root, index);
    } else if(strncmp(pwsc->uri,"/databases/",11) == 0) {

        /* the /databases/ uri will either be:
         *
         * /databases/id/items, which returns items in a db
         * /databases/id/containers, which returns a container
         * /databases/id/containers/id/items, which returns playlist elements
         * /databases/id/items/id.mp3, to spool an mp3
 * /databases/id/browse/category
         */

        uri = strdup(pwsc->uri);
        first=(char*)&uri[11];
        last=first;
        while((*last) && (*last != '/')) {
            last++;
        }

        if(*last) {
            *last='\0';
            db_index=atoll(first);

            last++;

            if(strncasecmp(last,"items/",6)==0) {
                /* streaming */
                first=last+6;
                while((*last) && (*last != '.'))
                    last++;

                if(*last == '.') {
                    *last='\0';
                    item=atoll(first);
                    streaming=1;
                    DPRINTF(E_DBG,L_DAAP|L_WS,"Streaming request for id %lu\n",item);
                }
                free(uri);
            } else if (strncasecmp(last,"items",5)==0) {
                /* songlist */
                free(uri);
                // pass the meta field request for processing
                // pass the query request for processing
                root=daap_response_songlist(ws_getvar(pwsc,"meta"),
                                            ws_getvar(pwsc,"query"));
                config_set_status(pwsc,session_id,"Sending songlist");
            } else if (strncasecmp(last,"containers/",11)==0) {
                /* playlist elements */
                first=last + 11;
                last=first;
                while((*last) && (*last != '/')) {
                    last++;
                }

                if(*last) {
                    *last='\0';
                    playlist_index=atoll(first);
                    // pass the meta list info for processing
                    root=daap_response_playlist_items(playlist_index,
                                                      ws_getvar(pwsc,"meta"),
                                                      ws_getvar(pwsc,"query"));
                }
                free(uri);
                config_set_status(pwsc,session_id,"Sending playlist info");
            } else if (strncasecmp(last,"containers",10)==0) {
                /* list of playlists */
                free(uri);
                root=daap_response_playlists(config.servername);
                config_set_status(pwsc,session_id,"Sending playlist info");
            } else if (strncasecmp(last,"browse/",7)==0) {
                config_set_status(pwsc,session_id,"Compiling browse info");
                root = daap_response_browse(last + 7,
                                            ws_getvar(pwsc, "filter"));
                config_set_status(pwsc,session_id,"Sending browse info");
                free(uri);
            }
        }

        // prune the full list if an index range was specified
        if(0 != (index = ws_getvar(pwsc, "index")))
            daap_handle_index(root, index);
    }

    if((!root)&&(!streaming)) {
        DPRINTF(E_DBG,L_WS|L_DAAP,"Bad request -- root=%x, streaming=%d\n",root,streaming);
        ws_returnerror(pwsc,400,"Invalid Request");
        config_set_status(pwsc,session_id,NULL);
        return;
    }

    pwsc->close=close;

    if(!streaming) {
        DPRINTF(E_DBG,L_WS,"Satisfying request\n");

        if((config.compress) && ws_testrequestheader(pwsc,"Accept-Encoding","gzip") && root->reported_size >= 1000) {
          compress=1;
        }

        DPRINTF(E_DBG,L_WS|L_DAAP,"Serializing\n");
        start_time = time(NULL);
        if (compress) {
          DPRINTF(E_DBG,L_WS|L_DAAP,"Using compression: %s\n", pwsc->uri);
          gz = gzip_alloc();
          daap_serialize(root,pwsc->fd,gz);
          gzip_compress(gz);
          bytes_written = gz->bytes_out;
          ws_writefd(pwsc,"HTTP/1.1 200 OK\r\n");
          ws_addresponseheader(pwsc,"Content-Length","%d",bytes_written);
          ws_addresponseheader(pwsc,"Content-Encoding","gzip");
          DPRINTF(E_DBG,L_WS,"Emitting headers\n");
          ws_emitheaders(pwsc);
          if (gzip_close(gz,pwsc->fd) != bytes_written) {
            DPRINTF(E_LOG,L_WS|L_DAAP,"Error compressing data\n");
          }
          DPRINTF(E_DBG,L_WS|L_DAAP,"Compression ratio: %f\n",((double) bytes_written)/(8.0 + root->reported_size))
        }
        else {
예제 #2
0
int plugin_ssc_should_transcode(WS_CONNINFO *pwsc, char *codec) {
    int result;
    char *native_codecs=NULL;
    char *user_agent=NULL;
    char *never_transcode = NULL;
    char *always_transcode = NULL;

    ASSERT((pwsc) && (codec));

    if(!pwsc)
        return FALSE;

    if(!codec) {
        DPRINTF(E_LOG,L_PLUG,"testing transcode on null codec?\n");
        return FALSE;
    }

    never_transcode = conf_alloc_string("general","never_transcode",NULL);
    if(never_transcode) {
        if(strstr(never_transcode,codec)) {
            free(never_transcode);
            return FALSE;
        }
        free(never_transcode);
    }

    if(pwsc) {
        /* see if the headers give us any guidance */
        native_codecs = ws_getrequestheader(pwsc,"accept-codecs");
        if(!native_codecs) {
            user_agent = ws_getrequestheader(pwsc,"user-agent");
            if(user_agent) {
                if(strncmp(user_agent,"iTunes",6)==0) {
                    native_codecs = "mpeg,mp4a,wav,mp4v,alac";
                } else if(strncmp(user_agent,"Roku",4)==0) {
                    native_codecs = "mpeg,mp4a,wav,wma";
                } else if(strncmp(user_agent,"Hifidelio",9)==0) {
                    return FALSE;
                }
            }
        }
    }

    if(!native_codecs) {
        native_codecs = "mpeg,wav";
    }

    /* can't transcode it if we can't transcode it */
    if(!_plugin_ssc_codecs)
        return FALSE;

    always_transcode = conf_alloc_string("general","always_transcode",NULL);
    if(always_transcode) {
        if(strstr(always_transcode,codec)) {
            free(always_transcode);
            return TRUE;
        }
        free(always_transcode);
    }

    if(strstr(native_codecs,codec))
        return FALSE;

    result = FALSE;
    if(strstr(_plugin_ssc_codecs,codec)) {
        result = TRUE;
    }
    return result;
}