Ejemplo n.º 1
0
int send_play_reply(RTSP_buffer * rtsp, char *object,
		    RTSP_session * rtsp_session)
{
	char r[1024];
	char temp[30];
	RTP_session *p = rtsp_session->rtp_session;

	TRACE_FUNC();

	/* build a reply message */
	sprintf(r,
		"%s %d %s" RTSP_EL "CSeq: %d" RTSP_EL "Server: %s/%s" RTSP_EL,
		RTSP_VER, 200, get_stat(200), rtsp->rtsp_cseq, PACKAGE,
		VERSION);
	add_time_stamp(r, 0);
	strcat(r, "Session: ");
	sprintf(temp, "%d", rtsp_session->session_id);
	strcat(r, temp);
	strcat(r, RTSP_EL);
	// strcat(r, "RTP-info: url=");
	strcat(r, "RTP-info: ");
	// strcat(r, object);
	// strcat(r, ";");
	do {
		strcat(r, "url=");
		// strcat(r, object);
		// TODO: we MUST be sure to send the correct url 
		sprintf(r + strlen(r), "rtsp://%s/%s/%s!%s",
			prefs_get_hostname(), p->sd_filename, p->sd_filename,
			p->current_media->filename);
		strcat(r, ";");
		sprintf(r + strlen(r), "seq=%u;rtptime=%u", p->start_seq,
			p->start_rtptime);
		if (p->next != NULL) {
			strcat(r, ",");
		} else {
			// strcat(r, "\r\n\r\n");
			strcat(r, RTSP_EL);
		}
		p = p->next;
	} while (p != NULL);
	// end of message
	strcat(r, RTSP_EL);

	bwrite(r, (unsigned short) strlen(r), rtsp);

//	INFOLOGG("200 - %s ", object);

	return ERR_NOERROR;
}
Ejemplo n.º 2
0
int RTCP_send_packet(RTP_session *session,rtcp_pkt_type type)
{
	unsigned char *pkt=NULL;	
	RTCP_header hdr;			
	uint32 pkt_size=0,hdr_s=0;
	
	hdr.version=2;
	hdr.padding=0;	
	hdr.pt=type;
	hdr_s=sizeof(hdr);
	switch (type) {
		case SR: {
			struct timeval ntp_time;
			RTCP_header_SR hdr_sr;
			int hdr_sr_s;
			//printf("SR\n");
			hdr_sr_s=sizeof(hdr_sr);
			pkt_size=hdr_s+hdr_sr_s;
			hdr.length=htons((pkt_size >> 2) -1);
			hdr.count=0;
			hdr_sr.ssrc=htonl(session->ssrc);

			gettimeofday(&ntp_time, NULL);
			hdr_sr.ntp_timestampH = htonl((unsigned int)ntp_time.tv_sec);
			hdr_sr.ntp_timestampL = htonl((unsigned int)ntp_time.tv_usec);
			hdr_sr.rtp_timestamp = htonl((unsigned int)((double)ntp_time.tv_sec + (double)ntp_time.tv_usec/1000000.) * session->current_media->description.clock_rate + session->start_rtptime);
			
			hdr_sr.pkt_count=session->rtcp_stats[i_server].pkt_count;
			hdr_sr.octet_count=session->rtcp_stats[i_server].octet_count;
			pkt=(unsigned char*)calloc(1,pkt_size);
			if (pkt==NULL) {
				return ERR_ALLOC;
			}			
			memcpy(pkt,&hdr,hdr_s);
			memcpy(pkt+hdr_s,&hdr_sr,hdr_sr_s);
			//fprintf(stderr,"pkt_size=%d,hdr_s=%d,hdr_sr_s=%d\n",pkt_size,hdr_s,hdr_sr_s);
			break;
		}
		case RR: {
			RTCP_header_RR hdr_rr;
			int hdr_rr_s;
			//printf("RR\n");
			hdr_rr_s=sizeof(hdr_rr);
			pkt_size=hdr_s+hdr_rr_s;
			hdr.length=htons((pkt_size >> 2) -1);
			hdr.count=0;
			hdr_rr.ssrc=htonl(session->ssrc);
			pkt=(unsigned char*)calloc(1,pkt_size);
			if (pkt==NULL) {
				return ERR_ALLOC;
			}			
			memcpy(pkt,&hdr,hdr_s);
			memcpy(pkt+hdr_s,&hdr_rr,hdr_rr_s);		
			break;		
		}		
		case SDES: {						
			RTCP_header_SDES hdr_sdes;
			char *name;
			int hdr_sdes_s,name_s;
			
			//printf("SDES\n");
			name=prefs_get_hostname();
			name_s=strlen(name);			
			hdr_sdes_s=sizeof(hdr_sdes);			
			
			pkt_size=(((hdr_s+hdr_sdes_s+name_s)%4)?1:0)+(hdr_s+hdr_sdes_s+name_s);			
			hdr.length=htons((pkt_size >> 2) -1);

			pkt=(unsigned char*)calloc(1,pkt_size);
			if (pkt==NULL) {
				return ERR_ALLOC;
			}
			hdr.count=1;
			hdr_sdes.ssrc=htonl(session->ssrc);
			hdr_sdes.attr_name=htonl(1);	// 1=CNAME
			hdr_sdes.len=htonl(name_s);
			memcpy(pkt,&hdr,hdr_s);
			memcpy(pkt+hdr_s,&hdr_sdes,hdr_sdes_s);
			memcpy(pkt+hdr_s+hdr_sdes_s,name,name_s);


			//fprintf(stderr,"pkt_size=%d,hdr_s=%d,hdr_sdes_s=%d,name_s=%d\n",pkt_size,hdr_s,hdr_sdes_s,name_s);
			
			break;
		}
		case BYE: {
			RTCP_header_BYE hdr_bye;
			int hdr_bye_s;
			char *reason="The medium is over.";
			//printf("BYE\n");
			hdr_bye_s=sizeof(hdr_bye);
			pkt_size=hdr_s+hdr_bye_s;
			hdr.length=htons((pkt_size >> 2) -1);
			hdr.count=1;
			hdr_bye.ssrc=htonl(session->ssrc);
			hdr_bye.length=htonl(strlen(reason));
			hdr_bye.ssrc=htonl(session->ssrc);			
			pkt=(unsigned char*)calloc(1,pkt_size);
			if (pkt==NULL) {
				return ERR_ALLOC;
			}			
			memcpy(pkt,&hdr,hdr_s);
			memcpy(pkt+hdr_s,&hdr_bye,hdr_bye_s);
			break;	
		}
		default: {			
			//printf("DEFAULT\n");
			return ERR_NOERROR;
		}
	}
	if (session->rtcp_outsize+pkt_size<=sizeof(session->rtcp_outbuffer)) {
		memcpy(session->rtcp_outbuffer+session->rtcp_outsize,pkt,pkt_size);
		session->rtcp_outsize+=pkt_size;
	}
	else {
		fnc_log(FNC_LOG_VERBOSE,"Output RTCP packet lost\n");
	}
	free(pkt);
	return ERR_NOERROR;
}
Ejemplo n.º 3
0
int RTSP_teardown(RTSP_buffer * rtsp)
{
	long int session_id;
	char *p;
	RTSP_session *s;
	RTP_session *rtp_curr, *rtp_prev = NULL, *rtp_temp;
	int valid_url;
	char object[255], server[255], trash[255], *filename;
	unsigned short port;
	char url[255];
	unsigned int cseq;

	// CSeq
	if ((p = strstr(rtsp->in_buffer, HDR_CSEQ)) == NULL) {
		send_reply(400, 0, rtsp);	/* Bad Request */
		return ERR_PARSE;
	} else {
		if (sscanf(p, "%254s %d", trash, &(rtsp->rtsp_cseq)) != 2) {
			send_reply(400, 0, rtsp);	/* Bad Request */
			return ERR_PARSE;
		}
	}
	cseq = rtsp->rtsp_cseq;
	/* Extract the URL */
	if (!sscanf(rtsp->in_buffer, " %*s %254s ", url)) {
		send_reply(400, 0, rtsp);	/* bad request */
		return ERR_PARSE;
	}
	/* Validate the URL */
	switch (parse_url(url, server, sizeof(server), &port, object, sizeof(object))) {
		case 1: // bad request
			send_reply(400, 0, rtsp);
			return ERR_PARSE;
			break;
		case -1: // internal server error
			send_reply(500, 0, rtsp);
			return ERR_PARSE;
			break;
		default:
			break;
	}
	if (strcmp(server, prefs_get_hostname()) != 0) {	/* Currently this feature is disabled. */
		/* wrong server name */
		//      send_reply(404, 0 , rtsp); /* Not Found */
		//      return ERR_PARSE;
	}
	if (strstr(object, "../")) {
		/* disallow relative paths outside of current directory. */
		send_reply(403, 0, rtsp);	/* Forbidden */
		return ERR_PARSE;
	}
	if (strstr(object, "./")) {
		/* Disallow ./ */
		send_reply(403, 0, rtsp);	/* Forbidden */
		return ERR_PARSE;
	}
	p = strrchr(object, '.');
	valid_url = 0;
	if (p == NULL) {
		send_reply(415, 0, rtsp);	/* Unsupported media type */
		return ERR_PARSE;
	} else {
		valid_url = is_supported_url(p);
	}
	if (!valid_url) {
		send_reply(415, 0, rtsp);	/* Unsupported media type */
		return ERR_PARSE;
	}
	// Session
	if ((p = strstr(rtsp->in_buffer, HDR_SESSION)) != NULL) {
		if (sscanf(p, "%254s %ld", trash, &session_id) != 2) {
			send_reply(454, 0, rtsp);	/* Session Not Found */
			return ERR_PARSE;
			// return ERR_NOERROR;
		}
	} else {
		session_id = -1;
	}
	s = rtsp->session_list;
	if (s == NULL) {
		send_reply(415, 0, rtsp);	// Internal server error
		return ERR_GENERIC;
	}
	if (s->session_id != session_id) {
		send_reply(454, 0, rtsp);	/* Session Not Found */
		return ERR_PARSE;
	}

	fnc_log(FNC_LOG_INFO,"TEARDOWN %s RTSP/1.0 ",url);
	send_teardown_reply(rtsp, session_id, cseq);
	// See User-Agent 
	if ((p=strstr(rtsp->in_buffer, HDR_USER_AGENT))!=NULL) {
		char cut[strlen(p)];
		strcpy(cut,p);
		p=strstr(cut, "\n");
		cut[strlen(cut)-strlen(p)-1]='\0';
		fnc_log(FNC_LOG_CLIENT,"%s\n",cut);
	}
	else
		fnc_log(FNC_LOG_CLIENT,"- \n");

	
	if (strchr(object, '!'))	/*Compatibility with RealOne and RealPlayer */
		filename = strchr(object, '!') + 1;
	else
		filename = object;



	// Release all URI RTP session
	rtp_curr = s->rtp_session;
	while (rtp_curr != NULL) {
		if (strcmp(rtp_curr->current_media->filename, filename) == 0
		    || strcmp(rtp_curr->current_media->aggregate, filename) == 0) {
			rtp_temp = rtp_curr;
			if (rtp_prev != NULL)
				rtp_prev->next = rtp_curr->next;
			else
				s->rtp_session = rtp_curr->next;
			rtp_curr = rtp_curr->next;
			// Release the scheduler entry
			schedule_remove(rtp_temp->sched_id);
			// Close connections
		} else {
			rtp_prev = rtp_curr;
			rtp_curr = rtp_curr->next;
		}
	}

	if (s->rtp_session == NULL) {
		// Close connection
		//close(s->fd);
		// Release the RTSP session
		free(rtsp->session_list);
		rtsp->session_list = NULL;
	}
	
	return ERR_NOERROR;
}
Ejemplo n.º 4
0
int RTSP_setup(RTSP_buffer * rtsp, RTSP_session ** new_session)
{
	char address[16];
	char object[255], server[255];
	char url[255];
	unsigned short port;
	RTSP_session *rtsp_s;
	RTP_session *rtp_s, *rtp_s_prec;
	int SessionID = 0;
//	port_pair cli_ports;
//	port_pair ser_ports;
	struct timeval now_tmp;
	char *p/* = NULL*/;
	unsigned int start_seq, start_rtptime;
	char transport_str[255];
	media_entry *list, *matching_me, req;
	struct sockaddr_storage rtsp_peer;
	socklen_t namelen = sizeof(rtsp_peer);
	unsigned long ssrc;
	SD_descr *matching_descr;
	unsigned char is_multicast_dad = 1;  //unicast and the first multicast
	RTP_transport transport;
	char *saved_ptr, *transport_tkn;
	int max_interlvd;

	// init
	memset(&req, 0, sizeof(req));
	memset(&transport, 0, sizeof(transport));
	
	// Parse the input message
	
	/* Get the URL */
	if (!sscanf(rtsp->in_buffer, " %*s %254s ", url)) {
		send_reply(400, 0, rtsp);	/* bad request */
		return ERR_NOERROR;
	}
	/* Validate the URL */
	switch (parse_url(url, server, sizeof(server), &port, object, sizeof(object))) {	//object is requested file's name
		case 1: // bad request
			send_reply(400, 0, rtsp);
			return ERR_NOERROR;
		case -1: // interanl server error
			send_reply(500, 0, rtsp);
			return ERR_NOERROR;
			break;
		default:
			break;
	}
	if (strcmp(server, prefs_get_hostname()) != 0) {	/* Currently this feature is disabled. */
		/* wrong server name */
		//      send_reply(404, 0 , rtsp); /* Not Found */
		//      return ERR_NOERROR;
	}
	if (strstr(object, "../")) {
		/* disallow relative paths outside of current directory. */
		send_reply(403, 0, rtsp);	/* Forbidden */
		return ERR_NOERROR;
	}
	if (strstr(object, "./")) {
		/* Disallow the ./ */
		send_reply(403, 0, rtsp);	/* Forbidden */
		return ERR_NOERROR;
	}

	if (!(p = strrchr(object, '.'))) {	// if filename is without extension
		send_reply(415, 0, rtsp);	/* Unsupported media type */
		return ERR_NOERROR;
	} else if (!is_supported_url(p)) {	//if filename's extension is not valid
		send_reply(415, 0, rtsp);	/* Unsupported media type */
		return ERR_NOERROR;
	}
	if ( !(p = strchr(object, '!')) ) {	//if '!' is not present then a file has not been specified
		send_reply(500, 0, rtsp);	/* Internal server error */
		return ERR_NOERROR;
	} else {
		// SETUP name.sd!stream
		strcpy(req.filename, p + 1);
		req.flags |= ME_FILENAME;

		*p = '\0';
	}

// ------------ START PATCH
	{
		char temp[255];
		char *pd=NULL;
		
		strcpy(temp, object);
#if 0
	printf("%s\n", object);
		// BEGIN 
		// if ( (p = strstr(temp, "/")) ) {
		if ( (p = strchr(temp, '/')) ) {
			strcpy(object, p + 1);	// CRITIC. 
		}
	printf("%s\n", temp);
#endif
		// pd = strstr(p, ".sd");	// this part is usefull in order to
		pd = strstr(temp, ".sd");
		if ( (p = strstr(pd + 1, ".sd")) ) {	// have compatibility with RealOne
			strcpy(object, pd + 4);	// CRITIC. 
		}		//Note: It's a critic part
		// END 
	}
// ------------ END PATCH
	if (enum_media(object, &matching_descr) != ERR_NOERROR) {
		send_reply(500, 0, rtsp);	/* Internal server error */
		return ERR_NOERROR;
	}
	list=matching_descr->me_list;

	if (get_media_entry(&req, list, &matching_me) == ERR_NOT_FOUND) {
		send_reply(404, 0, rtsp);	/* Not found */
		return ERR_NOERROR;
	}
	
	// Get the CSeq 
	if ((p = strstr(rtsp->in_buffer, HDR_CSEQ)) == NULL) {
		send_reply(400, 0, rtsp);	/* Bad Request */
		return ERR_NOERROR;
	} else {
		if (sscanf(p, "%*s %d", &(rtsp->rtsp_cseq)) != 1) {
			send_reply(400, 0, rtsp);	/* Bad Request */
			return ERR_NOERROR;
		}
	}
	/*if ((p = strstr(rtsp->in_buffer, "ssrc")) != NULL) {
		p = strchr(p, '=');
		sscanf(p + 1, "%lu", &ssrc);
	} else {*/
		ssrc = random32(0);
	//}
	
	// Start parsing the Transport header
	if ((p = strstr(rtsp->in_buffer, HDR_TRANSPORT)) == NULL) {
		send_reply(406, "Require: Transport settings" /* of rtp/udp;port=nnnn. "*/, rtsp);	/* Not Acceptable */
		return ERR_NOERROR;
	}
	if (sscanf(p, "%*10s%255s", transport_str) != 1) {
		fnc_log(FNC_LOG_ERR,"SETUP request malformed: Transport string is empty\n");
		send_reply(400, 0, rtsp);	/* Bad Request */
		return ERR_NOERROR;
	}
	printf("transport: %s\n", transport_str); // XXX tmp.
	
	// tokenize the coma seaparated list of transport settings:
	if ( !(transport_tkn=strtok_r(transport_str, ",", &saved_ptr)) ) {
		fnc_log(FNC_LOG_ERR,"Malformed Transport string from client\n");
		send_reply(400, 0, rtsp);	/* Bad Request */
		return ERR_NOERROR;
	}
	
	if (getpeername(rtsp->fd, (struct sockaddr *)&rtsp_peer, &namelen) != 0) {
		send_reply(415, 0, rtsp);	// Internal server error
		return ERR_GENERIC;
	}
	
	transport.type = RTP_no_transport;
	do { // search a good transport string
		if ( (p = strstr(transport_tkn, RTSP_RTP_AVP)) ) { // Transport: RTP/AVP
			p += strlen(RTSP_RTP_AVP);
			if ( !*p || (*p == ';') || (*p == ' ')) {
#if 0
				// if ((p = strstr(rtsp->in_buffer, "client_port")) == NULL && strstr(rtsp->in_buffer, "multicast") == NULL) {
				if ((p = strstr(transport_tkn, "client_port")) == NULL && strstr(transport_tkn, "multicast") == NULL) {
					send_reply(406, "Require: Transport settings of rtp/udp;port=nnnn. ", rtsp);	/* Not Acceptable */
					return ERR_NOERROR;
				}
#endif // #if 0
				if (strstr(transport_tkn, "unicast")) {
					if( (p = strstr(transport_tkn, "client_port")) ) {
						p = strstr(p, "=");
						sscanf(p + 1, "%d", &(transport.u.udp.cli_ports.RTP));
						p = strstr(p, "-");
						sscanf(p + 1, "%d", &(transport.u.udp.cli_ports.RTCP));
					}
					if (RTP_get_port_pair(&transport.u.udp.ser_ports) != ERR_NOERROR) {
						send_reply(500, 0, rtsp);	/* Internal server error */
						return ERR_GENERIC;
					}
					
					// strcpy(address, get_address());
					//UDP connection for outgoing RTP packets
					udp_connect(transport.u.udp.cli_ports.RTP, &transport.u.udp.rtp_peer, (*((struct sockaddr_in *) (&rtsp_peer))).sin_addr.s_addr,&transport.rtp_fd);
					//UDP connection for outgoing RTCP packets
					udp_connect(transport.u.udp.cli_ports.RTCP, &transport.u.udp.rtcp_out_peer,(*((struct sockaddr_in *) (&rtsp_peer))).sin_addr.s_addr, &transport.rtcp_fd_out);
					udp_open(transport.u.udp.ser_ports.RTCP, &transport.u.udp.rtcp_in_peer, &transport.rtcp_fd_in);	//bind
					
					transport.u.udp.is_multicast = 0;
				} else if ( matching_descr->flags & SD_FL_MULTICAST ) {	/*multicast*/
				//  TODO: make the difference between only multicast allowed or unicast fallback allowed.
					transport.u.udp.cli_ports.RTP = transport.u.udp.ser_ports.RTP =matching_me->rtp_multicast_port;
					transport.u.udp.cli_ports.RTCP = transport.u.udp.ser_ports.RTCP =matching_me->rtp_multicast_port+1;
					
					is_multicast_dad = 0;
					if (!(matching_descr->flags & SD_FL_MULTICAST_PORT) ) {	
						struct in_addr inp;
						unsigned char ttl=DEFAULT_TTL;
						struct ip_mreq mreq;

						mreq.imr_multiaddr.s_addr = inet_addr(matching_descr->multicast);
						mreq.imr_interface.s_addr = INADDR_ANY;
						setsockopt(transport.rtp_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
						setsockopt(transport.rtp_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));

						is_multicast_dad = 1;
						strcpy(address, matching_descr->multicast);
						//RTP outgoing packets
						inet_aton(address, &inp);
						udp_connect(transport.u.udp.ser_ports.RTP, &transport.u.udp.rtp_peer, inp.s_addr, &transport.rtp_fd);
						//RTCP outgoing packets
						inet_aton(address, &inp);
						udp_connect(transport.u.udp.ser_ports.RTCP, &transport.u.udp.rtcp_out_peer, inp.s_addr, &transport.rtcp_fd_out);
						//udp_open(transport.u.udp.ser_ports.RTCP, &(sp2->rtcp_in_peer), &(sp2->rtcp_fd_in));	//bind 
			
						if(matching_me->next==NULL)
							matching_descr->flags |= SD_FL_MULTICAST_PORT;
			
						matching_me->rtp_multicast_port = transport.u.udp.ser_ports.RTP;
						transport.u.udp.is_multicast = 1;
						fnc_log(FNC_LOG_DEBUG,"\nSet up socket for multicast ok\n");
					}
				} else
					continue;
				
				transport.type = RTP_rtp_avp;
				break; // found a valid transport
			} else if (!strncmp(p, "/TCP", 4)) { // Transport: RTP/AVP/TCP;interleaved=x-y // XXX still not finished
				if( (p = strstr(transport_tkn, "interleaved")) ) {
					p = strstr(p, "=");
					sscanf(p + 1, "%d", &(transport.u.tcp.interleaved.RTP));
					if ( (p = strstr(p, "-")) )
						sscanf(p + 1, "%d", &(transport.u.tcp.interleaved.RTCP));
					else
						transport.u.tcp.interleaved.RTCP = transport.u.tcp.interleaved.RTP + 1;
				} else { // search for max used interleved channel.
					max_interlvd = -1;
					for (rtp_s = (rtsp->session_list)?rtsp->session_list->rtp_session:NULL; rtp_s; rtp_s = rtp_s->next)
						max_interlvd = max(max_interlvd, (rtp_s->transport.type == RTP_rtp_avp_tcp)?rtp_s->transport.u.tcp.interleaved.RTCP:-1);
					transport.u.tcp.interleaved.RTP = max_interlvd + 1;
				 	transport.u.tcp.interleaved.RTCP = max_interlvd + 2;
				}
					
				transport.rtp_fd = rtsp->fd; // dup(rtsp->fd);
				transport.rtcp_fd_out = rtsp->fd; // dup(rtsp->fd);
				transport.rtcp_fd_in = -1;
					
				transport.type = RTP_rtp_avp_tcp;
				break; // found a valid transport
			}
		}
	} while ((transport_tkn=strtok_r(NULL, ",", &saved_ptr)));
	printf("rtp transport: %d\n", transport.type);
	
	if (transport.type == RTP_no_transport) {
		// fnc_log(FNC_LOG_ERR,"Unsupported Transport\n");
		send_reply(461, "Unsupported Transport", rtsp);	/* Bad Request */
		return ERR_NOERROR;
	}

	// If there's a Session header we have an aggregate control
	if ((p = strstr(rtsp->in_buffer, HDR_SESSION)) != NULL) {
		if (sscanf(p, "%*s %d", &SessionID) != 1) {
			send_reply(454, 0, rtsp);	/* Session Not Found */
			return ERR_NOERROR;
		}
	} else {
		// Generate a random Session number
		gettimeofday(&now_tmp, 0);
		srand((now_tmp.tv_sec * 1000) + (now_tmp.tv_usec / 1000));
#ifdef WIN32
		SessionID = rand();
#else
		SessionID = 1 + (int) (10.0 * rand() / (100000 + 1.0));
#endif
		if (SessionID == 0) {
			SessionID++;
		}
	}

	// Add an RTSP session if necessary
	if ( !rtsp->session_list ) {
		rtsp->session_list = (RTSP_session *) calloc(1, sizeof(RTSP_session));
	}
	rtsp_s = rtsp->session_list;
	
	// Setup the RTP session
	if (rtsp->session_list->rtp_session == NULL) {
		rtsp->session_list->rtp_session = (RTP_session *) calloc(1, sizeof(RTP_session));
		rtp_s = rtsp->session_list->rtp_session;
	} else {
		for (rtp_s = rtsp_s->rtp_session; rtp_s != NULL; rtp_s = rtp_s->next) {
			rtp_s_prec = rtp_s;
		}
		rtp_s_prec->next = (RTP_session *) calloc(1, sizeof(RTP_session));
		rtp_s = rtp_s_prec->next;
	}


#ifdef WIN32
	start_seq = rand();
	start_rtptime = rand();
#else
	// start_seq = 1 + (int) (10.0 * rand() / (100000 + 1.0));
	// start_rtptime = 1 + (int) (10.0 * rand() / (100000 + 1.0));
#if 0
	start_seq = 1 + (unsigned int) ((float)(0xFFFF) * ((float)rand() / (float)RAND_MAX));
	start_rtptime = 1 + (unsigned int) ((float)(0xFFFFFFFF) * ((float)rand() / (float)RAND_MAX));
#else
	start_seq = 1 + (unsigned int) (rand()%(0xFFFF));
	start_rtptime = 1 + (unsigned int) (rand()%(0xFFFFFFFF));
#endif
#endif
	if (start_seq == 0) {
		start_seq++;
	}
	if (start_rtptime == 0) {
		start_rtptime++;
	}
	rtp_s->pause = 1;
	strcpy(rtp_s->sd_filename, object);
	/*xxx*/
	rtp_s->current_media = (media_entry *) calloc(1, sizeof(media_entry));
	
	// if(!(matching_descr->flags & SD_FL_MULTICAST_PORT)){
	if( is_multicast_dad ) {
		if ( mediacpy(&rtp_s->current_media, &matching_me) ) {
			send_reply(500, 0, rtsp);	/* Internal server error */
			return ERR_GENERIC;
		}
	}

	gettimeofday(&now_tmp, 0);
	srand((now_tmp.tv_sec * 1000) + (now_tmp.tv_usec / 1000));
	rtp_s->start_rtptime = start_rtptime;
	rtp_s->start_seq = start_seq;
	memcpy(&rtp_s->transport, &transport, sizeof(transport));
	rtp_s->is_multicast_dad = is_multicast_dad;

	/*xxx*/
	rtp_s->sd_descr=matching_descr;
	
	rtp_s->sched_id = schedule_add(rtp_s);


	rtp_s->ssrc = ssrc;
	// Setup the RTSP session       
	rtsp_s->session_id = SessionID;
	*new_session = rtsp_s;

	fnc_log(FNC_LOG_INFO,"SETUP %s RTSP/1.0 ",url);
	send_setup_reply(rtsp, rtsp_s, matching_descr, rtp_s);	
	// See User-Agent 
	if ((p=strstr(rtsp->in_buffer, HDR_USER_AGENT))!=NULL) {
		char cut[strlen(p)];
		strcpy(cut,p);
		p=strstr(cut, "\n");
		cut[strlen(cut)-strlen(p)-1]='\0';
		fnc_log(FNC_LOG_CLIENT,"%s\n",cut);
	}
	else
		fnc_log(FNC_LOG_CLIENT,"- \n");

	return ERR_NOERROR;
}
Ejemplo n.º 5
0
/*
 	****************************************************************
 	*			DESCRIBE METHOD HANDLING
 	****************************************************************
*/
int RTSP_describe(RTSP_buffer * rtsp)
{
	int valid_url, res;
	char object[255], server[255], trash[255];
	char *p;
	unsigned short port;
	char url[255];
	media_entry media, req;
	description_format descr_format = df_SDP_format;	// shawill put to some default
	char descr[MAX_DESCR_LENGTH];


	/* Extract la URL */
	if (!sscanf(rtsp->in_buffer, " %*s %254s ", url)) {
		send_reply(400, 0, rtsp);	/* bad request */
		return ERR_NOERROR;
	}
	/* Validate the URL */
	switch (parse_url(url, server, sizeof(server), &port, object, sizeof(object))) {
		case 1: // bad request
			send_reply(400, 0, rtsp);
			return ERR_NOERROR;
			break;
		case -1: // internal server error
			send_reply(500, 0, rtsp);
			return ERR_NOERROR;
			break;
		default:
			break;
	}
	if (strcmp(server, prefs_get_hostname()) != 0) {	/* Currently this feature is disabled. */
		/* wrong server name */
		//      send_reply(404, 0 , rtsp);  /* Not Found */
		//      return ERR_NOERROR;
	}
	if (strstr(object, "../")) {
		/* disallow relative paths outside of current directory. */
		send_reply(403, 0, rtsp);	/* Forbidden */
		return ERR_NOERROR;
	}
	if (strstr(object, "./")) {
		/* Disallow ./ */
		send_reply(403, 0, rtsp);	/* Forbidden */
		return ERR_NOERROR;
	}
	p = strrchr(object, '.');
	valid_url = 0;
	if (p == NULL) {
		send_reply(415, 0, rtsp);	/* Unsupported media type */
		return ERR_NOERROR;
	} else {
		valid_url = is_supported_url(p);
	}
	if (!valid_url) {
		send_reply(415, 0, rtsp);	/* Unsupported media type */
		return ERR_NOERROR;
	}
	// Disallow Header REQUIRE
	if (strstr(rtsp->in_buffer, HDR_REQUIRE)) {
		send_reply(551, 0, rtsp);	/* Option not supported */
		return ERR_NOERROR;
	}


	/* Get the description format. SDP is recomended */
	if (strstr(rtsp->in_buffer, HDR_ACCEPT) != NULL) {
		if (strstr(rtsp->in_buffer, "application/sdp") != NULL) {
			descr_format = df_SDP_format;
		} else {
			// Add here new description formats
			send_reply(551, 0, rtsp);	/* Option not supported */
			return ERR_NOERROR;
		}
	}
	// Get the CSeq 
	if ((p = strstr(rtsp->in_buffer, HDR_CSEQ)) == NULL) {
		send_reply(400, 0, rtsp);	/* Bad Request */
		return ERR_NOERROR;
	} else {
		if (sscanf(p, "%254s %d", trash, &(rtsp->rtsp_cseq)) != 2) {
			send_reply(400, 0, rtsp);	/* Bad Request */
			return ERR_NOERROR;
		}
	}


	memset(&media, 0, sizeof(media));
	memset(&req, 0, sizeof(req));
	req.flags = ME_DESCR_FORMAT;
	req.descr_format = descr_format;
	res = get_media_descr(object, &req, &media, descr);
	if (res == ERR_NOT_FOUND) {
		send_reply(404, 0, rtsp);	// Not found
		return ERR_NOERROR;
	}
	if (res == ERR_PARSE || res == ERR_GENERIC || res == ERR_ALLOC) {
		send_reply(500, 0, rtsp);	// Internal server error
		return ERR_NOERROR;
	}

	if(max_connection()==ERR_GENERIC){
		/*redirect*/
		return send_redirect_3xx(rtsp, object);
	}


	fnc_log(FNC_LOG_INFO,"DESCRIBE %s RTSP/1.0 ",url);
	send_describe_reply(rtsp, object, descr_format, descr);
	
	// See User-Agent 
	if ((p=strstr(rtsp->in_buffer, HDR_USER_AGENT))!=NULL) {
		char cut[strlen(p)];
		strcpy(cut,p);
		p=strstr(cut, "\n");
		cut[strlen(cut)-strlen(p)-1]='\0';
		fnc_log(FNC_LOG_CLIENT,"%s\n",cut);
	}
	else
		fnc_log(FNC_LOG_CLIENT,"- \n");

	return ERR_NOERROR;
}