Example #1
0
File: rtsp.c Project: clkao/msdl
/*
 * set Speed: field to rtsp_hdr.
 */
void rtsp_set_speed_field(struct rtsp_header_t *rtsp_hdr,const char *speedstr)
{
    char *buffer = xmalloc(BUFSIZE_1K);
    
    /* speed specified */
    if(speedstr) {

	char *reason = NULL;
	int  guessed_speed = 0;
	
	if(speed_valid_and_guess(speedstr,&guessed_speed,&reason)) {
	    snprintf(buffer,BUFSIZE_1K - 1,"Speed: %s",speedstr);	    
	}
	else { /* invlalid, use guessed value */
	    if(guessed_speed == 0) {
		guessed_speed = 1; /* default speed 1.000 */
	    }
	    snprintf(buffer,BUFSIZE_1K - 1,"Speed: %d.000",guessed_speed);
	    display(MSDL_ERR,
		    "option \"-s %s\" is invalid as a rtsp speed request\n"
		    ": %s\n"
		    "send \"%s\" instead\n",
		    speedstr,reason,buffer);
	}
    }
    else { /* set default speed */
	strncpy(buffer,"Speed: 1.000",BUFSIZE_1K - 1);
    }
    rtsp_set_field(rtsp_hdr,buffer);

    free(buffer);
}
Example #2
0
File: rtsp.c Project: clkao/msdl
/*
 * set fields which are common in all rtsp packet. 
 * CSeq and Session field should be present in
 * every rtsp packet.
 */
int rtsp_set_standard_fields(struct rtsp_ctrl_t *rtsp_ctrl,
			     struct rtsp_header_t *rtsp_hdr)
{
    char buf[20];
    snprintf(buf,20,"Cseq: %u",rtsp_ctrl->cseq);
    rtsp_set_field(rtsp_hdr,buf);
  
    if(rtsp_ctrl->session) {
	char *buf2;
	buf2 = (char *)xmalloc(strlen(rtsp_ctrl->session) + 15);
	sprintf(buf2,"Session: %s",rtsp_ctrl->session);
	rtsp_set_field(rtsp_hdr,buf2);
	free(buf2);
    }

    return 0;
}
Example #3
0
/*
 * send SET_PARAMETER, with stream choosing subscribe.
 * return value ...     what rtsp_recv_header returned
 */
static int real_rtsp_set_parameter(struct stream_t *stream,char *subscribe)
{
    struct rtsp_ctrl_t *rtsp_ctrl = stream->stream_ctrl->rtsp_ctrl;
    struct rtsp_header_t *rtsp_hdr = NULL;
    int ret = 0;
    
    rtsp_hdr = new_rtsp_header_with_standard_fields(rtsp_ctrl);
    rtsp_set_field(rtsp_hdr,subscribe);
    if(stream->dlopts->bandwidth) { /* when user specified bandwidth */
	char *buffer = (char *)xmalloc(BUFSIZE_1K);
	snprintf(buffer,BUFSIZE_1K - 1,
		 "SetDeliveryBandwidth: Bandwidth=%d;BackOff=0",stream->dlopts->bandwidth);
	rtsp_set_field(rtsp_hdr,buffer);
	free(buffer);
    }
    
    rtsp_request_set_parameter(rtsp_hdr,rtsp_ctrl->mrl);
    rtsp_send_request_and_free(stream,rtsp_hdr);
    ret = rtsp_recv_header_ignore_message(stream);

    return ret;
}
Example #4
0
/*
 * send OPTIONS request, this is used as very first trial to server
 * we will need rtsp_hdr later, so return that.
 * return value:   -1: failure   status_code: success, rtsp_hdr_ret(malloc)
 */
int real_rtsp_options(struct stream_t *stream,struct rtsp_header_t **rtsp_hdr_ret)
{
    int ret = 0;
    struct rtsp_ctrl_t *rtsp_ctrl = stream->stream_ctrl->rtsp_ctrl;
    struct rtsp_header_t *rtsp_hdr = NULL;
    char *options_uri = NULL;
    int options_uri_len = 0;

    /* default is rtsp-real (becasue OPTIONS req is supported) */
    rtsp_hdr = new_rtsp_header_with_standard_fields(rtsp_ctrl);
    
    rtsp_set_field(rtsp_hdr,real_useragent);
    rtsp_set_field(rtsp_hdr,"GUID: 00000000-0000-0000-0000-000000000000");
    rtsp_set_field(rtsp_hdr,real_clientid);  
    rtsp_set_field(rtsp_hdr,"Pragma: initiate-session");
    rtsp_set_field(rtsp_hdr,"RegionData: 0");
    rtsp_set_field(rtsp_hdr,real_clientchallenge);
    rtsp_set_field(rtsp_hdr,real_companyid);
    rtsp_set_field(rtsp_hdr,real_playerstarttime);
    
    
    options_uri_len = strlen(stream->serverinfo->host) + 20;
    options_uri = (char *)xmalloc(options_uri_len);
    snprintf(options_uri,options_uri_len,"rtsp://%s:%i",
	     stream->serverinfo->host,stream->serverinfo->port);
    
    rtsp_request_options(rtsp_hdr,options_uri);
    rtsp_send_request_and_free(stream,rtsp_hdr);
    
    rtsp_hdr = new_rtsp_header();
    ret = rtsp_recv_header(stream,rtsp_hdr);
    if(ret < 0) {
	goto failed;
    }

    *rtsp_hdr_ret = rtsp_hdr;
    
    if(options_uri) free(options_uri);
    return ret;

  failed:
    if(rtsp_hdr)    free_rtsp_header(rtsp_hdr);
    if(options_uri) free(options_uri);
    *rtsp_hdr_ret = NULL;
    return -1;
}
Example #5
0
/*
 * send SETUP requst. 2 setups for multiple streams.
 * return value ...     what rtsp_recv_header returned
 */
static int real_rtsp_setup(struct stream_t *stream,struct rmff_header_t *rmff_header)
{
    struct rtsp_ctrl_t *rtsp_ctrl = stream->stream_ctrl->rtsp_ctrl;
    struct rtsp_header_t *rtsp_hdr = NULL;
    char *buffer = (char *)xmalloc(BUFSIZE_1K);
    int ret = 0;
    char challenge2[64];
    char checksum[34];
    
    rtsp_hdr = new_rtsp_header_with_standard_fields(rtsp_ctrl);
    
    real_calc_challenge2_and_checksum(rtsp_ctrl->challenge,challenge2,checksum);
  
    snprintf(buffer,BUFSIZE_1K - 1,"RealChallenge2: %s, sd=%s",
	     challenge2,checksum);
    rtsp_set_field(rtsp_hdr,buffer);
    snprintf(buffer,BUFSIZE_1K - 1,"If-Match: %s",rtsp_ctrl->etag);
    rtsp_set_field(rtsp_hdr,buffer);
    rtsp_set_field(rtsp_hdr,"RDTFeatureLevel: 2");
    rtsp_set_field(rtsp_hdr,real_transport);
    snprintf(buffer,BUFSIZE_1K - 1,"%s/streamid=0",rtsp_ctrl->mrl);
    rtsp_request_setup(rtsp_hdr,buffer);
    rtsp_send_request_and_free(stream,rtsp_hdr);
    
    /* receive message for SETUP */
    ret = rtsp_recv_header_ignore_message(stream);
    
    
    /*
      send messages if multiple stream exists (max is 2 streams anyways...)
    */
    if(rmff_header->prop->num_streams > 1) {
	rtsp_hdr = new_rtsp_header_with_standard_fields(rtsp_ctrl);

	rtsp_set_field(rtsp_hdr,real_transport);
	snprintf(buffer,BUFSIZE_1K - 1,"If-Match: %s",rtsp_ctrl->etag);
	rtsp_set_field(rtsp_hdr,buffer);
	snprintf(buffer,BUFSIZE_1K - 1,"%s/streamid=1",rtsp_ctrl->mrl);
	rtsp_request_setup(rtsp_hdr,buffer);
    
	rtsp_send_request_and_free(stream,rtsp_hdr);
	
	/* receive message for SETUP */
	ret = rtsp_recv_header_ignore_message(stream);
    }
    
    free(buffer);
    return ret; 
}
Example #6
0
File: rtsp.c Project: clkao/msdl
/*
 * set Range: field to rtsp_hdr.
 */
void rtsp_set_range_field(struct rtsp_header_t *rtsp_hdr,const char *rangestr)
{
    char *buffer = xmalloc(BUFSIZE_1K);

    /* range specified */
    if(rangestr) {
	char *reason = NULL;
	
	if(rtsp_npt_range_valid(rangestr,&reason)) { /* valid */
	    snprintf(buffer,BUFSIZE_1K - 1,"Range: npt=%s",rangestr);
	}
	else {
	    char *npt_range_str = NULL;
	    npt_range_str = rtsp_range_to_npt_range(rangestr,&reason);
	    if(npt_range_str) { /* acceptable   */
		snprintf(buffer,BUFSIZE_1K - 1,"Range: npt=%s",npt_range_str);
		display(MSDL_VER,
			"send \"%s\" for Range\n",
			npt_range_str);
		free(npt_range_str);
	    }
	    else {              /* really inacceptable */
		strncpy(buffer,"Range: npt=0.000-",BUFSIZE_1K - 1);
		display(MSDL_ERR,
			"option \"-r %s\" is invalid as a rtsp range request\n"
			": %s\n"
			"send \"%s\" instead\n",
			rangestr,reason,buffer);
	    }
	}
    }
    else { /* default range, from beginning */
	strncpy(buffer,"Range: npt=0.000-",BUFSIZE_1K - 1);
    }
    rtsp_set_field(rtsp_hdr,buffer);

    free(buffer);
}
Example #7
0
File: rtsp.c Project: clkao/msdl
/*
 * rtsp_response_parse :  parse rtsp response header 
 * make rtsp_hdr from raw data in rtsp_hdr->buffer
 *
 *    return value :        -1 ... ERROR
 *                           0 ... already parsed.
 *                           1 ... success.
 */
int rtsp_response_parse(struct rtsp_header_t *rtsp_hdr)
{
  
    char *hdr_ptr, *ptr;
    char *field = NULL;
  
    int pos_hdr_sep, hdr_sep_len;
    size_t len;
  
    if(rtsp_hdr == NULL) return -1;
    if(rtsp_hdr->is_parsed) return 0; /* already parsed. */
    
    /* get first word  */
    hdr_ptr = strstr(rtsp_hdr->buffer, " ");
    if(hdr_ptr == NULL) {
	display(MSDL_ERR,"Malformed answer : No %20 separator\n");
	return -1;
    }
  
    len = hdr_ptr - rtsp_hdr->buffer;
    rtsp_hdr->protocol = xmalloc(len + 1);
    strncpy(rtsp_hdr->protocol,rtsp_hdr->buffer,len);
    rtsp_hdr->protocol[len] = '\0';
  

    /* 1. set method */
    rtsp_hdr->method = strdup(rtsp_hdr->protocol);
  
    if(!strncasecmp(rtsp_hdr->protocol,"RTSP",4)) { /* RTSP message*/
    
	/* 2. get RTSP status code */
	if(sscanf(++hdr_ptr,"%d",&(rtsp_hdr->status_code)) != 1) {
	    display(MSDL_ERR,"Malformed answer : No rtsp status code!!\n");
	    return -1;
	} 
    
	hdr_ptr += 4; /* "[0-9][0-9][0-9] " */
    
	/* 3. get reason phrase */
	ptr = strstr(hdr_ptr,"\n");
	if(ptr == NULL) {
	    display(MSDL_ERR,"Malformed answer : unable to get reason_phrase\n");
	    return -1;
	}
	len = ptr - hdr_ptr; // len of reason phrase.

	rtsp_hdr->reason_phrase = xmalloc(len + 1);
	strncpy(rtsp_hdr->reason_phrase,hdr_ptr,len);
	if(rtsp_hdr->reason_phrase[len - 1] == '\r') { // M$ style newline!
	    len --; // we don't need \r.
	}
	rtsp_hdr->reason_phrase[len] = '\0'; // terminate string
    } 
    else if(!strncasecmp(rtsp_hdr->protocol,"SET_PARAMETER",strlen("SET_PARAMETER"))) {
	rtsp_hdr->status_code = RTSP_STATUS_SET_PARAMETER;
    }
    else if(!strncasecmp(rtsp_hdr->protocol,"OPTIONS",strlen("OPTIONS"))) {
	rtsp_hdr->status_code = RTSP_STATUS_OPTIONS;
    }
    else if(!strncasecmp(rtsp_hdr->protocol,"ANNOUNCE",strlen("ANNOUNCE"))) {
	rtsp_hdr->status_code = RTSP_STATUS_ANNOUNCE;
    }
    else {  /* NOT RTSP ---> abort */
	display(MSDL_ERR,"Protocol not RTSP, server says '%s'",rtsp_hdr->protocol);
	return -1;
    }
  
  
    hdr_sep_len = 4; /* header separator length */
    ptr = strstr(rtsp_hdr->buffer,"\r\n\r\n");
    if(!ptr) {
	ptr = strstr(rtsp_hdr->buffer,"\n\n");
	if(!ptr) {
	    display(MSDL_ERR,"Header may be incomplete!\n");
	    return -1;
	}
	hdr_sep_len = 2;
    }
    pos_hdr_sep = ptr - rtsp_hdr->buffer;
  
    /* points to first line after method line. */
    hdr_ptr = strstr(rtsp_hdr->buffer,"\n") + 1;

    /* parse of first line [DONE] */
  
  
    /* get all fields. they are separated by '\n' */
    do {
	ptr = hdr_ptr;
	while(*ptr != '\r' && *ptr != '\n') ptr++;
	len  = ptr - hdr_ptr;

	if(len == 0) break; /* met \n\n --> end of header! */
    
	field = (char *)xrealloc(field,len + 1); // +1 for '\0'
	strncpy(field,hdr_ptr,len);
	field[len] = '\0';
    
    
	rtsp_set_field(rtsp_hdr,field);
	hdr_ptr = ptr + ((*ptr == '\r') ? 2 : 1); /* points to next line */
    } while(hdr_ptr < (rtsp_hdr->buffer + pos_hdr_sep));
  
    if(field) {
	free(field);
    }

    /*
      rtsp_hdr->buffer_len is length of header total data received
    */
    if(pos_hdr_sep + hdr_sep_len < rtsp_hdr->buffer_len) {
	rtsp_hdr->body = rtsp_hdr->buffer + (pos_hdr_sep + hdr_sep_len);
	rtsp_hdr->body_len = rtsp_hdr->buffer_len - (pos_hdr_sep + hdr_sep_len);
    }
  
    /* mark parsed */
    rtsp_hdr->is_parsed = 1;
    
  
    return 1;
}
Example #8
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;
}
Example #9
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;
}