//return M4BadParam if invalid structure, M4SignalingFailure if bad formatting //or M4OK M4Err SDP_CheckInfo(SDPInfo *sdp) { M4Err e; u32 i, j; SDPMedia *media; SDPConnection *conn; SDP_RTPMap *map; Bool HasGlobalConnection, HasSeveralPorts; if (!sdp || !sdp->media_desc || !sdp->Attributes) return M4BadParam; //we force at least one media per SDP if (!ChainGetCount(sdp->media_desc)) return M4SignalingFailure; //normative fields //o= if (!sdp->o_add_type || !sdp->o_address || !sdp->o_username || !sdp->o_session_id || !sdp->o_version) return M4SignalingFailure; //s= if (!sdp->s_session_name) return M4SignalingFailure; //t= // if () return M4SignalingFailure; //c= if (sdp->c_connection) { e = SDP_CheckConnection(sdp->c_connection); if (e) return e; //multiple addresses are only for media desc if (sdp->c_connection->add_count >= 2) return M4SignalingFailure; HasGlobalConnection = 1; } else { HasGlobalConnection = 0; } //then check all media for (i=0; i<ChainGetCount(sdp->media_desc); i++) { media = ChainGetEntry(sdp->media_desc, i); HasSeveralPorts = 0; //m= : force non-null port, profile and fmt_list if (!media->PortNumber || !media->Profile) return M4SignalingFailure; if (media->NumPorts) HasSeveralPorts = 1; //no connections specified - THIS IS AN ERROR IN SDP BUT NOT IN ALL RTSP SESSIONS... // if (!HasGlobalConnection && !ChainGetCount(media->Connections)) return M4SignalingFailure; //too many connections specified if (HasGlobalConnection && ChainGetCount(media->Connections)) return M4SignalingFailure; //check all connections, and make sure we don't have multiple addresses //and multiple ports at the same time if (ChainGetCount(media->Connections)>1 && HasSeveralPorts) return M4SignalingFailure; for (j=0; j<ChainGetCount(media->Connections); j++) { conn = ChainGetEntry(media->Connections, j); e = SDP_CheckConnection(conn); if (e) return e; if ((conn->add_count >= 2) && HasSeveralPorts) return M4SignalingFailure; } //RTPMaps. 0 is tolerated, but if some are specified check them for (j=0; j<ChainGetCount(media->RTPMaps); j++) { map = ChainGetEntry(media->RTPMaps, j); //RFC2327 is not clear here, but we assume the PayloadType should be a DYN one //however this depends on the profile (RTP/AVP or others) so don't check it //ClockRate SHALL NOT be NULL if (!map->payload_name || !map->ClockRate) return M4SignalingFailure; } } //Encryption: nothing tells wether the scope of the global key is eclusive or not. //we accept a global key + keys per media entry, assuming that the media key primes //on the global key return M4OK; }
//return GF_BAD_PARAM if invalid structure, GF_REMOTE_SERVICE_ERROR if bad formatting //or GF_OK GF_EXPORT GF_Err gf_sdp_info_check(GF_SDPInfo *sdp) { GF_Err e; u32 i, j, count; GF_SDPMedia *media; GF_SDPConnection *conn; GF_RTPMap *map; Bool HasGlobalConnection, HasSeveralPorts; if (!sdp || !sdp->media_desc || !sdp->Attributes) return GF_BAD_PARAM; //we force at least one media per SDP if (!gf_list_count(sdp->media_desc)) return GF_REMOTE_SERVICE_ERROR; //normative fields //o= if (!sdp->o_add_type || !sdp->o_address || !sdp->o_username || !sdp->o_session_id || !sdp->o_version) return GF_REMOTE_SERVICE_ERROR; //s= //commented for intermedia demos // if (!sdp->s_session_name) return GF_REMOTE_SERVICE_ERROR; //t= // if () return GF_REMOTE_SERVICE_ERROR; //c= if (sdp->c_connection) { e = SDP_CheckConnection(sdp->c_connection); if (e) return e; //multiple addresses are only for media desc if (sdp->c_connection->add_count >= 2) return GF_REMOTE_SERVICE_ERROR; HasGlobalConnection = 1; } else { HasGlobalConnection = 0; } //then check all media i=0; while ((media = (GF_SDPMedia*)gf_list_enum(sdp->media_desc, &i))) { HasSeveralPorts = 0; //m= : force non-null port, profile and fmt_list if (/*!media->PortNumber || */ !media->Profile) return GF_REMOTE_SERVICE_ERROR; if (media->NumPorts) HasSeveralPorts = 1; //no connections specified - THIS IS AN ERROR IN SDP BUT NOT IN ALL RTSP SESSIONS... // if (!HasGlobalConnection && !gf_list_count(media->Connections)) return GF_REMOTE_SERVICE_ERROR; //too many connections specified if (HasGlobalConnection && gf_list_count(media->Connections)) return GF_REMOTE_SERVICE_ERROR; //check all connections, and make sure we don't have multiple addresses //and multiple ports at the same time count = gf_list_count(media->Connections); if (count>1 && HasSeveralPorts) return GF_REMOTE_SERVICE_ERROR; for (j=0; j<count; j++) { conn = (GF_SDPConnection*)gf_list_get(media->Connections, j); e = SDP_CheckConnection(conn); if (e) return e; if ((conn->add_count >= 2) && HasSeveralPorts) return GF_REMOTE_SERVICE_ERROR; } //RTPMaps. 0 is tolerated, but if some are specified check them j=0; while ((map = (GF_RTPMap*)gf_list_enum(media->RTPMaps, &j))) { //RFC2327 is not clear here, but we assume the PayloadType should be a DYN one //however this depends on the profile (RTP/AVP or others) so don't check it //ClockRate SHALL NOT be NULL if (!map->payload_name || !map->ClockRate) return GF_REMOTE_SERVICE_ERROR; } } //Encryption: nothing tells wether the scope of the global key is eclusive or not. //we accept a global key + keys per media entry, assuming that the media key primes //on the global key return GF_OK; }