Ejemplo n.º 1
0
/*
 * process rtsp header coming among rtsp real media packet
 * 
 * return value:       status code ... normal proceed case
 *                               0 ... EOF packet (not possible)
 *                              -1 ... error
 */
static int real_process_header(struct stream_t *stream)
{
    struct stream_ctrl_t *stream_ctrl = stream->stream_ctrl;
    struct rtsp_ctrl_t *rtsp_ctrl = stream_ctrl->rtsp_ctrl;
    struct rtsp_header_t *rtsp_hdr = NULL;
    int status_code = 0;
    int bodylen = 0;
    uint8_t *body = NULL;
    char *field = NULL;
    int got_cseq = 0;

    rtsp_hdr = new_rtsp_header();
    status_code = rtsp_recv_header(stream,rtsp_hdr);
    if(status_code < 0) {
	goto failed;
    }
    
    
    /* get content length data */
    if((field = rtsp_get_field(rtsp_hdr,"Content-length")) != NULL) {
	while(*field == ' ') field++;
	bodylen = atoi(field);	
	body = (uint8_t *)xmalloc(bodylen);
	bodylen = read_data(stream,body,bodylen);
    }
    /* get Cseq, for sending OK back */
    if((field = rtsp_get_field(rtsp_hdr,"Cseq")) != NULL) {
	while(*field == ' ') field++;
	got_cseq = atoi(field);	
    }


    if(!strncmp(rtsp_hdr->protocol,"RTSP",4)) { /* RTSP/1.0 200 OK , ignore this */
	/*
	  somehow RTSP message reply can be found among rdt messages.
	  send nothing.
	*/
	if(!got_cseq == rtsp_ctrl->cseq - 1) {
	    display(MSDL_DBG,"CSeq mismatch: expected %d, got %d",
		    rtsp_ctrl->cseq - 1,got_cseq);
	}
	/* DO NOT send RTSP OK */
    }
    else { /* not RTSP, whatever it is, send OK would be just fine  */
	rtsp_200ok(stream,got_cseq,rtsp_ctrl->session);
    }
    

    if(rtsp_hdr) free_rtsp_header(rtsp_hdr);      
    if(body)     free(body);
    return status_code;

  failed:
    if(body)     free(body);
    if(rtsp_hdr) free_rtsp_header(rtsp_hdr);
    return -1;
}
Ejemplo n.º 2
0
Archivo: rtsp.c Proyecto: clkao/msdl
/*
 * find Content-Length field in rtsp_hdr, and read (and trash) following data
 * return value:   bytes received and discarded
 *                -1 ... failed
 */
int rtsp_ignore_data_after_header(struct stream_t *stream,struct rtsp_header_t *rtsp_hdr)
{
    char *field = NULL;
    int body_left = 0;
    
    if((field = rtsp_get_field(rtsp_hdr,"Content-Length")) != NULL) {
	uint8_t *ignorebuf = NULL;
	
	while(*field == ' ') field++;
	body_left = atoi(field);
	if(body_left) {
	    ignorebuf = xmalloc(body_left);
	    if(read_data(stream,ignorebuf,body_left) <= 0) {
		free(ignorebuf);
		goto failed;
	    }
	    free(ignorebuf);
	}
    }

    return body_left;

  failed:
    return -1;
}
Ejemplo n.º 3
0
Archivo: rtsp.c Proyecto: clkao/msdl
/*
 * parse rtsp response
 * return value:   1 ... success
 *                -1 ... parse error
 */
int rtsp_parse_response(struct rtsp_ctrl_t *rtsp_ctrl,
			struct rtsp_header_t *rtsp_hdr)
{
    char *field;
    int answer_cseq;

    if((field = rtsp_get_field(rtsp_hdr,"Alert")) != NULL) {
	display(MSDL_ERR,"*** Alert ***\n%s\n",field);
    }

  
    if((field = rtsp_get_field(rtsp_hdr,"Cseq")) != NULL) {
	sscanf(field,"%d",&answer_cseq);
	if(answer_cseq != rtsp_ctrl->cseq - 1) {
	    /* -1 because cseq is incremented in build_request */
	    display(MSDL_DBG,"warning: Cseq mismatch, got %u, expected %u\n",
		    answer_cseq,rtsp_ctrl->cseq - 1);
	}
    }
  
    if((field = rtsp_get_field(rtsp_hdr,"Server")) != NULL) {
	while(*field == ' ') field++;
	if(rtsp_ctrl->server) { /* already has it */
	    if(strcmp(rtsp_ctrl->server,field)) { /* different server */
		display(MSDL_DBG,"warning: got different server\n"
			"    old: %s\n"
			"    new: %s\n",rtsp_ctrl->server,field);
		free(rtsp_ctrl->server);
		rtsp_ctrl->server = strdup(field);
	    }
	}
	else { /* not set yet */
	    rtsp_ctrl->server = strdup(field);
	}
    }
  
    if((field = rtsp_get_field(rtsp_hdr,"Session")) != NULL) {
	while(*field == ' ') field++;
	if(rtsp_ctrl->session) {
	    if(strcmp(rtsp_ctrl->session,field)) { /* different session */
		display(MSDL_DBG,"warning: got different session\n"
			"    old: [%s]\n"
			"    new: [%s]\n",rtsp_ctrl->session,field);
		free(rtsp_ctrl->session);
		rtsp_ctrl->session = strdup(field);
	    }
	}
	else {
	    rtsp_ctrl->session = strdup(field);
	}
    }
  
    /* real only, ignore in other protocol... */
    if((field = rtsp_get_field(rtsp_hdr,"RealChallenge1")) != NULL) {
	while(*field == ' ') field++;
	if(rtsp_ctrl->challenge) {
	    if(strcmp(rtsp_ctrl->challenge,field)) { /* different server */
		display(MSDL_DBG,"warning: got different client challenge\n"
			"    old: %s\n"
			"    new: %s\n",rtsp_ctrl->challenge,field);
		free(rtsp_ctrl->challenge);
		rtsp_ctrl->challenge = strdup(field);
	    }
	}
	else {
	    rtsp_ctrl->challenge = strdup(field);
	}
    }
    
    return 1;
}
Ejemplo n.º 4
0
Archivo: rtsp.c Proyecto: clkao/msdl
/*
 * start rtsp streaming.
 * 
 *    return value :   negative or 0  ... error
 *                                 1  ... success
 */
int rtsp_streaming_start(struct stream_t *stream)
{
    
    struct rtsp_header_t *rtsp_answer = NULL;

    int header_size;
  
    char *answer = NULL; /* temporary pointer */
    char *server = NULL;
    char *redirected = NULL;

    stream->stream_ctrl->status = STREAMING_HANDSHAKING;

    if(stream->dlopts->dl_protocol == RTSP_WMS) {
	server = strdup("WMServer");
    }
    else { /* still don't know which rtsp protocol, or REAL specified (need challenge) */
	
	stream->netsock->sock = rtsp_connect(stream);
	if(stream->netsock->sock < 0) {
	    display(MSDL_ERR,"cannot establish rtsp connection\n");
	    goto failed;
	}
	
	real_rtsp_options(stream,&rtsp_answer);

	if(rtsp_answer == NULL) {
	    display(MSDL_ERR,"rtsp connection failed\n");
	    goto failed;
	}
	
	/* get server name */
	if((answer = rtsp_get_field(rtsp_answer,"Server")) != NULL) {
	    while(*answer == ' ') answer++;  /* skip space */
	    server = strdup(answer);
	}
	else {
	    if((rtsp_get_field(rtsp_answer,"RealChallenge1")) != NULL) {
		server = strdup("Real");
	    }
	    else {
		server = strdup("Unknown Server");
	    }
	}
    }
  
    /* real or helix server (supported) */
    if(strstr(server,"Real") || strstr(server,"Helix")) {
	
	/* real-rtsp */
	struct rmff_header_t *rmff_header = NULL;	
	int ret = 0;

	/* connection is already setup, by real_rtsp_options called above */
	/* this is the function to do almost all setup process */
	ret = real_setup_and_get_header(stream,&rmff_header);
	
	if((!rmff_header) || (ret <= 0)) { /*  NOT OK  */
	    if((answer = rtsp_get_field(rtsp_answer,"Location")) != NULL) {
		/* redirected */
		while(*answer == ' ') answer++;
		
		redirected = strdup(answer);
		display(MSDL_NOR,"redirected to %s\n",redirected);
		/*
		  TODO redirection support
		  and I have never seen example...
		*/
		goto failed;
	    }
	    else {
		display(MSDL_ERR,"real/helix connection not established\n");
		goto failed;
	    }
	}
    
	/* OK, connection established */
	
	header_size = rmff_dump_header(rmff_header,
				       stream->stream_ctrl->write_buffer);
	stream->stream_ctrl->write_data_len = header_size;
    
	display(MSDL_VER,"rmff_header_size = %d\n",header_size);

	
	/* All Green */
	stream->stream_ctrl->rtsp_ctrl->rmff_header = rmff_header;
	stream->stream_ctrl->file_size     = rmff_header->data->size;
	stream->stream_ctrl->total_packets = rmff_header->data->num_packets;

	stream->stream_ctrl->rtsp_ctrl->get_media_packet = real_rdt_get_media_packet;
	/* to distinguish which rtsp */
	stream->stream_ctrl->rtsp_ctrl->rtsp_protocol = RTSP_REAL_PROTOCOL;
	/* for msdl function to know protocol */
	stream->stream_ctrl->protocol = RTSP_REAL;

    }
    else if(strstr(server,"WMServer")) {
	
	/* try rtsp-wms */
	struct asf_headerinfo_t *asf_headerinfo = NULL;
	int ret = 0;
	
	/*
	 * Clean up first.
	 */
	if(stream->netsock->sock) {
	    close(stream->netsock->sock);
	}
	
	/* free rtsp_ctrl_t */
	free_rtsp_ctrl_t(stream->stream_ctrl->rtsp_ctrl);
	stream->stream_ctrl->rtsp_ctrl = new_rtsp_ctrl_t();
	/* free serverinfo_t */
	free_serverinfo_t(stream->serverinfo);
	stream->serverinfo = new_serverinfo_t();
	
	/* DO NOT MESS WITH
	 * stream_t->netsock,
	 * stream_t->url,
	 * stream_t->dlopts,
	 * stream_t->resumeinfo,
	 * these are still valid (or just nothing (resumeinfo))
	 */

	/* re-establish rtsp connection for WMServer */
	stream->netsock->sock = rtsp_connect(stream);

	if(stream->netsock->sock < 0) {
	    /*
	      couldn't connect for some reason.
	      (rtsp port probably closed)
	     */
	    display(MSDL_ERR,"rtsp-wms connection not established\n");
	    display(MSDL_ERR,"server probably does not accept rtsp\n"
		    "retry using mmst protocol\n");

	    stream->stream_ctrl->status = STREAMING_OTHER_PROTOCOL;
	    stream->stream_ctrl->retry_protocol = MMST;	    
	    goto failed;
	}

    
	ret = wmserver_setup_and_get_header(stream,&asf_headerinfo);

	if(ret == 0) { /* retry    */
	    /* probably non-wmserver */
	    display(MSDL_ERR,"server probably does not accept rtsp\n"
		    "retry using mmst protocol\n",server);
	    stream->stream_ctrl->status = STREAMING_OTHER_PROTOCOL;
	    stream->stream_ctrl->retry_protocol = MMST;	    
	    
	    goto failed;
	}
	else if((!asf_headerinfo) || (ret < 0)) {       /* no retry */
	    display(MSDL_ERR,"rtsp setup failed\n");
	    goto failed;
	}

	
	/* All Green */
	stream->stream_ctrl->rtsp_ctrl->asf_headerinfo = asf_headerinfo;    /* set infomation */
	stream->stream_ctrl->packet_length = asf_headerinfo->fileh->max_packet_size;
	stream->stream_ctrl->file_size = asf_headerinfo->fileh->file_size;
	stream->stream_ctrl->total_packets = asf_headerinfo->fileh->num_packets;

	stream->stream_ctrl->rtsp_ctrl->get_media_packet = wmserver_rtp_get_media_packet;

	/* distinguish which rtsp */
	stream->stream_ctrl->rtsp_ctrl->rtsp_protocol = RTSP_WMS_PROTOCOL;
	/* for msdl function to know protocol */
	stream->stream_ctrl->protocol = RTSP_WMS;
	
    }
    else { /* unsupported servers */
	display(MSDL_ERR,"server type [%s] not supported\n",server);
	
	stream->stream_ctrl->rtsp_ctrl->rtsp_protocol = RTSP_UNKNOWN_PROTOCOL;
	goto failed;
    }

    
    if(server) free(server);
    if(rtsp_answer) free_rtsp_header(rtsp_answer);
    if(redirected) free(redirected);
  
    stream->stream_ctrl->status = STREAMING_DOWNLOADING;
    
    return 1; /* success */
  
  failed:
    if(server)      free(server);
    if(rtsp_answer) free_rtsp_header(rtsp_answer);
    if(redirected)  free(redirected);
    return -1;
}
Ejemplo n.º 5
0
/*
 * send PLAY request
 * return value ...     what rtsp_recv_header returned
 */
static int real_rtsp_play(struct stream_t *stream)
{
    struct rtsp_ctrl_t *rtsp_ctrl = stream->stream_ctrl->rtsp_ctrl;
    struct rtsp_header_t *rtsp_hdr = NULL;
 
    char *field = NULL;
    int ret = 0;
    
    /* 
     * Sending part 
     */
    rtsp_hdr = new_rtsp_header_with_standard_fields(rtsp_ctrl);

    if(stream->dlopts->resume_download) {
	real_prepare_resuming(stream);
    }

    if(stream->dlopts->bandwidth) { /* when user specified bandwidth */
	char *buffer = (char *)xmalloc(BUFSIZE_1K);
	snprintf(buffer,BUFSIZE_1K - 1,
		 "Bandwidth: %d",stream->dlopts->bandwidth);
	rtsp_set_field(rtsp_hdr,buffer);
	free(buffer);
    }
    
    rtsp_set_range_field(rtsp_hdr,stream->dlopts->range);
    rtsp_set_speed_field(rtsp_hdr,stream->dlopts->speed);
    
    rtsp_request_play(rtsp_hdr,rtsp_ctrl->mrl);
  
    rtsp_send_request_and_free(stream,rtsp_hdr);
    
    
    /* 
     * Receiving part 
     */
    /* receive message for PLAY request */
    rtsp_hdr = new_rtsp_header();
    ret = rtsp_recv_header(stream,rtsp_hdr);
    
    if(!is_rtsp_response_ok(rtsp_hdr->status_code)) { 
	display(MSDL_ERR,"PLAY request returned: %d (%s)\n",
		rtsp_hdr->status_code,rtsp_hdr->reason_phrase);
	
	field = rtsp_get_field(rtsp_hdr,"Alert");
	if(field) {
	    while(*field == ' ') field++;
	    display(MSDL_ERR,"message from server --> %s\n",field);
	}
	free_rtsp_header(rtsp_hdr);
	goto failed;
    }

    /* display real speed (might differ from user requested) */
    if((field = rtsp_get_field(rtsp_hdr,"Speed")) != NULL) {    
	if(stream->dlopts->speed) {
	    while(*field == ' ') field++;
	    display(MSDL_NOR,"Speed: %s\n",field);
	}
    }
    if((field = rtsp_get_field(rtsp_hdr,"Range")) != NULL) {    
	if(stream->dlopts->range) {
	    while(*field == ' ') field++;
	    display(MSDL_NOR,"Range: %s\n",field);
	}
    }

    /* skip content-length bytes from network */
    rtsp_ignore_data_after_header(stream,rtsp_hdr);
    free_rtsp_header(rtsp_hdr);
    
    return ret;

  failed:
    return -1;
}
Ejemplo n.º 6
0
/*
 * send DESCRIBE request
 * return value:   -1: failure   status_code: success
 */
static int real_rtsp_describe(struct stream_t *stream,char **description_ret)
{
    struct stream_ctrl_t *stream_ctrl = stream->stream_ctrl;
    struct rtsp_ctrl_t *rtsp_ctrl = stream_ctrl->rtsp_ctrl;
    struct rtsp_header_t *rtsp_hdr = NULL;

    char *description = NULL;
    char *buffer = (char *)xmalloc(BUFSIZE_1K);
    char *field = NULL;
    int len = 0;
    int ret = 0;
    
    rtsp_hdr = new_rtsp_header_with_standard_fields(rtsp_ctrl);
    rtsp_set_field(rtsp_hdr, "Accept: application/sdp");
    rtsp_set_field(rtsp_hdr, real_useragent);
    rtsp_set_field(rtsp_hdr, "Require: com.real.retain-entity-for-setup");
  
    snprintf(buffer,BUFSIZE_1K - 1,"Bandwidth: %u",stream_ctrl->bandwidth);
    rtsp_set_field(rtsp_hdr,buffer); 
  
    rtsp_set_field(rtsp_hdr, "Language: en-US");
    rtsp_set_field(rtsp_hdr, "RegionData: 0");
    rtsp_set_field(rtsp_hdr, real_clientid);
    rtsp_set_field(rtsp_hdr, "GUID: 00000000-0000-0000-0000-000000000000");
    rtsp_set_field(rtsp_hdr, "SupportsMaximumASMBandwidth: 1");
  
  
    rtsp_request_describe(rtsp_hdr,rtsp_ctrl->mrl);
    rtsp_send_request_and_free(stream,rtsp_hdr);
    
    rtsp_hdr = new_rtsp_header();
    ret = rtsp_recv_header(stream,rtsp_hdr);
    if(ret < 0) {
	free_rtsp_header(rtsp_hdr);
	goto failed;
    }
    
    /* NOT OK */
    if(!is_rtsp_response_ok(rtsp_hdr->status_code)) { 
	display(MSDL_ERR,"DESCRIBE request returned: %d (%s)\n",
		rtsp_hdr->status_code,rtsp_hdr->reason_phrase);
	
	field = rtsp_get_field(rtsp_hdr,"Alert");
	if(field) {
	    while(*field == ' ') field++;
	    display(MSDL_ERR,"message from server --> %s\n",field);
	}
	free_rtsp_header(rtsp_hdr);
	goto failed;
    }

    len = 0;
    /* Content-length must be present */
    if((field = rtsp_get_field(rtsp_hdr,"Content-length")) != NULL) {
	while(*field == ' ') field++;
	len = atoi(field);
    }
    else { /* no Content-length */
	display(MSDL_ERR,"warning: No Content-length in fields!!\n");
    }
  
    if((field = rtsp_get_field(rtsp_hdr,"ETag")) != NULL) {
	while(*field == ' ') field++;
	rtsp_ctrl->etag = strdup(field);
    }
    else {
	display(MSDL_ERR,"warning: No ETag!!\n");
	rtsp_ctrl->etag = NULL;
    }

    free_rtsp_header(rtsp_hdr);  
    
    /*
      copy description (sdp)
    */
    description = (char *)xmalloc(len + 1);
    if(read_data(stream,(uint8_t *)description,len) < 0) {
	goto failed;
    }
    description[len] = '\0';
  
    display(MSDL_DBG,"==================\n%s\n=(%d bytes)========\n",
	    description,(int)strlen(description));
    
    
    if(buffer) free(buffer);
    *description_ret = description;
    return ret;
    
  failed:
    if(description) free(description);
    if(buffer) free(buffer);
    *description_ret = NULL;
    return -1;
}