/*
 * OpenMRCP - Open Source Media Resource Control Protocol Stack
 * Copyright (C) 2007, Cepstral LLC
 *
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Author(s):
 * Arsen Chaloyan <achaloyan@yahoo.com>
 *
 * Contributor(s):
 *
 */

#ifndef __RTSP_HEADER_H__
#define __RTSP_HEADER_H__

/**
 * @file rtsp_header.h
 * @brief RTSP Header
 */ 

#include <apr_network_io.h>
#include <apr_strings.h>
#include <apr_pools.h>
#include "apt.h"
#include "apt_text_stream.h"

APT_BEGIN_EXTERN_C

/** RTSP transport and profile type */
typedef enum{
	RTSP_PROFILE_RTP_AVP,
	RTSP_PROFILE_RTP_SAVP,

	RTSP_PROFILE_COUNT,
	RTSP_PROFILE_NONE = RTSP_PROFILE_COUNT
} rtsp_transport_profile_t;

/** RTSP lower-transport */
typedef enum{
	RTSP_LOWER_TRANSPORT_UDP,
	RTSP_LOWER_TRANSPORT_TCP,

	RTSP_LOWER_TRANSPORT_COUNT,
	RTSP_LOWER_TRANSPORT_NONE = RTSP_LOWER_TRANSPORT_COUNT
} rtsp_lower_transport_t;

/** RTSP delivery */
typedef enum{
	RTSP_DELIVERY_UNICAST,
	RTSP_DELIVERY_MULTICAST,

	RTSP_DELIVERY_COUNT,
	RTSP_DELIVERY_NONE = RTSP_DELIVERY_COUNT
} rtsp_delivery_t;

typedef struct rtsp_port_range_t rtsp_port_range_t;
/** RTSP (RTP) port range */
struct rtsp_port_range_t {
	apr_port_t min;
	apr_port_t max;
};

static APR_INLINE void rtsp_port_range_init(rtsp_port_range_t *port_range)
{
	port_range->min = port_range->max = 0;
}

typedef struct rtsp_transport_t rtsp_transport_t;
/** RTSP transport */
struct rtsp_transport_t {
	rtsp_transport_profile_t profile;
	rtsp_lower_transport_t   lower_transport;
	rtsp_delivery_t          delivery;
	rtsp_port_range_t        client_port_range;
	rtsp_port_range_t        server_port_range;
};

static APR_INLINE void rtsp_transport_init(rtsp_transport_t *transport)
{
	transport->profile = RTSP_PROFILE_NONE;
	transport->lower_transport = RTSP_LOWER_TRANSPORT_NONE;
	rtsp_port_range_init(&transport->client_port_range);
	rtsp_port_range_init(&transport->server_port_range);
}

/** RTSP header fields */
typedef enum{
	RTSP_HEADER_FIELD_CSEQ,
	RTSP_HEADER_FIELD_TRANSPORT,
	RTSP_HEADER_FIELD_SESSION_ID,
	RTSP_HEADER_FIELD_RTP_INFO,
	RTSP_HEADER_FIELD_CONTENT_TYPE,
	RTSP_HEADER_FIELD_CONTENT_LENGTH,

	RTSP_HEADER_FIELD_COUNT,
	RTSP_HEADER_FIELD_UNKNOWN = RTSP_HEADER_FIELD_COUNT
} rtsp_header_field_id;

/** RTSP content types */
typedef enum {
	RTSP_CONTENT_TYPE_SDP,
	RTSP_CONTENT_TYPE_MRCP,

	RTSP_CONTENT_TYPE_COUNT,
	RTSP_CONTENT_TYPE_NONE = RTSP_CONTENT_TYPE_COUNT
} rtsp_content_type;


/** Bit field masks are used to define property set */
typedef int rtsp_header_property_set_t;


typedef struct rtsp_header_t rtsp_header_t;
/** RTSP header */
struct rtsp_header_t {
	/** sequence number */
	size_t            cseq; 
	/** transport */
	rtsp_transport_t  transport; 
	/** session identifier */
	const char       *session_id;
	/** rtp-info */
	const char       *rtp_info;

	/** content type */
	rtsp_content_type content_type;
	/** content length */
	size_t            content_length;

	/* set of properties of entire header contains */
	rtsp_header_property_set_t property_set;
};


/** Initialize header */
static APR_INLINE void rtsp_header_init(rtsp_header_t *header)
{
	header->cseq = 0;
	rtsp_transport_init(&header->transport);
	header->session_id = NULL;
	header->rtp_info = NULL;
	header->content_type = RTSP_CONTENT_TYPE_NONE;
	header->content_length = 0;

	header->property_set = 0;
}

/** Parse RTSP message */
apt_bool_t rtsp_header_parse(rtsp_header_t *header, apt_text_stream_t *text_stream, apr_pool_t *pool);
/** Generate RTSP message */
apt_bool_t rtsp_header_generate(rtsp_header_t *header, apt_text_stream_t *text_stream);



/** Add property to property set */
static APR_INLINE void rtsp_header_property_add(rtsp_header_property_set_t *property_set, size_t id)
{
	int mask = 1 << id;
	*property_set |= mask;
}

/** Remove property from property set */
static APR_INLINE void rtsp_header_property_remove(rtsp_header_property_set_t *property_set, size_t id)
{
	int mask = 1 << id;
	*property_set &= ~mask;
}

/** Check the property in property set */
static APR_INLINE apt_bool_t rtsp_header_property_check(rtsp_header_property_set_t *property_set, size_t id)
{
	int mask = 1 << id;
	return ((*property_set & mask) == mask) ? TRUE : FALSE;
}


APT_END_EXTERN_C

#endif /*__RTSP_HEADER_H__*/
