Пример #1
0
static ngx_int_t
ngx_http_vod_hls_parse_uri_file_name(
	ngx_http_request_t *r,
	ngx_http_vod_loc_conf_t *conf,
	u_char* start_pos,
	u_char* end_pos,
	request_params_t* request_params,
	const ngx_http_vod_request_t** request)
{
	uint32_t flags;
	ngx_int_t rc;

	// ts segment
	if (ngx_http_vod_match_prefix_postfix(start_pos, end_pos, &conf->hls.m3u8_config.segment_file_name_prefix, ts_file_ext))
	{
		start_pos += conf->hls.m3u8_config.segment_file_name_prefix.len;
		end_pos -= (sizeof(ts_file_ext) - 1);
		*request = &hls_ts_segment_request;
		flags = PARSE_FILE_NAME_EXPECT_SEGMENT_INDEX;
	}
	// vtt segment
	else if (ngx_http_vod_match_prefix_postfix(start_pos, end_pos, &conf->hls.m3u8_config.segment_file_name_prefix, vtt_file_ext))
	{
		start_pos += conf->hls.m3u8_config.segment_file_name_prefix.len;
		end_pos -= (sizeof(vtt_file_ext) - 1);
		*request = &hls_vtt_segment_request;
		flags = PARSE_FILE_NAME_EXPECT_SEGMENT_INDEX;
	}
	// manifest
	else if (ngx_http_vod_ends_with_static(start_pos, end_pos, m3u8_file_ext))
	{
		end_pos -= (sizeof(m3u8_file_ext) - 1);

		// make sure the file name begins with 'index' or 'iframes'
		if (ngx_http_vod_starts_with(start_pos, end_pos, &conf->hls.m3u8_config.index_file_name_prefix))
		{
			*request = &hls_index_request;
			start_pos += conf->hls.m3u8_config.index_file_name_prefix.len;
			flags = 0;
		}
		else if (ngx_http_vod_starts_with(start_pos, end_pos, &conf->hls.iframes_file_name_prefix))
		{
			*request = &hls_iframes_request;
			start_pos += conf->hls.iframes_file_name_prefix.len;
			flags = 0;
		}
		else if (ngx_http_vod_starts_with(start_pos, end_pos, &conf->hls.master_file_name_prefix))
		{
			*request = &hls_master_request;
			start_pos += conf->hls.master_file_name_prefix.len;
			flags = PARSE_FILE_NAME_MULTI_STREAMS_PER_TYPE;
		}
		else
		{
			ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
				"ngx_http_vod_hls_parse_uri_file_name: unidentified m3u8 request");
			return NGX_HTTP_BAD_REQUEST;
		}
	}
	// encryption key
	else if (ngx_http_vod_match_prefix_postfix(start_pos, end_pos, &conf->hls.m3u8_config.encryption_key_file_name, key_file_ext) &&
		!conf->drm_enabled)
	{
		start_pos += conf->hls.m3u8_config.encryption_key_file_name.len;
		end_pos -= (sizeof(key_file_ext) - 1);
		*request = &hls_enc_key_request;
		flags = 0;
	}
	else
	{
		ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
			"ngx_http_vod_hls_parse_uri_file_name: unidentified request");
		return NGX_HTTP_BAD_REQUEST;
	}

	// parse the required tracks string
	rc = ngx_http_vod_parse_uri_file_name(r, start_pos, end_pos, flags, request_params);
	if (rc != NGX_OK)
	{
		ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
			"ngx_http_vod_hls_parse_uri_file_name: ngx_http_vod_parse_uri_file_name failed %i", rc);
		return rc;
	}

	return NGX_OK;
}
ngx_int_t
ngx_http_vod_mss_parse_uri_file_name(
	ngx_http_request_t *r,
	ngx_http_vod_loc_conf_t *conf,
	u_char* start_pos,
	u_char* end_pos,
	ngx_http_vod_request_params_t* request_params)
{
	fragment_params_t fragment_params;
	ngx_int_t rc;

	// fragment
	if (end_pos[-1] == ')')
	{
		if (!ngx_http_vod_parse_string(fragment_match_definition, start_pos, end_pos, &fragment_params))
		{
			ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
				"ngx_http_vod_mss_parse_uri_file_name: ngx_http_vod_parse_string failed");
			return NGX_HTTP_BAD_REQUEST;
		}

		if (fragment_params.media_type.len != sizeof(MSS_STREAM_TYPE_VIDEO) - 1)
		{
			ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
				"ngx_http_vod_mss_parse_uri_file_name: invalid media type length %uz", fragment_params.media_type.len);
			return NGX_HTTP_BAD_REQUEST;
		}

		request_params->required_files = (1 << MSS_FILE_INDEX(fragment_params.bitrate));

		if (ngx_memcmp(fragment_params.media_type.data, MSS_STREAM_TYPE_VIDEO, sizeof(MSS_STREAM_TYPE_VIDEO) - 1) == 0)
		{
			request_params->required_tracks[MEDIA_TYPE_VIDEO] = (1 << MSS_TRACK_INDEX(fragment_params.bitrate));
		}
		else if (ngx_memcmp(fragment_params.media_type.data, MSS_STREAM_TYPE_AUDIO, sizeof(MSS_STREAM_TYPE_AUDIO) - 1) == 0)
		{
			request_params->required_tracks[MEDIA_TYPE_AUDIO] = (1 << MSS_TRACK_INDEX(fragment_params.bitrate));
		}
		else
		{
			ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
				"ngx_http_vod_mss_parse_uri_file_name: invalid media type %V", &fragment_params.media_type);
			return NGX_HTTP_BAD_REQUEST;
		}

		request_params->segment_index = segmenter_get_segment_index(&conf->segmenter, fragment_params.time / 10000);

		request_params->request = conf->drm_enabled ? &mss_playready_fragment_request : &mss_fragment_request;

		return NGX_OK;
	}

	// manifest
	if (!ngx_http_vod_starts_with(start_pos, end_pos, &conf->mss.manifest_file_name_prefix))
	{
		ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
			"ngx_http_vod_mss_parse_uri_file_name: unidentified request");
		return NGX_HTTP_BAD_REQUEST;
	}

	request_params->request = &mss_manifest_request;
	start_pos += conf->mss.manifest_file_name_prefix.len;

	rc = ngx_http_vod_parse_uri_file_name(r, start_pos, end_pos, FALSE, request_params);
	if (rc != NGX_OK)
	{
		ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
			"ngx_http_vod_mss_parse_uri_file_name: ngx_http_vod_parse_uri_file_name failed %i", rc);
		return rc;
	}

	return NGX_OK;
}
Пример #3
0
static ngx_int_t
ngx_http_vod_hls_parse_uri_file_name(
	ngx_http_request_t *r,
	ngx_http_vod_loc_conf_t *conf,
	u_char* start_pos,
	u_char* end_pos,
	request_params_t* request_params,
	const ngx_http_vod_request_t** request)
{
	bool_t expect_segment_index;
	ngx_int_t rc;

	// segment
	if (ngx_http_vod_match_prefix_postfix(start_pos, end_pos, &conf->hls.m3u8_config.segment_file_name_prefix, ts_file_ext))
	{
		start_pos += conf->hls.m3u8_config.segment_file_name_prefix.len;
		end_pos -= (sizeof(ts_file_ext) - 1);
		*request = &hls_segment_request;
		expect_segment_index = TRUE;
	}
	// manifest
	else if (ngx_http_vod_ends_with_static(start_pos, end_pos, m3u8_file_ext))
	{
		end_pos -= (sizeof(m3u8_file_ext) - 1);

		// make sure the file name begins with 'index' or 'iframes'
		if (ngx_http_vod_starts_with(start_pos, end_pos, &conf->hls.m3u8_config.index_file_name_prefix))
		{
			*request = &hls_index_request;
			start_pos += conf->hls.m3u8_config.index_file_name_prefix.len;
		}
		else if (ngx_http_vod_starts_with(start_pos, end_pos, &conf->hls.iframes_file_name_prefix))
		{
			*request = &hls_iframes_request;
			start_pos += conf->hls.iframes_file_name_prefix.len;
		}
		else if (ngx_http_vod_starts_with(start_pos, end_pos, &conf->hls.master_file_name_prefix))
		{
			*request = &hls_master_request;
			start_pos += conf->hls.master_file_name_prefix.len;
		}
		else
		{
			ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
				"ngx_http_vod_hls_parse_uri_file_name: unidentified m3u8 request");
			return NGX_HTTP_BAD_REQUEST;
		}

		expect_segment_index = FALSE;
	}
	// encryption key
	else if (ngx_http_vod_match_prefix_postfix(start_pos, end_pos, &conf->hls.m3u8_config.encryption_key_file_name, key_file_ext))
	{
		start_pos += conf->hls.m3u8_config.encryption_key_file_name.len;
		end_pos -= (sizeof(key_file_ext) - 1);
		*request = &hls_enc_key_request;
		expect_segment_index = FALSE;
	}
	else
	{
		ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
			"ngx_http_vod_hls_parse_uri_file_name: unidentified request");
		return NGX_HTTP_BAD_REQUEST;
	}

	// parse the required tracks string
	rc = ngx_http_vod_parse_uri_file_name(r, start_pos, end_pos, expect_segment_index, request_params);
	if (rc != NGX_OK)
	{
		ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
			"ngx_http_vod_hls_parse_uri_file_name: ngx_http_vod_parse_uri_file_name failed %i", rc);
		return rc;
	}

	return NGX_OK;
}
Пример #4
0
static ngx_int_t
ngx_http_vod_hds_parse_uri_file_name(
	ngx_http_request_t *r,
	ngx_http_vod_loc_conf_t *conf,
	u_char* start_pos,
	u_char* end_pos,
	request_params_t* request_params,
	const ngx_http_vod_request_t** request)
{
	ngx_int_t rc;

	// fragment request
	if (ngx_http_vod_starts_with(start_pos, end_pos, &conf->hds.manifest_config.fragment_file_name_prefix))
	{
		// sample fragment file name: frag-f3-v1-a1-Seg1-Frag1
		start_pos += conf->hds.manifest_config.fragment_file_name_prefix.len;

		// parse the fragment index
		end_pos = ngx_http_vod_extract_uint32_token_reverse(start_pos, end_pos, &request_params->segment_index);
		if (request_params->segment_index == 0)
		{
			ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
				"ngx_http_vod_hds_parse_uri_file_name: failed to parse fragment index");
			return NGX_HTTP_BAD_REQUEST;
		}

		request_params->segment_index--;		// convert to 0-based

		// extract the '-Seg1-Frag' part
		end_pos -= sizeof("-Seg1-Frag") - 1;
		if (end_pos < start_pos ||
			ngx_memcmp(end_pos, "-Seg1-Frag", sizeof("-Seg1-Frag") - 1) != 0)
		{
			ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
				"ngx_http_vod_hds_parse_uri_file_name: invalid segment / fragment requested");
			return NGX_HTTP_BAD_REQUEST;
		}

		*request = &hds_fragment_request;
	}
	// manifest request
	else if (ngx_http_vod_match_prefix_postfix(start_pos, end_pos, &conf->hds.manifest_file_name_prefix, manifest_file_ext))
	{
		start_pos += conf->hds.manifest_file_name_prefix.len;
		end_pos -= (sizeof(manifest_file_ext) - 1);
		*request = &hds_manifest_request;
	}
	else
	{
		ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
			"ngx_http_vod_hds_parse_uri_file_name: unidentified request");
		return NGX_HTTP_BAD_REQUEST;
	}

	// parse the required tracks string
	rc = ngx_http_vod_parse_uri_file_name(r, start_pos, end_pos, FALSE, request_params);
	if (rc != NGX_OK)
	{
		ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
			"ngx_http_vod_hds_parse_uri_file_name: ngx_http_vod_parse_uri_file_name failed %i", rc);
		return rc;
	}

	return NGX_OK;
}
ngx_int_t
ngx_http_vod_mss_parse_uri_file_name(
	ngx_http_request_t *r,
	ngx_http_vod_loc_conf_t *conf,
	u_char* start_pos,
	u_char* end_pos,
	request_params_t* request_params,
	const ngx_http_vod_request_t** request)
{
	fragment_params_t fragment_params;
	ngx_int_t rc;

	// fragment
	if (end_pos[-1] == ')')
	{
		if (!ngx_http_vod_parse_string(fragment_match_definition, start_pos, end_pos, &fragment_params))
		{
			ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
				"ngx_http_vod_mss_parse_uri_file_name: ngx_http_vod_parse_string failed");
			return NGX_HTTP_BAD_REQUEST;
		}

		if (fragment_params.media_type.len != sizeof(MSS_STREAM_TYPE_VIDEO) - 1)
		{
			ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
				"ngx_http_vod_mss_parse_uri_file_name: invalid media type length %uz", fragment_params.media_type.len);
			return NGX_HTTP_BAD_REQUEST;
		}

		request_params->sequences_mask = (1 << mss_sequence_index(fragment_params.bitrate));

		if (ngx_memcmp(fragment_params.media_type.data, MSS_STREAM_TYPE_VIDEO, sizeof(MSS_STREAM_TYPE_VIDEO) - 1) == 0)
		{
			request_params->tracks_mask[MEDIA_TYPE_VIDEO] = (1 << mss_track_index(fragment_params.bitrate));
		}
		else if (ngx_memcmp(fragment_params.media_type.data, MSS_STREAM_TYPE_AUDIO, sizeof(MSS_STREAM_TYPE_AUDIO) - 1) == 0)
		{
			request_params->tracks_mask[MEDIA_TYPE_AUDIO] = (1 << mss_track_index(fragment_params.bitrate));
		}
		else
		{
			ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
				"ngx_http_vod_mss_parse_uri_file_name: invalid media type %V", &fragment_params.media_type);
			return NGX_HTTP_BAD_REQUEST;
		}

		request_params->segment_time = fragment_params.time / 10000;

		// Note: assuming no discontinuity, if this changes the segment index will be recalculated
		request_params->segment_index = segmenter_get_segment_index_no_discontinuity(
			&conf->segmenter, 
			request_params->segment_time);

		*request = conf->drm_enabled ? &mss_playready_fragment_request : &mss_fragment_request;

		return NGX_OK;
	}
	// manifest
	else if (ngx_http_vod_starts_with(start_pos, end_pos, &conf->mss.manifest_file_name_prefix))
	{
		*request = &mss_manifest_request;
		start_pos += conf->mss.manifest_file_name_prefix.len;

		rc = ngx_http_vod_parse_uri_file_name(r, start_pos, end_pos, FALSE, request_params);
		if (rc != NGX_OK)
		{
			ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
				"ngx_http_vod_mss_parse_uri_file_name: ngx_http_vod_parse_uri_file_name failed %i", rc);
			return rc;
		}

		return NGX_OK;
	}
	// fragment with non-standard format (used with redirect)
	else if (ngx_http_vod_match_prefix_postfix(start_pos, end_pos, &conf->hls.m3u8_config.segment_file_name_prefix, m4s_file_ext))
	{
		start_pos += conf->hls.m3u8_config.segment_file_name_prefix.len;
		end_pos -= (sizeof(m4s_file_ext) - 1);
		*request = conf->drm_enabled ? &mss_playready_fragment_request : &mss_fragment_request;

		return ngx_http_vod_parse_uri_file_name(r, start_pos, end_pos, TRUE, request_params);
	}
	else
	{
		ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
			"ngx_http_vod_mss_parse_uri_file_name: unidentified request");
		return NGX_HTTP_BAD_REQUEST;
	}
}