Beispiel #1
0
static int ping(struct backend *s, const char *userid)
{
    unsigned code = 0;
    const char *errstr;
    hdrcache_t resp_hdrs = NULL;
    struct body_t resp_body;

    /* Send Authorization request to server */
    prot_puts(s->out, "OPTIONS * HTTP/1.1\r\n");
    prot_printf(s->out, "Host: %s\r\n", s->hostname);
    prot_printf(s->out, "User-Agent: %s\r\n", buf_cstring(&serverinfo));
    prot_printf(s->out, "Authorize-As: %s\r\n", userid ? userid : "anonymous");
    prot_puts(s->out, "\r\n");
    prot_flush(s->out);

    /* Read response(s) from backend until final response or error */
    do {
        resp_body.flags = BODY_DISCARD;
        if (http_read_response(s, METH_OPTIONS, &code, NULL,
                               &resp_hdrs, &resp_body, &errstr)) {
            break;
        }
    } while (code < 200);

    if (resp_hdrs) spool_free_hdrcache(resp_hdrs);

    return (code != 200);
}
Beispiel #2
0
int httpreq(char** buffer, size_t* length)
{
  int socket_fd;
  size_t request_text_length;

  if ((socket_fd = http_connect(LFM_HOST)) < 0) {
    LOG(LOG_CRITICAL, "Could not connect to %s.", LFM_HOST);
    exit(ERROR);
  }

  http_request(NEW_RELEASE_URL, strlen(NEW_RELEASE_URL),
               LFM_HOST, strlen(LFM_HOST), buffer, &request_text_length);

  if (http_send_request(socket_fd, *buffer, request_text_length) == -1) {
    LOG(LOG_CRITICAL, "Could not send request.");
    exit(ERROR);
  }

  free(*buffer);

  if (http_read_response(socket_fd, buffer, length)) {
    LOG(LOG_CRITICAL, "Could not read request");
    exit(ERROR);
  }

  http_close(socket_fd);

  return OK;
}
Beispiel #3
0
static int cddb_http_request(char *command,
                      int (*reply_parser)(HTTP_header_t*, cddb_data_t*),
                      cddb_data_t *cddb_data)
{
    char request[4096];
    int fd, ret = 0;
    URL_t *url;
    HTTP_header_t *http_hdr;

    if (reply_parser == NULL || command == NULL || cddb_data == NULL)
        return -1;

    sprintf(request, "http://%s/~cddb/cddb.cgi?cmd=%s%s&proto=%d",
            cddb_data->freedb_server, command, cddb_data->cddb_hello,
            cddb_data->freedb_proto_level);
    mp_msg(MSGT_OPEN, MSGL_INFO,"Request[%s]\n", request);

    url = url_new(request);
    if (url == NULL) {
        mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_NotAValidURL);
        return -1;
    }

    fd = http_send_request(url,0);
    if (fd < 0) {
        mp_msg(MSGT_DEMUX, MSGL_ERR,
               MSGTR_MPDEMUX_CDDB_FailedToSendHTTPRequest);
        return -1;
    }

    http_hdr = http_read_response(fd);
    if (http_hdr == NULL) {
        mp_msg(MSGT_DEMUX, MSGL_ERR,
               MSGTR_MPDEMUX_CDDB_FailedToReadHTTPResponse);
        return -1;
    }

    http_debug_hdr(http_hdr);
    mp_msg(MSGT_OPEN, MSGL_INFO,"body=[%s]\n", http_hdr->body);

    switch (http_hdr->status_code) {
    case 200:
        ret = reply_parser(http_hdr, cddb_data);
        break;
    case 400:
        mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_HTTPErrorNOTFOUND);
        break;
    default:
        mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_HTTPErrorUnknown);
    }

    http_free(http_hdr);
    url_free(url);

    return ret;
}
Beispiel #4
0
static int cddb_http_request(char *command,
                      int (*reply_parser)(HTTP_header_t*, cddb_data_t*),
                      cddb_data_t *cddb_data)
{
    char request[4096];
    int fd, ret = 0;
    URL_t *url;
    HTTP_header_t *http_hdr;

    if (reply_parser == NULL || command == NULL || cddb_data == NULL)
        return -1;

    sprintf(request, "http://%s/~cddb/cddb.cgi?cmd=%s%s&proto=%d",
            cddb_data->freedb_server, command, cddb_data->cddb_hello,
            cddb_data->freedb_proto_level);
    mp_msg(MSGT_OPEN, MSGL_INFO,"Request[%s]\n", request);

    url = url_new(request);
    if (url == NULL) {
        mp_tmsg(MSGT_DEMUX, MSGL_ERR, "not a valid URL\n");
        return -1;
    }

    fd = http_send_request(url,0);
    if (fd < 0) {
        mp_tmsg(MSGT_DEMUX, MSGL_ERR, "Failed to send the HTTP request.\n");
        return -1;
    }

    http_hdr = http_read_response(fd);
    if (http_hdr == NULL) {
        mp_tmsg(MSGT_DEMUX, MSGL_ERR, "Failed to read the HTTP response.\n");
        return -1;
    }

    http_debug_hdr(http_hdr);
    mp_msg(MSGT_OPEN, MSGL_INFO,"body=[%s]\n", http_hdr->body);

    switch (http_hdr->status_code) {
    case 200:
        ret = reply_parser(http_hdr, cddb_data);
        break;
    case 400:
        mp_tmsg(MSGT_DEMUX, MSGL_ERR, "Not Found.\n");
        break;
    default:
        mp_tmsg(MSGT_DEMUX, MSGL_ERR, "unknown error code\n");
    }

    http_free(http_hdr);
    url_free(url);

    return ret;
}
Beispiel #5
0
int
http_seek( stream_t *stream, off_t pos ) {
	HTTP_header_t *http_hdr = NULL;
	int fd;
	if( stream==NULL ) return 0;

	if( stream->fd>0 ) closesocket(stream->fd); // need to reconnect to seek in http-stream
	fd = http_send_request( stream->streaming_ctrl->url, pos );
	if( fd<0 ) return 0;

	http_hdr = http_read_response( fd );

	if( http_hdr==NULL ) return 0;

	if( mp_msg_test(MSGT_NETWORK,MSGL_V) )
		http_debug_hdr( http_hdr );

	switch( http_hdr->status_code ) {
		case 200:
		case 206: // OK
			mp_msg(MSGT_NETWORK,MSGL_V,"Content-Type: [%s]\n", http_get_field(http_hdr, "Content-Type") );
			mp_msg(MSGT_NETWORK,MSGL_V,"Content-Length: [%s]\n", http_get_field(http_hdr, "Content-Length") );
			if( http_hdr->body_size>0 ) {
				if( streaming_bufferize( stream->streaming_ctrl, http_hdr->body, http_hdr->body_size )<0 ) {
					http_free( http_hdr );
					return -1;
				}
			}
			break;
		default:
			mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ErrServerReturned, http_hdr->status_code, http_hdr->reason_phrase );
			closesocket( fd );
			fd = -1;
	}
	stream->fd = fd;

	if( http_hdr ) {
		http_free( http_hdr );
		stream->streaming_ctrl->data = NULL;
	}

	stream->pos=pos;

	return 1;
}
Beispiel #6
0
static int login(struct backend *s, const char *userid,
                 sasl_callback_t *cb, const char **status,
                 int noauth __attribute__((unused)))
{
    int r = 0;
    socklen_t addrsize;
    struct sockaddr_storage saddr_l, saddr_r;
    char remoteip[60], localip[60];
    static struct buf buf = BUF_INITIALIZER;
    sasl_security_properties_t secprops =
        { 0, 0xFF, PROT_BUFSIZE, 0, NULL, NULL }; /* default secprops */
    const char *mech_conf, *pass, *clientout = NULL;
    struct auth_scheme_t *scheme = NULL;
    unsigned need_tls = 0, tls_done = 0, auth_done = 0, clientoutlen;
    hdrcache_t hdrs = NULL;

    if (status) *status = NULL;

    /* set the IP addresses */
    addrsize = sizeof(struct sockaddr_storage);
    if (getpeername(s->sock, (struct sockaddr *) &saddr_r, &addrsize) ||
        iptostring((struct sockaddr *) &saddr_r, addrsize, remoteip, 60)) {
        if (status) *status = "Failed to get remote IP address";
        return SASL_FAIL;
    }

    addrsize = sizeof(struct sockaddr_storage);
    if (getsockname(s->sock, (struct sockaddr *) &saddr_l, &addrsize) ||
        iptostring((struct sockaddr *) &saddr_l, addrsize, localip, 60)) {
        if (status) *status = "Failed to get local IP address";
        return SASL_FAIL;
    }

    /* Create callbacks, if necessary */
    if (!cb) {
        buf_setmap(&buf, s->hostname, strcspn(s->hostname, "."));
        buf_appendcstr(&buf, "_password");
        pass = config_getoverflowstring(buf_cstring(&buf), NULL);
        if (!pass) pass = config_getstring(IMAPOPT_PROXY_PASSWORD);
        cb = mysasl_callbacks(NULL, /* userid */
                              config_getstring(IMAPOPT_PROXY_AUTHNAME),
                              config_getstring(IMAPOPT_PROXY_REALM),
                              pass);
        s->sasl_cb = cb;
    }

    /* Create SASL context */
    r = sasl_client_new(s->prot->sasl_service, s->hostname,
                        localip, remoteip, cb, SASL_USAGE_FLAGS, &s->saslconn);
    if (r != SASL_OK) goto done;

    r = sasl_setprop(s->saslconn, SASL_SEC_PROPS, &secprops);
    if (r != SASL_OK) goto done;

    /* Get SASL mechanism list.  We can force a particular
       mechanism using a <shorthost>_mechs option */
    buf_setmap(&buf, s->hostname, strcspn(s->hostname, "."));
    buf_appendcstr(&buf, "_mechs");
    if (!(mech_conf = config_getoverflowstring(buf_cstring(&buf), NULL))) {
        mech_conf = config_getstring(IMAPOPT_FORCE_SASL_CLIENT_MECH);
    }

    do {
        unsigned code;
        const char **hdr, *errstr, *serverin;
        char base64[BASE64_BUF_SIZE+1];
        unsigned int serverinlen;
        struct body_t resp_body;
#ifdef SASL_HTTP_REQUEST
        sasl_http_request_t httpreq = { "OPTIONS",      /* Method */
                                        "*",            /* URI */
                                        (u_char *) "",  /* Empty body */
                                        0,              /* Zero-length body */
                                        0 };            /* Persistent cxn? */
#endif

        /* Base64 encode any client response, if necessary */
        if (clientout && scheme && (scheme->flags & AUTH_BASE64)) {
            r = sasl_encode64(clientout, clientoutlen,
                              base64, BASE64_BUF_SIZE, &clientoutlen);
            if (r != SASL_OK) break;

            clientout = base64;
        }

        /* Send Authorization and/or Upgrade request to server */
        prot_puts(s->out, "OPTIONS * HTTP/1.1\r\n");
        prot_printf(s->out, "Host: %s\r\n", s->hostname);
        prot_printf(s->out, "User-Agent: %s\r\n", buf_cstring(&serverinfo));
        if (scheme) {
            prot_printf(s->out, "Authorization: %s %s\r\n",
                        scheme->name, clientout ? clientout : "");
            prot_printf(s->out, "Authorize-As: %s\r\n",
                        userid ? userid : "anonymous");
        }
        else {
            prot_printf(s->out, "Upgrade: %s\r\n", TLS_VERSION);
            if (need_tls) {
                prot_puts(s->out, "Connection: Upgrade\r\n");
                need_tls = 0;
            }
            prot_puts(s->out, "Authorization: \r\n");
        }
        prot_puts(s->out, "\r\n");
        prot_flush(s->out);

        serverin = clientout = NULL;
        serverinlen = clientoutlen = 0;

        /* Read response(s) from backend until final response or error */
        do {
            resp_body.flags = BODY_DISCARD;
            r = http_read_response(s, METH_OPTIONS, &code, NULL,
                                   &hdrs, &resp_body, &errstr);
            if (r) {
                if (status) *status = errstr;
                break;
            }

            if (code == 101) {  /* Switching Protocols */
                if (tls_done) {
                    r = HTTP_BAD_GATEWAY;
                    if (status) *status = "TLS already active";
                    break;
                }
                else if (backend_starttls(s, NULL, NULL, NULL)) {
                    r = HTTP_SERVER_ERROR;
                    if (status) *status = "Unable to start TLS";
                    break;
                }
                else tls_done = 1;
            }
        } while (code < 200);

        switch (code) {
        default: /* Failure */
            if (!r) {
                r = HTTP_BAD_GATEWAY;
                if (status) {
                    buf_reset(&buf);
                    buf_printf(&buf,
                               "Unexpected status code from backend: %u", code);
                    *status = buf_cstring(&buf);
                }
            }
            break;

        case 426: /* Upgrade Required */
            if (tls_done) {
                r = HTTP_BAD_GATEWAY;
                if (status) *status = "TLS already active";
            }
            else need_tls = 1;
            break;

        case 200: /* OK */
            if (scheme->recv_success &&
                (serverin = scheme->recv_success(hdrs))) {
                /* Process success data */
                serverinlen = strlen(serverin);
                goto challenge;
            }
            break;

        case 401: /* Unauthorized */
            if (auth_done) {
                r = SASL_BADAUTH;
                break;
            }

            if (!serverin) {
                int i = 0;

                hdr = spool_getheader(hdrs, "WWW-Authenticate");

                if (!scheme) {
                    unsigned avail_auth_schemes = 0;
                    const char *mech = NULL;
                    size_t len;

                    /* Compare authentication schemes offered in
                     * WWW-Authenticate header(s) to what we support */
                    buf_reset(&buf);
                    for (i = 0; hdr && hdr[i]; i++) {
                        len = strcspn(hdr[i], " ");

                        for (scheme = auth_schemes; scheme->name; scheme++) {
                            if (!strncmp(scheme->name, hdr[i], len) &&
                                !((scheme->flags & AUTH_NEED_PERSIST) &&
                                  (resp_body.flags & BODY_CLOSE))) {
                                /* Tag the scheme as available */
                                avail_auth_schemes |= (1 << scheme->idx);

                                /* Add SASL-based schemes to SASL mech list */
                                if (scheme->saslmech) {
                                    if (buf_len(&buf)) buf_putc(&buf, ' ');
                                    buf_appendcstr(&buf, scheme->saslmech);
                                }
                                break;
                            }
                        }
                    }

                    /* If we have a mech_conf, use it */
                    if (mech_conf && buf_len(&buf)) {
                        char *conf = xstrdup(mech_conf);
                        char *newmechlist =
                            intersect_mechlists(conf,
                                                (char *) buf_cstring(&buf));

                        if (newmechlist) {
                            buf_setcstr(&buf, newmechlist);
                            free(newmechlist);
                        }
                        else {
                            syslog(LOG_DEBUG, "%s did not offer %s",
                                   s->hostname, mech_conf);
                            buf_reset(&buf);
                        }
                        free(conf);
                    }

#ifdef SASL_HTTP_REQUEST
                    /* Set HTTP request as specified above (REQUIRED) */
                    httpreq.non_persist = (resp_body.flags & BODY_CLOSE);
                    sasl_setprop(s->saslconn, SASL_HTTP_REQUEST, &httpreq);
#endif

                    /* Try to start SASL exchange using available mechs */
                    r = sasl_client_start(s->saslconn, buf_cstring(&buf),
                                          NULL,         /* no prompts */
                                          NULL, NULL,   /* no initial resp */
                                          &mech);

                    if (mech) {
                        /* Find auth scheme associated with chosen SASL mech */
                        for (scheme = auth_schemes; scheme->name; scheme++) {
                            if (scheme->saslmech &&
                                !strcmp(scheme->saslmech, mech)) break;
                        }
                    }
                    else {
                        /* No matching SASL mechs - try Basic */
                        scheme = &auth_schemes[AUTH_BASIC];
                        if (!(avail_auth_schemes & (1 << scheme->idx))) {
                            need_tls = !tls_done;
                            break;  /* case 401 */
                        }
                    }

                    /* Find the associated WWW-Authenticate header */
                    for (i = 0; hdr && hdr[i]; i++) {
                        len = strcspn(hdr[i], " ");
                        if (!strncmp(scheme->name, hdr[i], len)) break;
                    }
                }

                /* Get server challenge, if any */
                if (hdr) {
                    const char *p = strchr(hdr[i], ' ');
                    serverin = p ? ++p : "";
                    serverinlen = strlen(serverin);
                }
            }

        challenge:
            if (serverin) {
                /* Perform the next step in the auth exchange */

                if (scheme->idx == AUTH_BASIC) {
                    /* Don't care about "realm" in server challenge */
                    const char *authid =
                        callback_getdata(s->saslconn, cb, SASL_CB_AUTHNAME);
                    pass = callback_getdata(s->saslconn, cb, SASL_CB_PASS);

                    buf_reset(&buf);
                    buf_printf(&buf, "%s:%s", authid, pass);
                    clientout = buf_cstring(&buf);
                    clientoutlen = buf_len(&buf);
                    auth_done = 1;
                }
                else {
                    /* Base64 decode any server challenge, if necessary */
                    if (serverin && (scheme->flags & AUTH_BASE64)) {
                        r = sasl_decode64(serverin, serverinlen,
                                          base64, BASE64_BUF_SIZE, &serverinlen);
                        if (r != SASL_OK) break;  /* case 401 */

                        serverin = base64;
                    }

                    /* SASL mech (Digest, Negotiate, NTLM) */
                    r = sasl_client_step(s->saslconn, serverin, serverinlen,
                                         NULL,          /* no prompts */
                                         &clientout, &clientoutlen);
                    if (r == SASL_OK) auth_done = 1;
                }
            }
            break;  /* case 401 */
        }

    } while (need_tls || clientout);

  done:
    if (hdrs) spool_free_hdrcache(hdrs);

    if (r && status && !*status) *status = sasl_errstring(r, NULL, NULL);

    return r;
}
int  http_seek(stream_t *stream, off_t pos) 
{

	HTTP_header_t * http_hdr = NULL;
	int fd = -1;

	if (stream == NULL)
	{
		OS_PRINTF("[%s][ERROR] stream == NULL!!!!\n",__func__);
		return 0;
	}
	
	//This if removed for network play issue fix, Gavin 2013-09-09
	//if (stream->fd > 0) closesocket(stream->fd); // need to reconnect to seek in http-stream
	//yliu add :for  fd = 0
#ifdef __LINUX__
	if (stream->fd > 0) 
	{
		closesocket(stream->fd); // need to reconnect to seek in http-stream
	}
#else
	if (stream->fd >= 0) 
	{
		closesocket(stream->fd);
		stream->fd = -1;
	}
#endif
      
	 if(is_file_seq_exit())
	 {
       
	     return -1;
	 }

	fd = http_send_request(stream->streaming_ctrl->url, pos);

	if (fd < 0) 
	{
		OS_PRINTF("[%s][ERROR] fail to send request  fd[%d]!!!!!!!!\n",__func__,fd);
		return 0;
	}

	http_hdr = http_read_response(fd);
       
	if (http_hdr == NULL) 
	{
	//yliu add:
	 closesocket(fd);
       fd = -1;
		OS_PRINTF("[%s][ERROR] fail to read response !!!!!!!!\n",__func__);
		return 0;
	}
      
      stream->streaming_ctrl->chunksize = http_hdr->chunksize;
	if (mp_msg_test(MSGT_NETWORK, MSGL_V))
	{
		http_debug_hdr(http_hdr);
	}

	switch (http_hdr->status_code) {
		case 200:
		case 206: // OK
			//mp_msg(MSGT_NETWORK, MSGL_V, "Content-Type: [%s]\n", http_get_field(http_hdr, "Content-Type"));
			//mp_msg(MSGT_NETWORK, MSGL_V, "Content-Length: [%s]\n", http_get_field(http_hdr, "Content-Length"));
			OS_PRINTF("[%s] Content-Type: [%s]\n",__func__,http_get_field(http_hdr, "Content-Type"));
			OS_PRINTF("[%s] Content-Length: [%s]\n",__func__,http_get_field(http_hdr, "Content-Length"));
                   //  yliu add :for reconnect
                   //if(pos == 0)
                    {
              	if(http_get_field(http_hdr, "Content-Length"))
			   stream->end_pos = atoll(http_get_field(http_hdr, "Content-Length"))+pos;
                   else
                      stream->end_pos = 0;
                    }
			OS_PRINTF("[%s] stream->end_pos: [%ld]\n",__func__,stream->end_pos);
			
			if (http_hdr->body_size > 0) {
				if (streaming_bufferize(stream->streaming_ctrl, http_hdr->body, http_hdr->body_size) < 0) {
					http_free(http_hdr);
                    closesocket(fd);
                    fd = -1;
					return -1;
				}
			}

			break;

			
		default:
			mp_msg(MSGT_NETWORK, MSGL_ERR, MSGTR_MPDEMUX_NW_ErrServerReturned, http_hdr->status_code, http_hdr->reason_phrase);
			closesocket(fd);
			fd = -1;
	}
	//add macro for consistency in Linux Version, yliu 2013-09-10
#if  0
	//This if added for network play issue fix, Gavin 2013-09-09
	if(stream->fd >= 0)
	{
		closesocket(stream->fd); // need to reconnect to seek in http-stream
		stream->fd = -1;
	}
#endif

	stream->fd = fd;

	if (http_hdr) {
		
		http_free(http_hdr);
		stream->streaming_ctrl->data = NULL;
		
	}

	stream->pos = pos;
	return 1;
}
Beispiel #8
0
Datei: http.c Projekt: zerix/mpv
//! If this function succeeds you must closesocket stream->fd
static int http_streaming_start(stream_t *stream, int* file_format) {
	HTTP_header_t *http_hdr = NULL;
	int fd = stream->fd;
	int res = STREAM_UNSUPPORTED;
	int redirect = 0;
	int auth_retry=0;
	int seekable=0;
	char *content_type;
	const char *content_length;
	char *next_url;
	URL_t *url = stream->streaming_ctrl->url;

	do
	{
		redirect = 0;
		if (fd >= 0) closesocket(fd);
		fd = http_send_request( url, 0 );
		if( fd<0 ) {
			goto err_out;
		}

		http_free(http_hdr);
		http_hdr = http_read_response( fd );
		if( http_hdr==NULL ) {
			goto err_out;
		}

		if( mp_msg_test(MSGT_NETWORK,MSGL_V) ) {
			http_debug_hdr( http_hdr );
		}

		// Check if we can make partial content requests and thus seek in http-streams
		if( http_hdr!=NULL && http_hdr->status_code==200 ) {
		    const char *accept_ranges = http_get_field(http_hdr,"Accept-Ranges");
		    const char *server = http_get_field(http_hdr, "Server");
		    if (accept_ranges)
			seekable = strncmp(accept_ranges,"bytes",5)==0;
		    else if (server && (strcmp(server, "gvs 1.0") == 0 ||
		                        strncmp(server, "MakeMKV", 7) == 0)) {
			// HACK for youtube and MakeMKV incorrectly claiming not to support seeking
			mp_msg(MSGT_NETWORK, MSGL_WARN, "Broken webserver, incorrectly claims to not support Accept-Ranges\n");
			seekable = 1;
		    }
		}

		print_icy_metadata(http_hdr);

		// Check if the response is an ICY status_code reason_phrase
		if( !strcasecmp(http_hdr->protocol, "ICY") ||
		     http_get_field(http_hdr, "Icy-MetaInt") ) {
			switch( http_hdr->status_code ) {
				case 200: { // OK
					char *field_data;
					// If content-type == video/nsv we most likely have a winamp video stream
					// otherwise it should be mp3. if there are more types consider adding mime type
					// handling like later
					if ( (field_data = http_get_field(http_hdr, "content-type")) != NULL && (!strcmp(field_data, "video/nsv") || !strcmp(field_data, "misc/ultravox")))
						*file_format = DEMUXER_TYPE_NSV;
					else if ( (field_data = http_get_field(http_hdr, "content-type")) != NULL && (!strcmp(field_data, "audio/aacp") || !strcmp(field_data, "audio/aac")))
						*file_format = DEMUXER_TYPE_AAC;
					else
						*file_format = DEMUXER_TYPE_LAVF;
					res = STREAM_ERROR;
					goto out;
				}
				case 400: // Server Full
					mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server is full, skipping!\n");
					goto err_out;
				case 401: // Service Unavailable
					mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server return service unavailable, skipping!\n");
					goto err_out;
				case 403: // Service Forbidden
					mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server return 'Service Forbidden'\n");
					goto err_out;
				case 404: // Resource Not Found
					mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server couldn't find requested stream, skipping!\n");
					goto err_out;
				default:
					mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: unhandled ICY-Errorcode, contact MPlayer developers!\n");
					goto err_out;
			}
		}

		// Assume standard http if not ICY
		switch( http_hdr->status_code ) {
			case 200: // OK
				content_length = http_get_field(http_hdr, "Content-Length");
				if (content_length) {
					mp_msg(MSGT_NETWORK,MSGL_V,"Content-Length: [%s]\n", content_length);
					stream->end_pos = atoll(content_length);
				}
				// Look if we can use the Content-Type
				content_type = http_get_field( http_hdr, "Content-Type" );
				if( content_type!=NULL ) {
					unsigned int i;

					mp_msg(MSGT_NETWORK,MSGL_V,"Content-Type: [%s]\n", content_type );
					// Check in the mime type table for a demuxer type
					for (i = 0; mime_type_table[i].mime_type != NULL; i++) {
						if( !strcasecmp( content_type, mime_type_table[i].mime_type ) ) {
							*file_format = mime_type_table[i].demuxer_type;
							res = seekable;
							goto out;
						}
					}
				}
				// Not found in the mime type table, don't fail,
				// we should try raw HTTP
				res = seekable;
				goto out;
			// Redirect
			case 301: // Permanently
			case 302: // Temporarily
			case 303: // See Other
			case 307: // Temporarily (since HTTP/1.1)
				// TODO: RFC 2616, recommand to detect infinite redirection loops
				next_url = http_get_field( http_hdr, "Location" );
				if( next_url!=NULL ) {
					int is_ultravox = strcasecmp(stream->streaming_ctrl->url->protocol, "unsv") == 0;
					stream->streaming_ctrl->url = url_redirect( &url, next_url );
					if (url_is_protocol(url, "mms")) {
						res = STREAM_REDIRECTED;
						goto err_out;
					}
					if (!url_is_protocol(url, "http")) {
						mp_msg(MSGT_NETWORK,MSGL_ERR,"Unsupported http %d redirect to %s protocol\n", http_hdr->status_code, url->protocol);
						goto err_out;
					}
					if (is_ultravox)
						url_set_protocol(url, "unsv");
					redirect = 1;
				}
				break;
			case 401: // Authentication required
				if( http_authenticate(http_hdr, url, &auth_retry)<0 )
					goto err_out;
				redirect = 1;
				break;
			default:
				mp_msg(MSGT_NETWORK,MSGL_ERR,"Server returned %d: %s\n", http_hdr->status_code, http_hdr->reason_phrase );
				goto err_out;
		}
	} while( redirect );

err_out:
	if (fd >= 0) closesocket( fd );
	fd = -1;
	http_free( http_hdr );
	http_hdr = NULL;
out:
	stream->streaming_ctrl->data = http_hdr;
	stream->fd = fd;
	return res;
}
Beispiel #9
0
Datei: http.c Projekt: zerix/mpv
static int nop_streaming_start( stream_t *stream ) {
	HTTP_header_t *http_hdr = NULL;
	char *next_url=NULL;
	int fd,ret;
	if( stream==NULL ) return -1;

	fd = stream->fd;
	if( fd<0 ) {
		fd = http_send_request( stream->streaming_ctrl->url, 0 );
		if( fd<0 ) return -1;
		http_hdr = http_read_response( fd );
		if( http_hdr==NULL ) return -1;

		switch( http_hdr->status_code ) {
			case 200: // OK
				mp_msg(MSGT_NETWORK,MSGL_V,"Content-Type: [%s]\n", http_get_field(http_hdr, "Content-Type") );
				mp_msg(MSGT_NETWORK,MSGL_V,"Content-Length: [%s]\n", http_get_field(http_hdr, "Content-Length") );
				if( http_hdr->body_size>0 ) {
					if( streaming_bufferize( stream->streaming_ctrl, http_hdr->body, http_hdr->body_size )<0 ) {
						http_free( http_hdr );
						return -1;
					}
				}
				break;
			// Redirect
			case 301: // Permanently
			case 302: // Temporarily
			case 303: // See Other
			case 307: // Temporarily (since HTTP/1.1)
				ret=-1;
				next_url = http_get_field( http_hdr, "Location" );

				if (next_url != NULL) {
					mp_msg(MSGT_NETWORK,MSGL_STATUS,"Redirected: Using this url instead %s\n",next_url);
							stream->streaming_ctrl->url=url_new_with_proxy(next_url);
					ret=nop_streaming_start(stream); //recursively get streaming started
				} else {
					mp_msg(MSGT_NETWORK,MSGL_ERR,"Redirection failed\n");
					closesocket( fd );
					fd = -1;
				}
				return ret;
				break;
			case 401: //Authorization required
			case 403: //Forbidden
			case 404: //Not found
			case 500: //Server Error
			default:
				mp_msg(MSGT_NETWORK,MSGL_ERR,"Server returned code %d: %s\n", http_hdr->status_code, http_hdr->reason_phrase );
				closesocket( fd );
				fd = -1;
				return -1;
				break;
		}
		stream->fd = fd;
	} else {
		http_hdr = (HTTP_header_t*)stream->streaming_ctrl->data;
		if( http_hdr->body_size>0 ) {
			if( streaming_bufferize( stream->streaming_ctrl, http_hdr->body, http_hdr->body_size )<0 ) {
				http_free( http_hdr );
				stream->streaming_ctrl->data = NULL;
				return -1;
			}
		}
	}

	if( http_hdr ) {
		http_free( http_hdr );
		stream->streaming_ctrl->data = NULL;
	}

	stream->streaming_ctrl->streaming_read = nop_streaming_read;
	stream->streaming_ctrl->streaming_seek = nop_streaming_seek;
	stream->streaming_ctrl->status = streaming_playing_e;
        stream->streaming = true;
	return 0;
}