Example #1
0
M4Err SDP_Parse(SDPInfo *sdp, char *sdp_text, u32 text_size)
{
	SDPBandwidth *bw;
	SDPConnection *conn;
	SDPMedia *media;
	SDPTiming *timing;
	u32 i;
	s32 pos, LinePos;
	char LineBuf[3000], comp[3000];

	media = NULL;
	timing = NULL;

	if (!sdp) return M4BadParam;

	//Clean SDP info
	SDP_Reset(sdp);

	LinePos = 0;
	while (1) {
		LinePos = SP_GetOneLine(sdp_text, LinePos, text_size, LineBuf, 3000);
		if (LinePos <= 0) break;
		if (!strcmp(LineBuf, "\r\n") || !strcmp(LineBuf, "\n") || !strcmp(LineBuf, "\r")) continue;


		switch (LineBuf[0]) {
		case 'v':
			pos = SP_GetComponent(LineBuf, 2, "\t\r\n", comp, 3000);
			sdp->Version = atoi(comp);
			break;
		case 'o':
			pos = SP_GetComponent(LineBuf, 2, " \t\r\n", comp, 3000);
			sdp->o_username = strdup(comp);
			pos = SP_GetComponent(LineBuf, pos, " \t\r\n", comp, 3000);
			sdp->o_session_id = strdup(comp);
			pos = SP_GetComponent(LineBuf, pos, " \t\r\n", comp, 3000);
			sdp->o_version = strdup(comp);
			
			pos = SP_GetComponent(LineBuf, pos, " \t\r\n", comp, 3000);
			sdp->o_net_type = strdup(comp);

			pos = SP_GetComponent(LineBuf, pos, " \t\r\n", comp, 3000);
			sdp->o_add_type = strdup(comp);

			pos = SP_GetComponent(LineBuf, pos, " \t\r\n", comp, 3000);
			sdp->o_address = strdup(comp);
			break;
		case 's':
			pos = SP_GetComponent(LineBuf, 2, "\t\r\n", comp, 3000);
			sdp->s_session_name = strdup(comp);
			break;
		case 'i':
			pos = SP_GetComponent(LineBuf, 2, "\t\r\n", comp, 3000);
			sdp->i_description = strdup(comp);
			break;
		case 'u':
			pos = SP_GetComponent(LineBuf, 2, "\t\r\n", comp, 3000);
			sdp->u_uri = strdup(comp);
			break;
		case 'e':
			pos = SP_GetComponent(LineBuf, 2, "\t\r\n", comp, 3000);
			sdp->e_email = strdup(comp);
			break;
		case 'p':
			pos = SP_GetComponent(LineBuf, 2, "\t\r\n", comp, 3000);
			sdp->p_phone = strdup(comp);
			break;
		case 'c':
			//if at session level, only 1 is allowed for all SDP
			if (sdp->c_connection) break;
			
			conn = SDP_NewConnection();

			pos = SP_GetComponent(LineBuf, 2, " \t\r\n", comp, 3000);
			conn->net_type = strdup(comp);
			
			pos = SP_GetComponent(LineBuf, pos, " \t\r\n", comp, 3000);
			conn->add_type = strdup(comp);

			pos = SP_GetComponent(LineBuf, pos, " /\r\n", comp, 3000);
			conn->host = strdup(comp);
			if (SK_IsMulticastAddress(conn->host)) {
				//a valid SDP will have TTL if address is multicast
				pos = SP_GetComponent(LineBuf, pos, "/\r\n", comp, 3000);
				if (pos <= 0) {
					SDP_DeleteConnection(conn);
					break;
				}
				conn->TTL = atoi(comp);
				//multiple address indication is only valid for media
				pos = SP_GetComponent(LineBuf, pos, "/\r\n", comp, 3000);
				if (pos > 0) {
					if (!media) {
						SDP_DeleteConnection(conn);
						break;
					}
					conn->add_count = atoi(comp);
				}
			}
			if (!media) 
				sdp->c_connection = conn;
			else 
				ChainAddEntry(media->Connections, conn);

			break;
		case 'b':
			pos = SP_GetComponent(LineBuf, 2, ":\r\n", comp, 3000);
			if (strcmp(comp, "CT") && strcmp(comp, "AS") && (comp[0] != 'X')) break;

			bw = malloc(sizeof(SDPBandwidth));
			bw->name = strdup(comp);
			pos = SP_GetComponent(LineBuf, pos, ":\r\n", comp, 3000);
			bw->value = atoi(comp);
			if (media) {
				ChainAddEntry(media->Bandwidths, bw);
			} else {
				ChainAddEntry(sdp->b_bandwidth, bw);
			}
			break;

		case 't':
			if (media) break;
			//create a new time structure for each entry
			timing = malloc(sizeof(SDPTiming));
			memset(timing, 0, sizeof(SDPTiming));
			pos = SP_GetComponent(LineBuf, 2, " \t\r\n", comp, 3000);
			timing->StartTime = atoi(comp);
			pos = SP_GetComponent(LineBuf, pos, "\r\n", comp, 3000);
			timing->StopTime = atoi(comp);
			ChainAddEntry(sdp->Timing, timing);
			break;
		case 'r':
			if (media) break;
			pos = SP_GetComponent(LineBuf, 2, " \t\r\n", comp, 3000);
			timing->RepeatInterval = SDP_MakeSeconds(comp);
			pos = SP_GetComponent(LineBuf, pos, " \t\r\n", comp, 3000);
			timing->ActiveDuration = SDP_MakeSeconds(comp);
			while (1) {
				pos = SP_GetComponent(LineBuf, pos, " \t\r\n", comp, 3000);
				if (pos <= 0) break;
				timing->OffsetFromStart[timing->NbRepeatOffsets] = SDP_MakeSeconds(comp);
				timing->NbRepeatOffsets += 1;
			}
			break;
		case 'z':
			if (media) break;
			pos = 2;
			while (1) {
				pos = SP_GetComponent(LineBuf, pos, " \t\r\n", comp, 3000);
				if (pos <= 0) break;
				timing->AdjustmentTime[timing->NbZoneOffsets] = atoi(comp);
				pos = SP_GetComponent(LineBuf, pos, " \t\r\n", comp, 3000);
				timing->AdjustmentOffset[timing->NbZoneOffsets] = SDP_MakeSeconds(comp);
				timing->NbZoneOffsets += 1;
			}
			break;
		case 'k':
			pos = SP_GetComponent(LineBuf, 2, ":\t\r\n", comp, 3000);
			if (media) {
				media->k_method = strdup(comp);
			} else {
				sdp->k_method = strdup(comp);
			}
			pos = SP_GetComponent(LineBuf, pos, ":\r\n", comp, 3000);
			if (pos > 0) {
				if (media) {
					media->k_key = strdup(comp);
				} else {
					sdp->k_key = strdup(comp);
				}
			}
			break;
		case 'a':
			SDP_ParseAttribute(sdp, LineBuf+2, media);
			break;
		case 'm':
			pos = SP_GetComponent(LineBuf, 2, " \t\r\n", comp, 3000);
			if (strcmp(comp, "audio") 
				&& strcmp(comp, "data") 
				&& strcmp(comp, "control") 
				&& strcmp(comp, "video") 
				&& strcmp(comp, "text") 
				&& strcmp(comp, "application")) {
				return M4ServiceError;
			}
			media = SDP_NewMedia();
			//media type
			if (!strcmp(comp, "video")) media->Type = 1;
			else if (!strcmp(comp, "audio")) media->Type = 2;
			else if (!strcmp(comp, "text")) media->Type = 3;
			else if (!strcmp(comp, "data")) media->Type = 4;
			else if (!strcmp(comp, "control")) media->Type = 5;
			else media->Type = 0;
			//port numbers			
			SP_GetComponent(LineBuf, pos, " ", comp, 3000);
			if (!strstr(comp, "/")) {
				pos = SP_GetComponent(LineBuf, pos, " \r\n", comp, 3000);
				media->PortNumber = atoi(comp);
				media->NumPorts = 0;
			} else {
				pos = SP_GetComponent(LineBuf, pos, " /\r\n", comp, 3000);
				media->PortNumber = atoi(comp);
				pos = SP_GetComponent(LineBuf, pos, " \r\n", comp, 3000);
				media->NumPorts = atoi(comp);
			}
			//transport Profile
			pos = SP_GetComponent(LineBuf, pos, " \r\n", comp, 3000);
			media->Profile = strdup(comp);
			pos = SP_GetComponent(LineBuf, pos, " \r\n", comp, 3000);
			media->fmt_list = strdup(comp);

			ChainAddEntry(sdp->media_desc, media);
			break;
		}
	}
	//finally rewrite the fmt_list for all media, and remove dynamic payloads 
	//from the list
	for (i=0; i<ChainGetCount(sdp->media_desc); i++) {
		media = ChainGetEntry(sdp->media_desc, i);
		pos = 0;
		LinePos = 1;
		strcpy(LineBuf, "");
		while (1) {
			if (!media->fmt_list) break;
			pos = SP_GetComponent(media->fmt_list, pos, " ", comp, 3000);
			if (pos <= 0) break;
			if (!SDP_IsDynamicPayload(media, comp)) {
				if (!LinePos) {
					strcat(LineBuf, " ");
				} else {
					LinePos = 0;
				}
				strcat(LineBuf, comp);
			}
			free(media->fmt_list);
			media->fmt_list = NULL;
			if (strlen(LineBuf)) {
				media->fmt_list = strdup(LineBuf);
			}
		}
	}
	return M4OK;
}
Example #2
0
GF_EXPORT
GF_Err gf_sdp_info_parse(GF_SDPInfo *sdp, char *sdp_text, u32 text_size)
{
	GF_SDPBandwidth *bw;
	GF_SDPConnection *conn;
	GF_SDPMedia *media;
	GF_SDPTiming *timing;
	u32 i;
	s32 pos, LinePos;
	char LineBuf[3000], comp[3000];

	media = NULL;
	timing = NULL;

	if (!sdp) return GF_BAD_PARAM;

	//Clean SDP info
	gf_sdp_info_reset(sdp);

	LinePos = 0;
	while (1) {
		LinePos = gf_token_get_line(sdp_text, LinePos, text_size, LineBuf, 3000);
		if (LinePos <= 0) break;
		if (!strcmp(LineBuf, "\r\n") || !strcmp(LineBuf, "\n") || !strcmp(LineBuf, "\r")) continue;


		switch (LineBuf[0]) {
		case 'v':
			pos = gf_token_get(LineBuf, 2, "\t\r\n", comp, 3000);
			sdp->Version = atoi(comp);
			break;
		case 'o':
			pos = gf_token_get(LineBuf, 2, " \t\r\n", comp, 3000);
			sdp->o_username = gf_strdup(comp);
			pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000);
			sdp->o_session_id = gf_strdup(comp);
			pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000);
			sdp->o_version = gf_strdup(comp);
			
			pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000);
			sdp->o_net_type = gf_strdup(comp);

			pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000);
			sdp->o_add_type = gf_strdup(comp);

			pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000);
			sdp->o_address = gf_strdup(comp);
			break;
		case 's':
			pos = gf_token_get(LineBuf, 2, "\t\r\n", comp, 3000);
			sdp->s_session_name = gf_strdup(comp);
			break;
		case 'i':
			pos = gf_token_get(LineBuf, 2, "\t\r\n", comp, 3000);
			sdp->i_description = gf_strdup(comp);
			break;
		case 'u':
			pos = gf_token_get(LineBuf, 2, "\t\r\n", comp, 3000);
			sdp->u_uri = gf_strdup(comp);
			break;
		case 'e':
			pos = gf_token_get(LineBuf, 2, "\t\r\n", comp, 3000);
			sdp->e_email = gf_strdup(comp);
			break;
		case 'p':
			pos = gf_token_get(LineBuf, 2, "\t\r\n", comp, 3000);
			sdp->p_phone = gf_strdup(comp);
			break;
		case 'c':
			//if at session level, only 1 is allowed for all SDP
			if (sdp->c_connection) break;
			
			conn = gf_sdp_conn_new();

			pos = gf_token_get(LineBuf, 2, " \t\r\n", comp, 3000);
			conn->net_type = gf_strdup(comp);
			
			pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000);
			conn->add_type = gf_strdup(comp);

			pos = gf_token_get(LineBuf, pos, " /\r\n", comp, 3000);
			conn->host = gf_strdup(comp);
			if (gf_sk_is_multicast_address(conn->host)) {
				//a valid SDP will have TTL if address is multicast
				pos = gf_token_get(LineBuf, pos, "/\r\n", comp, 3000);
				if (pos > 0) {
					conn->TTL = atoi(comp);
					//multiple address indication is only valid for media
					pos = gf_token_get(LineBuf, pos, "/\r\n", comp, 3000);
				}
				if (pos > 0) {
					if (!media) {
						gf_sdp_conn_del(conn);
						break;
					}
					conn->add_count = atoi(comp);
				}
			}
			if (!media) 
				sdp->c_connection = conn;
			else 
				gf_list_add(media->Connections, conn);

			break;
		case 'b':
			pos = gf_token_get(LineBuf, 2, ":\r\n", comp, 3000);
			if (strcmp(comp, "CT") && strcmp(comp, "AS") && (comp[0] != 'X')) break;

			bw = (GF_SDPBandwidth*)gf_malloc(sizeof(GF_SDPBandwidth));
			bw->name = gf_strdup(comp);
			pos = gf_token_get(LineBuf, pos, ":\r\n", comp, 3000);
			bw->value = atoi(comp);
			if (media) {
				gf_list_add(media->Bandwidths, bw);
			} else {
				gf_list_add(sdp->b_bandwidth, bw);
			}
			break;

		case 't':
			if (media) break;
			//create a new time structure for each entry
			GF_SAFEALLOC(timing, GF_SDPTiming);
			pos = gf_token_get(LineBuf, 2, " \t\r\n", comp, 3000);
			timing->StartTime = atoi(comp);
			pos = gf_token_get(LineBuf, pos, "\r\n", comp, 3000);
			timing->StopTime = atoi(comp);
			gf_list_add(sdp->Timing, timing);
			break;
		case 'r':
			if (media) break;
			pos = gf_token_get(LineBuf, 2, " \t\r\n", comp, 3000);
			timing->RepeatInterval = SDP_MakeSeconds(comp);
			pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000);
			timing->ActiveDuration = SDP_MakeSeconds(comp);
			while (1) {
				pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000);
				if (pos <= 0) break;
				timing->OffsetFromStart[timing->NbRepeatOffsets] = SDP_MakeSeconds(comp);
				timing->NbRepeatOffsets += 1;
			}
			break;
		case 'z':
			if (media) break;
			pos = 2;
			while (1) {
				pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000);
				if (pos <= 0) break;
				timing->AdjustmentTime[timing->NbZoneOffsets] = atoi(comp);
				pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000);
				timing->AdjustmentOffset[timing->NbZoneOffsets] = SDP_MakeSeconds(comp);
				timing->NbZoneOffsets += 1;
			}
			break;
		case 'k':
			pos = gf_token_get(LineBuf, 2, ":\t\r\n", comp, 3000);
			if (media) {
				media->k_method = gf_strdup(comp);
			} else {
				sdp->k_method = gf_strdup(comp);
			}
			pos = gf_token_get(LineBuf, pos, ":\r\n", comp, 3000);
			if (pos > 0) {
				if (media) {
					media->k_key = gf_strdup(comp);
				} else {
					sdp->k_key = gf_strdup(comp);
				}
			}
			break;
		case 'a':
			SDP_ParseAttribute(sdp, LineBuf+2, media);
			break;
		case 'm':
			pos = gf_token_get(LineBuf, 2, " \t\r\n", comp, 3000);
			if (strcmp(comp, "audio") 
				&& strcmp(comp, "data") 
				&& strcmp(comp, "control") 
				&& strcmp(comp, "video") 
				&& strcmp(comp, "text") 
				&& strcmp(comp, "application")) {
				return GF_SERVICE_ERROR;
			}
			media = gf_sdp_media_new();
			//media type
			if (!strcmp(comp, "video")) media->Type = 1;
			else if (!strcmp(comp, "audio")) media->Type = 2;
			else if (!strcmp(comp, "text")) media->Type = 3;
			else if (!strcmp(comp, "data")) media->Type = 4;
			else if (!strcmp(comp, "control")) media->Type = 5;
			else media->Type = 0;
			//port numbers			
			gf_token_get(LineBuf, pos, " ", comp, 3000);
			if (!strstr(comp, "/")) {
				pos = gf_token_get(LineBuf, pos, " \r\n", comp, 3000);
				media->PortNumber = atoi(comp);
				media->NumPorts = 0;
			} else {
				pos = gf_token_get(LineBuf, pos, " /\r\n", comp, 3000);
				media->PortNumber = atoi(comp);
				pos = gf_token_get(LineBuf, pos, " \r\n", comp, 3000);
				media->NumPorts = atoi(comp);
			}
			//transport Profile
			pos = gf_token_get(LineBuf, pos, " \r\n", comp, 3000);
			media->Profile = gf_strdup(comp);
			pos = gf_token_get(LineBuf, pos, " \r\n", comp, 3000);
			media->fmt_list = gf_strdup(comp);

			gf_list_add(sdp->media_desc, media);
			break;
		}
	}
	//finally rewrite the fmt_list for all media, and remove dynamic payloads 
	//from the list
	i=0;
	while ((media = (GF_SDPMedia*)gf_list_enum(sdp->media_desc, &i))) {
		pos = 0;
		LinePos = 1;
		strcpy(LineBuf, "");
		while (1) {
			if (!media->fmt_list) break;
			pos = gf_token_get(media->fmt_list, pos, " ", comp, 3000);
			if (pos <= 0) break;
			if (!SDP_IsDynamicPayload(media, comp)) {
				if (!LinePos) {
					strcat(LineBuf, " ");
				} else {
					LinePos = 0;
				}
				strcat(LineBuf, comp);
			}
			gf_free(media->fmt_list);
			media->fmt_list = NULL;
			if (strlen(LineBuf)) {
				media->fmt_list = gf_strdup(LineBuf);
			}
		}
	}
	return GF_OK;
}