예제 #1
0
파일: pong61.c 프로젝트: cs61/cs61-psets
// pong_thread(threadarg)
//    Connect to the server at the position indicated by `threadarg`
//    (which is a pointer to a `pong_args` structure).
void* pong_thread(void* threadarg) {
    pthread_detach(pthread_self());

    // Copy thread arguments onto our stack.
    pong_args pa = *((pong_args*) threadarg);

    char url[256];
    snprintf(url, sizeof(url), "move?x=%d&y=%d&style=on",
             pa.x, pa.y);

    http_connection* conn = http_connect(pong_addr);
    http_send_request(conn, url);
    http_receive_response_headers(conn);
    if (conn->status_code != 200)
        fprintf(stderr, "%.3f sec: warning: %d,%d: "
                "server returned status %d (expected 200)\n",
                elapsed(), pa.x, pa.y, conn->status_code);

    http_receive_response_body(conn);
    double result = strtod(conn->buf, NULL);
    if (result < 0) {
        fprintf(stderr, "%.3f sec: server returned error: %s\n",
                elapsed(), http_truncate_response(conn));
        exit(1);
    }

    http_close(conn);

    // signal the main thread to continue
    pthread_cond_signal(&condvar);
    // and exit!
    pthread_exit(NULL);
}
예제 #2
0
파일: main.c 프로젝트: padenot/Serendipite
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;
}
예제 #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;
}
예제 #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;
}
예제 #5
0
파일: network.c 프로젝트: dreamerc/mplayer
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;
}
예제 #6
0
void
send_head_request(uv_connect_t *req, int status)
{
	if (status != 0) {
		printf("on connect failed: %s\n", uv_strerror(status));
		return;
	}

	uv_read_start(req->handle, on_alloc, on_head_read);

	task *task = (struct task*)req->handle->data;

	http_request *request = task->head_request;
	http_set_on_header_field(request, on_header_field);
	http_set_on_header_value(request, on_header_value);
	http_set_on_headers_complete(request, on_headers_complete_close);
	http_request_set_method(request, HTTP_HEAD);
	http_send_request(request);

	uv_fs_t fs;
	task->fd = uv_fs_open(req->handle->loop, &fs, task->name, O_CREAT | O_RDWR, 0777, NULL);
}
예제 #7
0
파일: http.c 프로젝트: hyrise/dispatcher
struct HttpResponse *executeRequest(struct Host *host, struct HttpRequest *request) {
    debug("execute request %s:%d", host->url, host->port);
    int sockfd = http_open_connection(host->url, host->port);
    if (sockfd == -1) {
        return NULL;
    }

    const char *connection_type = dict_get_case(request->headers, "Connection");
    debug("connection_type: %s", connection_type);

    if (http_send_request(sockfd, request) != 0) {
        return NULL;
    }

    struct HttpResponse *response;
    int http_error =  http_receive_response(sockfd, &response);
    if (http_error != HTTP_SUCCESS) {
        debug("http error: executeRequest");
    }
    debug("Close socket.");
    close(sockfd);

    return response;
}
예제 #8
0
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;
}
예제 #9
0
파일: pong61.c 프로젝트: cs61/cs61-psets
// main(argc, argv)
//    The main loop.
int main(int argc, char** argv) {
    // parse arguments
    int ch, nocheck = 0;
    while ((ch = getopt(argc, argv, "nh:p:u:")) != -1) {
        if (ch == 'h')
            pong_host = optarg;
        else if (ch == 'p')
            pong_port = optarg;
        else if (ch == 'u')
            pong_user = optarg;
        else if (ch == 'n')
            nocheck = 1;
        else
            usage();
    }
    if (optind == argc - 1)
        pong_user = argv[optind];
    else if (optind != argc)
        usage();

    // look up network address of pong server
    struct addrinfo hints;
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_NUMERICSERV;
    int r = getaddrinfo(pong_host, pong_port, &hints, &pong_addr);
    if (r != 0) {
        fprintf(stderr, "problem looking up %s: %s\n",
                pong_host, gai_strerror(r));
        exit(1);
    }

    // reset pong board and get its dimensions
    int width, height;
    {
        http_connection* conn = http_connect(pong_addr);
        http_send_request(conn, nocheck ? "reset?nocheck=1" : "reset");
        http_receive_response_headers(conn);
        http_receive_response_body(conn);
        if (conn->status_code != 200
            || sscanf(conn->buf, "%d %d\n", &width, &height) != 2
            || width <= 0 || height <= 0) {
            fprintf(stderr, "bad response to \"reset\" RPC: %d %s\n",
                    conn->status_code, http_truncate_response(conn));
            exit(1);
        }
        http_close(conn);
    }
    // measure future times relative to this moment
    elapsed_base = timestamp();

    // print display URL
    printf("Display: http://%s:%s/%s/%s\n",
           pong_host, pong_port, pong_user,
           nocheck ? " (NOCHECK mode)" : "");

    // initialize global synchronization objects
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&condvar, NULL);

    // play game
    int x = 0, y = 0, dx = 1, dy = 1;
    while (1) {
        // create a new thread to handle the next position
        pong_args pa;
        pa.x = x;
        pa.y = y;
        pthread_t pt;
        r = pthread_create(&pt, NULL, pong_thread, &pa);
        if (r != 0) {
            fprintf(stderr, "%.3f sec: pthread_create: %s\n",
                    elapsed(), strerror(r));
            exit(1);
        }

        // wait until that thread signals us to continue
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&condvar, &mutex);
        pthread_mutex_unlock(&mutex);

        // update position
        x += dx;
        y += dy;
        if (x < 0 || x >= width) {
            dx = -dx;
            x += 2 * dx;
        }
        if (y < 0 || y >= height) {
            dy = -dy;
            y += 2 * dy;
        }

        // wait 0.1sec
        usleep(100000);
    }
}
예제 #10
0
static void cmd_httpc_post(int argc, char **argv)
{
	if (argc < 3) {
		dbg("\nUsage: %s\n", httpc_test_cmds[0].help);
		return;
	}

	const char *url = argv[1];
	const char *data = argv[2];
	int len = strlen(data);
	int count = 1;		/* Default value */

	/* Check if user has given count */
	if (argc > 3) {
		count = strtol(argv[3], NULL, 0);
	}

	http_session_t hnd;
	int rv = http_open_session(&hnd, url, 0, NULL, 0);
	if (rv != 0) {
		dbg("Open session failed: %s (%d)", url, rv);
		return;
	}

	while (count--) {
		http_req_t req = {
			.type = HTTP_POST,
			.resource = url,
			.version = HTTP_VER_1_1,
			.content = data,
			.content_len = len,
		};

		rv = http_prepare_req(hnd, &req,
				      STANDARD_HDR_FLAGS |
				      HDR_ADD_CONN_KEEP_ALIVE);
		if (rv != 0) {
			dbg("Prepare request failed: %d", rv);
			break;
		}

		rv = http_send_request(hnd, &req);
		if (rv != 0) {
			dbg("Send request failed: %d", rv);
			break;
		}

		http_resp_t *resp;
		rv = http_get_response_hdr(hnd, &resp);
		if (rv != 0) {
			dbg("Get resp header failed: %d", rv);
			break;
		}

		dbg("Content length: %d", resp->content_length);
		if (resp->content_length == 0) {
			continue;
		}

		dbg("------------Content------------");
		while (1) {
			char buf[32];
			rv = http_read_content(hnd, buf, sizeof(buf));
			if (rv == 0 || rv < 0) {
				break;
			}
			wmprintf("%s", buf);
		}

		if (rv < 0) {
			/* Error condition */
			break;
		}
	}
}
예제 #11
0
// pong_thread(threadarg)
//    Connect to the server at the position indicated by `threadarg`
//    (which is a pointer to a `pong_args` structure).
void* pong_thread(void* threadarg) {
    pthread_detach(pthread_self());

    // Copy thread arguments onto our stack.
    pong_args pa = *((pong_args*) threadarg);

    char url[256];
    snprintf(url, sizeof(url), "move?x=%d&y=%d&style=on",
             pa.x, pa.y);
    http_connection* conn;
    size_t sleeptime = 10000;
retry:
    // find reusable connection using LIFO access
	pthread_mutex_lock(&table_lock);
	if(conn_done_num > 0) {
		conn = conn_done_table[conn_done_num - 1];
		--conn_done_num;
		pthread_mutex_unlock(&table_lock);
	} else {
		// if not, create a new connection
		pthread_mutex_unlock(&table_lock);
    	conn = http_connect(pong_addr);
    }
    // let other threads wait for a sleeping thread due to server down
    pthread_mutex_lock(&time_lock);
    while(stop_time != 0) {
    	 pthread_cond_wait(&stop_time_cond, &time_lock);
    }
    pthread_mutex_unlock(&time_lock);
    // send request after the server has waken up
    http_send_request(conn, url);
    http_receive_response_headers(conn);
    // failed connection
	while(conn->state == HTTP_BROKEN && conn->status_code == -1) {
		http_close(conn);
		// usleep less than 1 second
	    if(sleeptime < 1000000)
	    	usleep(sleeptime);
		else {
	   		// sleep longer than a second
	    	sleep(1);
	    	usleep(sleeptime % 1000000);
	    }
	    // keep sleep time less than 2 seconds and double each retry
		if(sleeptime <= 1000000)
	    	sleeptime += sleeptime;
    	goto retry;
	}
	
    if (conn->status_code != 200)
        fprintf(stderr, "%.3f sec: warning: %d,%d: "
                "server returned status %d (expected 200)\n",
                elapsed(), pa.x, pa.y, conn->status_code);
    // signal more thread creation after having received header
	pthread_cond_signal(&condvar);
    http_receive_response_body(conn);
    // if server sends STOP, read the time in millisecond to stop_time
    pthread_mutex_lock(&time_lock);
    if(stop_time == 0 && sscanf(http_truncate_response(conn), "+%d STOP", &stop_time) && stop_time != 0) {
    	pthread_mutex_unlock(&time_lock);
    	// sleep less than 1 second
    	if(stop_time < 1000)
			usleep(stop_time * 1000);
		else {
			// sleep longer than 1 second
			sleep(stop_time / 1000);
			usleep((stop_time % 1000) * 1000);
		}
    	pthread_mutex_lock(&time_lock);
		stop_time = 0;
		// woke up, tell all threads to continue
		pthread_cond_broadcast(&stop_time_cond);
    	pthread_mutex_unlock(&time_lock);
    } else if (stop_time != 0) {
    	while(stop_time != 0) {
    		pthread_cond_wait(&stop_time_cond, &time_lock);
    	}
    	if(sscanf(http_truncate_response(conn), "+%d STOP", &stop_time) && stop_time != 0) {
    		pthread_mutex_unlock(&time_lock);
    		if(stop_time < 1000)
				usleep(stop_time * 1000);
			else {
				sleep(stop_time / 1000);
				usleep((stop_time % 1000) * 1000);
			}
    		pthread_mutex_lock(&time_lock);
			stop_time = 0;
			pthread_cond_broadcast(&stop_time_cond);
    		pthread_mutex_unlock(&time_lock);
    	} else {
    		pthread_mutex_unlock(&time_lock);
    	}
    } else {
    	pthread_mutex_unlock(&time_lock);
    }
    double result = strtod(conn->buf, NULL);
    if (result < 0) {
        fprintf(stderr, "%.3f sec: server returned error: %s\n",
                elapsed(), http_truncate_response(conn));
        exit(1);
    }
	// if the connection has status done, keep it in the connection table
	pthread_mutex_lock(&table_lock);
    if(conn->state == HTTP_DONE && conn_done_num < 29) {
    	conn_done_table[conn_done_num] = conn;
    	++conn_done_num;
		pthread_mutex_unlock(&table_lock);
    } else {
		pthread_mutex_unlock(&table_lock);
    	http_close(conn);
    }

    // signal the main thread to continue
    // pthread_cond_signal(&condvar);
    // and exit!
    pthread_exit(NULL);
}
예제 #12
0
파일: http.c 프로젝트: 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;
}
예제 #13
0
파일: http.c 프로젝트: 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;
}