/***************************************************************************************
 *
 *  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
 *
 *  By downloading, copying, installing or using the software you agree to this license.
 *  If you do not agree to this license, do not download, install, 
 *  copy or use the software.
 *
 *  Copyright (C) 2014-2024, Happytimesoft Corporation, all rights reserved.
 *
 *  Redistribution and use in binary forms, with or without modification, are permitted.
 *
 *  Unless required by applicable law or agreed to in writing, software distributed 
 *  under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 *  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
 *  language governing permissions and limitations under the License.
 *
****************************************************************************************/

#include "sys_inc.h"
#include "word_analyse.h"
#include "rtsp_parse.h"
#include "http_cln.h"

/**************************************************************************/
const RREQMTV rtsp_req_mtvs[] =
{
	{RTSP_MT_DESCRIBE,		"DESCRIBE",		8},
	{RTSP_MT_ANNOUNCE,		"ANNOUNCE",		8},
	{RTSP_MT_OPTIONS,		"OPTIONS",		7},
	{RTSP_MT_PAUSE,			"PAUSE",		5},
	{RTSP_MT_PLAY,			"PLAY",			4},
	{RTSP_MT_RECORD,		"RECORD",		6},
	{RTSP_MT_REDIRECT,		"REDIRECT",		8},
	{RTSP_MT_SETUP,			"SETUP",		5},
	{RTSP_MT_SET_PARAMETER,	"SET_PARAMETER",13},
	{RTSP_MT_GET_PARAMETER,	"GET_PARAMETER",13},
	{RTSP_MT_TEARDOWN,		"TEARDOWN",		8}
};

/**************************************************************************/
BOOL rtsp_is_rtsp_msg(char * msg_buf)
{
	uint32 i;
	for (i=0; i < sizeof(rtsp_req_mtvs)/sizeof(RREQMTV); i++)
	{
		if (memcmp(msg_buf, rtsp_req_mtvs[i].msg_str, rtsp_req_mtvs[i].msg_len) == 0)
		{
			return TRUE;
		}
	}

	if (memcmp(msg_buf, "RTSP/1.0", strlen("RTSP/1.0")) == 0)
	{
		return TRUE;
	}
	
	return FALSE;
}

void rtsp_headl_parse(char * pline, int llen, HRTSP_MSG * p_msg)
{
	char word_buf[256];
	int  word_len;
	int  next_word_offset;
	BOOL bHaveNextWord;

	bHaveNextWord = GetLineWord(pline, 0, llen, word_buf, sizeof(word_buf), &next_word_offset, WORD_TYPE_STRING);
	word_len = (int)strlen(word_buf);
	if (word_len > 0 && word_len < 31)
	{
		memcpy(p_msg->first_line.header, pline, word_len);
		p_msg->first_line.header[word_len] = '\0';

		while (pline[next_word_offset] == ' ')
		{
			next_word_offset++;
		}
		
		p_msg->first_line.value_string = pline+next_word_offset;
		p_msg->first_line.value_string[llen-next_word_offset] = '\0';

		if (strcasecmp(word_buf, "RTSP/1.0") == 0)
		{
			if (bHaveNextWord)
			{
				word_len = sizeof(word_buf);
				bHaveNextWord = GetLineWord(pline, next_word_offset, llen, word_buf, sizeof(word_buf), &next_word_offset, WORD_TYPE_NUM);
				word_len = (int)strlen(word_buf);
				if (word_len > 0)
				{
					p_msg->msg_type = 1;
					p_msg->msg_sub_type = atoi(word_buf);
				}
			}
		}
		else
		{
			uint32 i;
			
			p_msg->msg_type = 0;
			
			for (i=0; i < sizeof(rtsp_req_mtvs)/sizeof(RREQMTV); i++)
			{
				if (strcasecmp(word_buf, (char *)(rtsp_req_mtvs[i].msg_str)) == 0)
				{
					p_msg->msg_sub_type = rtsp_req_mtvs[i].msg_type;
					break;
				}
			}
		}
	}
}

int rtsp_line_parse(char * p_buf, int max_len, char sep_char, PPSN_CTX * p_ctx)
{
	char word_buf[256];
	BOOL bHaveNextLine = TRUE;
	int line_len = 0;
	int parse_len = 0;

	char * ptr = p_buf;

	do {
		if (GetSipLine(ptr, max_len, &line_len, &bHaveNextLine) == FALSE)
		{
			return -1;
		}

		if (line_len <= 2)
		{
			return(parse_len + line_len);
		}

		int	next_word_offset = 0;
		GetLineWord(ptr, 0, line_len-2, word_buf, sizeof(word_buf), &next_word_offset, WORD_TYPE_STRING);
		
		char nchar = *(ptr + next_word_offset);
		if (nchar != sep_char) // SIP is ':',SDP is '='
		{
			return -1;
		}

		next_word_offset++;
		while (ptr[next_word_offset] == ' ')
		{
			next_word_offset++;
		}
		
		HDRV * pHdrV = hdrv_buf_get_idle();
		if (pHdrV == NULL)
		{
			log_print(HT_LOG_ERR, "%s, hdrv_buf_get_idle return NULL!!!\r\n", __FUNCTION__);
			return -1;
		}

		strncpy(pHdrV->header, word_buf, 31);
		pHdrV->value_string = ptr+next_word_offset;
		pps_ctx_ul_add(p_ctx, pHdrV);

		ptr += line_len;
		max_len -= line_len;
		parse_len += line_len;

        while (*ptr == '\r' || *ptr == '\n')
        {
            ptr++;
            parse_len++;
        }
	} while (bHaveNextLine);

	return parse_len;
}

int rtsp_ctx_parse(HRTSP_MSG * p_msg)
{
	int flag = 0;
	RTSPCTXT w_ctx_type;

	HDRV * pHdrV = (HDRV *)pps_lookup_start(&(p_msg->rtsp_ctx));
	while (pHdrV != NULL)
	{
		if (strcasecmp(pHdrV->header, "Content-Length") == 0)
		{
			p_msg->ctx_len = atol(pHdrV->value_string);
			flag++;
		}
		else if (strcasecmp(pHdrV->header, "Content-Type") == 0)
		{
			char type_word[64];
			int  next_tmp;
			GetLineWord(pHdrV->value_string, 0, (int)strlen(pHdrV->value_string), type_word, sizeof(type_word), &next_tmp, WORD_TYPE_STRING);

			if (strcasecmp(type_word, "application/sdp") == 0)
			{
				w_ctx_type = RTSP_CTX_SDP;
			}	
			else
			{
				w_ctx_type = RTSP_CTX_NULL;
			}
			
			p_msg->ctx_type = w_ctx_type;
			flag++;
		}
		
		pHdrV = (HDRV *)pps_lookup_next(&(p_msg->rtsp_ctx), pHdrV);
	}
	pps_lookup_end(&(p_msg->rtsp_ctx));

	if (p_msg->ctx_type && p_msg->ctx_len)
	{
		return 1;
	}
	
	return 0;
}

int rtsp_msg_parse(char * msg_buf, int msg_buf_len, HRTSP_MSG * msg)
{
    int line_len = 0;
	BOOL bHaveNextLine;	
	char * p_buf = msg_buf;

	msg->msg_type = (uint32) -1;	

	if (GetSipLine(p_buf, msg_buf_len, &line_len, &bHaveNextLine) == FALSE)
	{
		return -1;
	}
	
	if (line_len > 0)
	{
		rtsp_headl_parse(p_buf, line_len-2, msg);
	}
	
	if (msg->msg_type == (uint32) -1)	
	{
		return -1;
	}
	
	p_buf += line_len;
	msg->rtsp_len = rtsp_line_parse(p_buf, msg_buf_len-line_len, ':', &(msg->rtsp_ctx));
	if (msg->rtsp_len <= 0)
	{
		return -1;
	}
	
	p_buf += msg->rtsp_len;
	
	if (rtsp_ctx_parse(msg) == 1 && msg->ctx_len > 0)
	{
		msg->sdp_len = rtsp_line_parse(p_buf, msg->ctx_len, '=', &(msg->sdp_ctx));
		if (msg->sdp_len < 0)
		{
			return -1;
		}	
	}

	return (line_len + msg->rtsp_len + msg->sdp_len);
}

int rtsp_msg_parse_part1(char * p_buf, int buf_len, HRTSP_MSG * msg)
{
    int line_len = 0;
	BOOL bHaveNextLine;	

	msg->msg_type = (uint32) -1;	

	if (GetSipLine(p_buf, buf_len, &line_len, &bHaveNextLine) == FALSE)
	{
		return -1;
	}
	
	if (line_len > 0)
	{
		rtsp_headl_parse(p_buf, line_len-2, msg);
	}
	
	if (msg->msg_type == (uint32) -1)
	{
		return -1;
	}
	
	p_buf += line_len;
	msg->rtsp_len = rtsp_line_parse(p_buf, buf_len-line_len, ':', &(msg->rtsp_ctx));
	if (msg->rtsp_len <= 0)
	{
		return -1;
	}
	
	rtsp_ctx_parse(msg);

	return (line_len + msg->rtsp_len);
}

int rtsp_msg_parse_part2(char * p_buf, int buf_len, HRTSP_MSG * msg)
{
	msg->sdp_len = rtsp_line_parse(p_buf, buf_len, '=', &(msg->sdp_ctx));
	if (msg->sdp_len < 0)
	{
	    msg->sdp_len = rtsp_line_parse(p_buf, buf_len, ':', &(msg->sdp_ctx));
	    if (msg->sdp_len < 0)
	    {
		    return -1;
		}
	}
	
	return msg->sdp_len;
}

HDRV * rtsp_find_headline(HRTSP_MSG * msg, const char * head)
{
	if (msg == NULL || head == NULL)
	{
		return NULL;
	}
	
	HDRV * line = (HDRV *)pps_lookup_start(&(msg->rtsp_ctx));
	while (line != NULL)
	{
		if (strcasecmp(line->header, head) == 0)
		{
			return line;
		}
		
		line = (HDRV *)pps_lookup_next(&(msg->rtsp_ctx), line);
	}
	pps_lookup_end(&(msg->rtsp_ctx));

	return NULL;
}

HDRV * rtsp_find_headline_next(HRTSP_MSG * msg, const char * head, HDRV * hrv)
{
    HDRV * line;
    
	if (msg == NULL || head == NULL)
	{
		return NULL;
	}
	
	line = (HDRV *)pps_lookup_start(&(msg->rtsp_ctx));
	while (line != NULL)
	{
		if (line == hrv)
		{
			line = (HDRV *)pps_lookup_next(&(msg->rtsp_ctx), line);
			break;
		}

		line = (HDRV *)pps_lookup_next(&(msg->rtsp_ctx), line);
	}
	
	while (line != NULL)
	{		
		if (strcasecmp(line->header, head) == 0)
		{
			pps_lookup_end(&(msg->rtsp_ctx));
			return line;
		}

		line = (HDRV *)pps_lookup_next(&(msg->rtsp_ctx), line);
	}
	pps_lookup_end(&(msg->rtsp_ctx));

	return NULL;
}

BOOL rtsp_get_headline_string(HRTSP_MSG * rx_msg, const char * head, char * p_value, int size)
{
	HDRV * rx_head = rtsp_find_headline(rx_msg, head);
	if (rx_head == NULL || p_value == NULL)
	{
		return FALSE;
	}
	
	if (rx_head->value_string == NULL)
	{
		return FALSE;
	}
	
	p_value[0] = '\0';

	int len = (int)strlen(rx_head->value_string);
	if (len >= size)
	{
		log_print(HT_LOG_ERR, "%s, %s, value_string(%s) len(%d) > size(%d)\r\n", 
		    __FUNCTION__, head, rx_head->value_string, len, size);
		return FALSE;
	}

	strcpy(p_value, rx_head->value_string);
	
	return TRUE;
}

BOOL rtsp_get_headline_uri(HRTSP_MSG * rx_msg, char * p_uri, int size)
{
	char * p_ptr = rx_msg->first_line.value_string;
	if (p_ptr == NULL)
	{
		return FALSE;
	}
	
	char * p_end = p_ptr;
	while (*p_end != ' ')
	{
		p_end++;
	}
	
	int len = (int)(p_end - p_ptr);
	if (len >= size)
	{
		return FALSE;
	}
	
	memcpy(p_uri, p_ptr, len);
	p_uri[len] = '\0';
	
	return TRUE;
}

HDRV * rtsp_find_sdp_headline(HRTSP_MSG * msg, const char * head)
{
	if (msg == NULL || head == NULL)
	{
		return NULL;
	}
	
	HDRV * line = (HDRV *)pps_lookup_start(&(msg->sdp_ctx));
	while (line != NULL)
	{
		if (strcasecmp(line->header, head) == 0)
		{
			return line;
		}
		
		line = (HDRV *)pps_lookup_next(&(msg->sdp_ctx), line);
	}
	pps_lookup_end(&(msg->sdp_ctx));

	return NULL;
}

BOOL rtsp_msg_with_sdp(HRTSP_MSG * msg)
{
	if (msg == NULL)
	{
		return FALSE;
	}
	
	if (msg->sdp_ctx.node_num == 0)
	{
		return FALSE;
	}
	
	return TRUE;
}

BOOL rtsp_get_msg_session(HRTSP_MSG * rx_msg, char *session_buf, int len)
{
	session_buf[0] = '\0';

	HDRV * rx_id = rtsp_find_headline(rx_msg, "Session");
	if (rx_id == NULL || len <= 0)
	{
		return FALSE;
	}
	
	int	next_word_offset;

	GetLineWord(rx_id->value_string, 0, (int)strlen(rx_id->value_string), session_buf, len, &next_word_offset, WORD_TYPE_STRING);

	return TRUE;
}

BOOL rtsp_match_msg_session(HRTSP_MSG * rx_msg, HRTSP_MSG * tx_msg)
{
	HDRV * rx_id = rtsp_find_headline(rx_msg, "Session");
	HDRV * tx_id = rtsp_find_headline(tx_msg, "Session");

	if (rx_id == NULL || tx_id == NULL)
	{
		return FALSE;
	}
	
	char rx_word_buf[256];
	char tx_word_buf[256];
	int	 next_word_offset;

	GetLineWord(rx_id->value_string, 0, (int)strlen(rx_id->value_string),
		rx_word_buf, sizeof(rx_word_buf), &next_word_offset, WORD_TYPE_STRING);
	GetLineWord(tx_id->value_string, 0, (int)strlen(tx_id->value_string),
		tx_word_buf, sizeof(tx_word_buf), &next_word_offset, WORD_TYPE_STRING);

	if (strcmp(rx_word_buf, tx_word_buf) != 0)
	{
		return FALSE;
	}
	
	return TRUE;
}

BOOL rtsp_match_msg_cseq(HRTSP_MSG * rx_msg, HRTSP_MSG * tx_msg)
{
	HDRV * rx_cseq = rtsp_find_headline(rx_msg, "CSeq");
	HDRV * tx_cseq = rtsp_find_headline(tx_msg, "CSeq");

	if (rx_cseq == NULL || tx_cseq == NULL)
	{
		return FALSE;
	}
	
	char rx_word_buf[256];
	char tx_word_buf[256];
	int	 next_offset;

	GetLineWord(rx_cseq->value_string, 0, (int)strlen(rx_cseq->value_string),
		rx_word_buf, sizeof(rx_word_buf), &next_offset, WORD_TYPE_NUM);
	GetLineWord(tx_cseq->value_string, 0, (int)strlen(tx_cseq->value_string),
		tx_word_buf, sizeof(tx_word_buf), &next_offset, WORD_TYPE_NUM);

	if (strcmp(rx_word_buf, tx_word_buf) != 0)
	{
		return FALSE;
	}
	
	GetLineWord(rx_cseq->value_string, next_offset, (int)strlen(rx_cseq->value_string),
		rx_word_buf, sizeof(rx_word_buf), &next_offset, WORD_TYPE_STRING);
	GetLineWord(tx_cseq->value_string, next_offset, (int)strlen(tx_cseq->value_string),
		tx_word_buf, sizeof(tx_word_buf), &next_offset, WORD_TYPE_STRING);

	if (strcasecmp(rx_word_buf, tx_word_buf) != 0)
	{
		return FALSE;
	}
	
	return TRUE;
}

BOOL rtsp_get_msg_cseq(HRTSP_MSG * rx_msg, char *cseq_buf, int len)
{
	HDRV * rx_cseq = rtsp_find_headline(rx_msg, "CSeq");
	if ((rx_cseq == NULL) || len <= 0)
	{
		return FALSE;
	}
	
	int	next_offset;

	GetLineWord(rx_cseq->value_string, 0, (int)strlen(rx_cseq->value_string), cseq_buf, len, &next_offset, WORD_TYPE_NUM);

	return TRUE;
}

BOOL rtsp_get_user_agent_info(HRTSP_MSG * rx_msg, char * agent_buf, int max_len)
{
	if (agent_buf == NULL || max_len <= 0)
	{
		return FALSE;
	}
	
	agent_buf[0] = '\0';

	HDRV * rx_line = rtsp_find_headline(rx_msg, "User-Agent");
	if (rx_line == NULL)
	{
		return FALSE;
	}
	
	strncpy(agent_buf, rx_line->value_string, max_len);
	
	return TRUE;
}

BOOL rtsp_get_session_info(HRTSP_MSG * rx_msg, char * session_buf, int max_len, int * timeout)
{
	if (session_buf == NULL || max_len <= 0)
	{
		return FALSE;
	}

	HDRV * rx_line = rtsp_find_headline(rx_msg, "Session");
	if (rx_line == NULL)
	{
		return FALSE;
	}
	
	session_buf[0] = '\0';
	
	if (rx_line->value_string)
	{		
		char * p = strchr(rx_line->value_string, ';');
		if (!p)
		{
			strncpy(session_buf, rx_line->value_string, max_len);
		}
		else
		{
			*p = '\0';
			strncpy(session_buf, rx_line->value_string, max_len);
			*p = ';';
		}

		if (timeout)
		{
			char value_string[256] = {'\0'};
			strncpy(value_string, rx_line->value_string, sizeof(value_string)-1);
			lowercase(value_string);
			
			p = strstr(value_string, "timeout=");
			if (p)
			{
				p += strlen("timeout=");
				*timeout = atoi(p);

				if (*timeout <= 0)
				{
					*timeout = 60;
				}
				else if (*timeout < 10)
				{
				    *timeout = 10;
				}
			}
		}
	}	
	
	return TRUE;
}

BOOL rtsp_get_rtp_info(HRTSP_MSG * rx_msg, char * v_ctl, uint32 * p_v_ts, char * a_ctl, uint32 * p_a_ts)
{
    HDRV * rx_line = rtsp_find_headline(rx_msg, "RTP-Info");
	if (rx_line == NULL)
	{
		return FALSE;
	}

	if (NULL == rx_line->value_string)
	{
	    return FALSE;
	}

    // set default value -1
    *p_v_ts = -1;
    *p_a_ts = -1;
    
	if (v_ctl && v_ctl[0] != '\0')
	{
	    int ctl_len;
	    char * p = strchr(v_ctl, '?');
	    if (p)
	    {
	        char ctl[128] = {'\0'};
	        strncpy(ctl, v_ctl, p-v_ctl);

	        p = strstr(rx_line->value_string, ctl);
	        ctl_len = strlen(ctl);
	    }
	    else
	    {
	        p = strstr(rx_line->value_string, v_ctl);
	        ctl_len = strlen(v_ctl);
	    }
	    
        if (p)
        {
            p += ctl_len;

            int i = 0, j = 0;
            char * p_buff = NULL;
            char * p_semicolon = strchr(p, ',');
            char * p_rtptime = strstr(p, "rtptime=");
            char rtptime[32] = {'\0'};

            if (p_rtptime)
            {
                if (p_semicolon)
                {
                    if (p_rtptime < p_semicolon)
                    {
                        p_buff = p_rtptime+strlen("rtptime=");
                    }
                }
                else
                {
                    p_buff = p_rtptime+strlen("rtptime=");
                }

                while (p_buff && p_buff[i] != '\0')
                {
                    if (p_buff[i] == ',' || p_buff[i] == ';')
                    {
                        break;
                    }
                    else if (j < 31)
                    {
                        rtptime[j++] = p_buff[i];
                    }

                    i++;
                }
                
                *p_v_ts = (uint32)strtoul(rtptime, NULL, 10);
            }
        }
    }

    if (a_ctl && a_ctl[0] != '\0')
	{
	    int ctl_len;
	    char * p = strchr(a_ctl, '?');
	    if (p)
	    {
	        char ctl[128] = {'\0'};
	        strncpy(ctl, a_ctl, p-a_ctl);

	        p = strstr(rx_line->value_string, ctl);
	        ctl_len = strlen(ctl);
	    }
	    else
	    {
	        p = strstr(rx_line->value_string, a_ctl);
	        ctl_len = strlen(a_ctl);
	    }

        if (p)
        {
            p += ctl_len;

            int i = 0, j = 0;
            char * p_buff = NULL;
            char * p_semicolon = strchr(p, ',');
            char * p_rtptime = strstr(p, "rtptime=");
            char rtptime[32] = {'\0'};

            if (p_rtptime)
            {
                if (p_semicolon)
                {
                    if (p_rtptime < p_semicolon)
                    {
                        p_buff = p_rtptime+strlen("rtptime=");
                    }
                }
                else
                {
                    p_buff = p_rtptime+strlen("rtptime=");
                }

                while (p_buff && p_buff[i] != '\0')
                {
                    if (p_buff[i] == ',' || p_buff[i] == ';')
                    {
                        break;
                    }
                    else if (j < 31)
                    {
                        rtptime[j++] = p_buff[i];
                    }

                    i++;
                }

                *p_a_ts = (uint32)strtoul(rtptime, NULL, 10);
            }
        }
    }
    
	return TRUE;
}

BOOL rtsp_get_tcp_transport_info(HRTSP_MSG * rx_msg, uint16 * interleaved)
{
    BOOL ret = FALSE;
    
    HDRV * rx_line = rtsp_find_headline(rx_msg, "Transport");
	if (rx_line == NULL)
	{
		return FALSE;
	}
	
	if (rx_line->value_string)
	{	
	    char buff[32] = {'\0'};
		if (GetNameValuePair(rx_line->value_string, (int)strlen(rx_line->value_string), "interleaved", buff, sizeof(buff)-1))
		{
		    if (interleaved)
		    {
		        *interleaved = atoi(buff);		        
            }

            ret = TRUE;
		}
	}
	
	return ret;
}

BOOL rtsp_get_udp_transport_info(HRTSP_MSG * rx_msg, uint16 * client_port, uint16 * server_port)
{
    BOOL ret = FALSE;
    
    HDRV * rx_line = rtsp_find_headline(rx_msg, "Transport");
	if (rx_line == NULL)
	{
		return FALSE;
	}
	
	if (rx_line->value_string)
	{	
	    char buff[32] = {'\0'};
		if (GetNameValuePair(rx_line->value_string, (int)strlen(rx_line->value_string), "client_port", buff, sizeof(buff)-1))
		{
		    if (client_port)
		    {
		        *client_port = atoi(buff);		        
		    }

		    ret = TRUE;
		}

		if (GetNameValuePair(rx_line->value_string, (int)strlen(rx_line->value_string), "server_port", buff, sizeof(buff)-1))
		{
		    if (server_port)
		    {
		        *server_port = atoi(buff);		        
		    }

		    ret = TRUE;
		}
	}
	
	return ret;
}

BOOL rtsp_get_mc_transport_info(HRTSP_MSG * rx_msg, char * destination, uint16 * port)
{
    BOOL ret = FALSE;
    
    HDRV * rx_line = rtsp_find_headline(rx_msg, "Transport");
	if (rx_line == NULL)
	{
		return FALSE;
	}
	
	if (rx_line->value_string)
	{	
	    char buff[32] = {'\0'};
		if (GetNameValuePair(rx_line->value_string, (int)strlen(rx_line->value_string), "destination", buff, sizeof(buff)-1))
		{
		    if (destination)
		    {
		        strcpy(destination, buff);
            }

            ret = TRUE;
		}

		if (GetNameValuePair(rx_line->value_string, (int)strlen(rx_line->value_string), "port", buff, sizeof(buff)-1))
		{
		    if (port)
		    {
		        *port = atoi(buff);		        
		    }

		    ret = TRUE;
		}
	}
	
	return ret;
}

BOOL rtsp_is_line_exist(HRTSP_MSG * rx_msg, const char * head, const char * value)
{
    char buf[256];
    char lovalue[256] = {'\0'};
    
    if (!rtsp_get_headline_string(rx_msg, head, buf, sizeof(buf)))
    {
        return FALSE;
    }

    strncpy(lovalue, value, sizeof(lovalue)-1);

    lowercase(buf);
    lowercase(lovalue);
    
    if (!strstr(buf, lovalue))
    {
        return FALSE;
    }

    return TRUE;
}

BOOL rtsp_get_cbase_info(HRTSP_MSG * rx_msg, char * cbase_buf, int max_len)
{
	if (cbase_buf == NULL || max_len <= 0)
	{
		return FALSE;
	}
	
	cbase_buf[0] = '\0';

	HDRV * rx_line = rtsp_find_headline(rx_msg, "Content-Base");
	if (rx_line == NULL)
	{
		return FALSE;
	}
	
	strncpy(cbase_buf, rx_line->value_string, max_len);
	
	return TRUE;
}

void rtsp_add_tx_msg_line(HRTSP_MSG * tx_msg, const char * msg_hdr, const char * msg_fmt, ...)
{
    int slen;
	va_list argptr;	

	if (tx_msg == NULL || tx_msg->msg_buf == NULL)
	{
		return;
	}
	
	HDRV *pHdrV = hdrv_buf_get_idle();
	if (pHdrV == NULL)
	{
		log_print(HT_LOG_ERR, "%s, hdrv_buf_get_idle return NULL!!!\r\n", __FUNCTION__);
		return;
	}

	pHdrV->value_string = tx_msg->msg_buf + tx_msg->buf_offset;

	strncpy(pHdrV->header, msg_hdr, 31);

	va_start(argptr, msg_fmt);

#if	__LINUX_OS__
	slen = vsnprintf(pHdrV->value_string, 1600-tx_msg->buf_offset, msg_fmt, argptr);
#else
	slen = vsprintf(pHdrV->value_string, msg_fmt, argptr);
#endif

	va_end(argptr);

	if (slen < 0)
	{
		log_print(HT_LOG_ERR, "%s, vsnprintf return %d !!!\r\n", __FUNCTION__, slen);
		hdrv_buf_free(pHdrV);
		return;
	}

	pHdrV->value_string[slen] = '\0';
	tx_msg->buf_offset += slen + 1;

	pps_ctx_ul_add(&(tx_msg->rtsp_ctx), pHdrV);
}

void rtsp_add_tx_msg_sdp_line(HRTSP_MSG * tx_msg, const char * msg_hdr, const char * msg_fmt, ...)
{
    int slen;
	va_list argptr;	

	if (tx_msg == NULL || tx_msg->msg_buf == NULL)
	{
		return;
	}
	
	HDRV *pHdrV = hdrv_buf_get_idle();
	if (pHdrV == NULL)
	{
		log_print(HT_LOG_ERR, "%s, hdrv_buf_get_idle return NULL!!!\r\n", __FUNCTION__);
		return;
	}

	pHdrV->value_string = tx_msg->msg_buf + tx_msg->buf_offset;

	strncpy(pHdrV->header, msg_hdr, 31);

	va_start(argptr, msg_fmt);

#if	__LINUX_OS__
	slen = vsnprintf(pHdrV->value_string, 1600-tx_msg->buf_offset, msg_fmt, argptr);
#else
	slen = vsprintf(pHdrV->value_string, msg_fmt, argptr);
#endif

	va_end(argptr);

	if (slen < 0)
	{
		log_print(HT_LOG_ERR, "%s, vsnprintf return %d !!!\r\n", __FUNCTION__, slen);
		hdrv_buf_free(pHdrV);
		return;
	}

	pHdrV->value_string[slen] = '\0';
	tx_msg->buf_offset += slen + 1;

	pps_ctx_ul_add(&(tx_msg->sdp_ctx), pHdrV);
}

void rtsp_add_tx_msg_fline(HRTSP_MSG * tx_msg, const char * msg_hdr, const char * msg_fmt, ...)
{
    int slen;
	va_list argptr;	

	if (tx_msg == NULL || tx_msg->msg_buf == NULL)
	{
		return;
	}
	
	strncpy(tx_msg->first_line.header, msg_hdr, sizeof(tx_msg->first_line.header)-1);
	tx_msg->first_line.value_string = tx_msg->msg_buf + tx_msg->buf_offset;

	va_start(argptr, msg_fmt);
#if	__LINUX_OS__
	slen = vsnprintf(tx_msg->first_line.value_string, 1600-tx_msg->buf_offset, msg_fmt, argptr);
#else
	slen = vsprintf(tx_msg->first_line.value_string, msg_fmt, argptr);
#endif
	va_end(argptr);

	if (slen < 0)
	{
		log_print(HT_LOG_ERR, "%s, vsnprintf return %d !!!\r\n", __FUNCTION__, slen);
		return;
	}

	tx_msg->first_line.value_string[slen] = '\0';
	
	tx_msg->buf_offset += slen + 1;
}

void rtsp_copy_msg_line(HRTSP_MSG * src_msg, HRTSP_MSG * dst_msg, char * msg_hdr)
{
	HDRV * src_line = rtsp_find_headline(src_msg, msg_hdr);
	if (src_line == NULL)
	{
	    return;
	}
	
	HDRV * dst_line = hdrv_buf_get_idle();
	if (dst_line == NULL)
	{
	    return;
	}
	
	strcpy(dst_line->header, src_line->header);

	dst_line->value_string = dst_msg->msg_buf + dst_msg->buf_offset;
	if (dst_line->value_string == NULL)
	{
		hdrv_buf_free(dst_line);
		return;
	}

	strcpy(dst_line->value_string, src_line->value_string);
	dst_msg->buf_offset += (int)strlen(src_line->value_string) + 1;

	pps_ctx_ul_add(&(dst_msg->rtsp_ctx), dst_line);
}

void rtsp_free_msg(HRTSP_MSG * msg)
{
	if (msg == NULL)
	{
	    return;
	}
	
	rtsp_free_msg_content(msg);
	rtsp_free_msg_buf(msg);
}

void rtsp_free_msg_content(HRTSP_MSG * msg)
{
	if (msg == NULL)
	{
	    return;
	}
	
	hdrv_ctx_free(&(msg->rtsp_ctx));
	hdrv_ctx_free(&(msg->sdp_ctx));

	net_buf_free(msg->msg_buf);
}

BOOL rtsp_get_remote_media_ip(HRTSP_MSG * rx_msg, uint32 * media_ip)
{
	HDRV * pHdr = rtsp_find_sdp_headline(rx_msg, "c");
	if ((pHdr != NULL) && (pHdr->value_string != NULL) && (strlen(pHdr->value_string) > 0))
	{
		char tmp_buf[128];
		int next_offset;
		
		GetLineWord(pHdr->value_string, 0, (int)strlen(pHdr->value_string),
				    tmp_buf, sizeof(tmp_buf), &next_offset, WORD_TYPE_STRING);
		if (strcasecmp(tmp_buf, "IN") != 0)
		{
		    return FALSE;
		}
		
		GetLineWord(pHdr->value_string, next_offset, (int)strlen(pHdr->value_string),
				    tmp_buf, sizeof(tmp_buf), &next_offset, WORD_TYPE_STRING);
		if (strcasecmp(tmp_buf, "IP4") != 0)
		{
		    return FALSE;
		}
		
		GetLineWord(pHdr->value_string, next_offset, (int)strlen(pHdr->value_string),
				    tmp_buf, sizeof(tmp_buf), &next_offset, WORD_TYPE_STRING);

		log_print(HT_LOG_DBG, "%s, media_ip=%s\r\n", __FUNCTION__, tmp_buf);

		if (is_ip_address(tmp_buf))
		{
			*media_ip = inet_addr(tmp_buf);
			return TRUE;
		}
	}

	return FALSE;
}

HDRV * rtsp_find_mdesc_point(HRTSP_MSG * rx_msg, HDRV * pStartHdr, const char * cap_name, int * next_offset, const char * attr)
{
    char media_type[16];
	HDRV * pHdr = pStartHdr;
	HDRV * pHdr1 = NULL;

	for (; pHdr != NULL; pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx),pHdr))
	{
		if (strcasecmp(pHdr->header, "m") != 0)
		{
			continue;
		}
		
		GetLineWord(pHdr->value_string, 0, (int)strlen(pHdr->value_string), media_type, sizeof(media_type), next_offset, WORD_TYPE_STRING);
		
		if (strcasecmp(media_type, cap_name) != 0)
		{
			continue;
		}
		
		if (NULL == attr)
		{
			return pHdr;
		}
		
		pHdr1 = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
		
		for (; pHdr1 != NULL; pHdr1 = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr1))
		{
			if (strcasecmp(pHdr1->header, "m") == 0)
			{
				break;
			}
			
			if (pHdr1->value_string && (pHdr1->header[0] == 'a') && (memcmp(pHdr1->value_string, attr, strlen(attr)) == 0))
			{
				return pHdr;
			}				
		}
	}

	return NULL;
}

BOOL rtsp_get_remote_cap(HRTSP_MSG * rx_msg, const char * cap_name, int * cap_count, uint8 * cap_array, uint16 * rtp_port, const char * attr)
{
	int next_offset = 0;
	char media_port[16],tmp_buf[64];

	*cap_count = 0;

	HDRV * pHdr = (HDRV *)pps_lookup_start(&(rx_msg->sdp_ctx));

	pHdr = rtsp_find_mdesc_point(rx_msg, pHdr, cap_name, &next_offset, attr);
	if (pHdr == NULL)
	{
		pps_lookup_end(&(rx_msg->sdp_ctx));
		return FALSE;
	}

	GetLineWord(pHdr->value_string, next_offset, (int)strlen(pHdr->value_string),
				media_port, sizeof(media_port), &next_offset, WORD_TYPE_NUM);
	
	GetLineWord(pHdr->value_string, next_offset, (int)strlen(pHdr->value_string),
				tmp_buf, sizeof(tmp_buf), &next_offset, WORD_TYPE_STRING);

	if (strcasecmp(tmp_buf, "RTP/AVP") != 0)
	{
		pps_lookup_end(&(rx_msg->sdp_ctx));
		return FALSE;
	}

	int count = 0;
	BOOL cap_next_flag = TRUE;
	
	do {
		cap_next_flag = GetLineWord(pHdr->value_string, next_offset, (int)strlen(pHdr->value_string),
					tmp_buf, sizeof(tmp_buf), &next_offset, WORD_TYPE_NUM);
		if (tmp_buf[0] != '\0')
		{
			if (count >= MAX_AVN)
			{
				pps_lookup_end(&(rx_msg->sdp_ctx));
				return FALSE;
			}

			cap_array[count++] = (uint8)atol(tmp_buf);
			*cap_count = count;
		}
	} while (cap_next_flag);

	if (count > 0)
	{
		if (rtp_port)
		{
			*rtp_port = (uint16)atol(media_port);
		}
		
		pps_lookup_end(&(rx_msg->sdp_ctx));
		return TRUE;
	}

	pps_lookup_end(&(rx_msg->sdp_ctx));

	return FALSE;
}

BOOL rtsp_get_digest_info(HRTSP_MSG * rx_msg, HD_AUTH_INFO * p_auth)
{
    int len;
	int	next_offset;
	char word_buf[128];
	HDRV * chap_id = NULL;
	char * p;

	p_auth->auth_response[0] = '\0';

RETRY:

    if (chap_id)
    {
        chap_id = rtsp_find_headline_next(rx_msg, "WWW-Authenticate", chap_id);
    }
    else
    {
        chap_id = rtsp_find_headline(rx_msg, "WWW-Authenticate");
    }
    
	if (chap_id == NULL)
	{
		return FALSE;
	}

	GetLineWord(chap_id->value_string, 0, (int)strlen(chap_id->value_string),
		word_buf, sizeof(word_buf), &next_offset, WORD_TYPE_STRING);
	if (strcasecmp(word_buf, "digest") != 0)
	{
        goto RETRY;
	}

	p = chap_id->value_string + next_offset;
	len = (int)strlen(chap_id->value_string) - next_offset;

    if (!http_get_digest_params(p, len, p_auth))
    {
        goto RETRY;
    }

    if (p_auth->auth_algorithm[0] != '\0' && 
        strncasecmp(p_auth->auth_algorithm, "MD5", 3) &&  
        strncasecmp(p_auth->auth_algorithm, "SHA-256", 7))
    {
        goto RETRY;
    }
	
	return TRUE;
}

BOOL rtsp_get_auth_digest_info(HRTSP_MSG * rx_msg, HD_AUTH_INFO * p_auth)
{
    int len;
    int	next_offset;
    char word_buf[128];
    char * p;
	
    HDRV * res_line = rtsp_find_headline(rx_msg, "Authorization");
	if (res_line == NULL)
	{
		return FALSE;
	}
	
	GetLineWord(res_line->value_string, 0, (int)strlen(res_line->value_string),	
	    word_buf, sizeof(word_buf), &next_offset, WORD_TYPE_STRING);
		
	if (strcasecmp(word_buf, "digest") != 0)
	{
		return FALSE;
	}

	p = res_line->value_string + next_offset;
	len = (int)strlen(res_line->value_string) - next_offset;
	
	if (!GetNameValuePair(p, len, "username", p_auth->auth_name, sizeof(p_auth->auth_name)))
	{	
		return FALSE;
	}
	
	if (!GetNameValuePair(p, len, "realm", p_auth->auth_realm, sizeof(p_auth->auth_realm)))
	{	
		return FALSE;
	}
	
	if (!GetNameValuePair(p, len, "nonce", p_auth->auth_nonce, sizeof(p_auth->auth_nonce)))
	{	
		return FALSE;
	}
	
	if (!GetNameValuePair(p, len, "uri", p_auth->auth_uri, sizeof(p_auth->auth_uri)))
	{	
		return FALSE;
	}
	
	if (!GetNameValuePair(p, len, "response", p_auth->auth_response, sizeof(p_auth->auth_response)))
	{	
		return FALSE;
	}

	if (!GetNameValuePair(p, len, "algorithm", p_auth->auth_algorithm, sizeof(p_auth->auth_algorithm)))
	{
	    p_auth->auth_algorithm[0] = '\0';
	}
	
	if (GetNameValuePair(p, len, "qop", p_auth->auth_qop, sizeof(p_auth->auth_qop)))
	{
        char * stop_string;
        
		if (!GetNameValuePair(p, len, "cnonce", p_auth->auth_cnonce, sizeof(p_auth->auth_cnonce)))
		{	
			p_auth->auth_cnonce[0] = '\0';
		}
		
		if (!GetNameValuePair(p, len, "nc", p_auth->auth_ncstr, sizeof(p_auth->auth_ncstr)))
		{	
			p_auth->auth_ncstr[0] = '\0';
		}
		
		p_auth->auth_nc = strtol(p_auth->auth_ncstr, &stop_string, 16);
		
		if (strlen(stop_string) > 0)
		{
			return FALSE;
		}
	}
	else
	{
		p_auth->auth_qop[0] = '\0';
		p_auth->auth_cnonce[0] = '\0';
		p_auth->auth_ncstr[0] = '\0';
		p_auth->auth_nc = 0;
	}

	return TRUE;
}

BOOL rtsp_get_remote_cap_desc(HRTSP_MSG * rx_msg, const char * cap_name, char cap_desc[][MAX_AVDESCLEN], const char * attr)
{
	int next_offset = 0;
	int index = 0;

	HDRV * pHdr = (HDRV *)pps_lookup_start(&(rx_msg->sdp_ctx));

	pHdr = rtsp_find_mdesc_point(rx_msg, pHdr, cap_name, &next_offset, attr);
	if (pHdr == NULL)
	{
		pps_lookup_end(&(rx_msg->sdp_ctx));
		return FALSE;
	}

	for (index=0; index<MAX_AVN; index++)
	{
		cap_desc[index][0] = '\0';
	}
	
	index = 0;
	pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
	while (pHdr != NULL)
	{
		if (strcasecmp(pHdr->header, "m") == 0)
		{
		    break;
		}
		
		if (index >= MAX_AVN)
		{
		    break;
		}
		
        snprintf(cap_desc[index], MAX_AVDESCLEN, "%s=%s", pHdr->header, pHdr->value_string);

        index++;

		pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
	}

	pps_lookup_end(&(rx_msg->sdp_ctx));

	return (index != 0);
}

BOOL rtsp_find_sdp_control(HRTSP_MSG * rx_msg, char * ctl_buf, const char * tname, int max_len, const char *attr)
{
	if (rx_msg == NULL || ctl_buf == NULL)
	{
		return FALSE;
	}
	
	int next_offset = 0;
	int mlen = (int)strlen("control:");
	
	ctl_buf[0] = '\0';

	HDRV * pHdr = (HDRV *)pps_lookup_start(&(rx_msg->sdp_ctx));

	pHdr = rtsp_find_mdesc_point(rx_msg, pHdr, tname, &next_offset, attr);
	if (pHdr == NULL)
	{
		pps_lookup_end(&(rx_msg->sdp_ctx));
		return FALSE;
	}

	pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
	while (pHdr != NULL)
	{
		if (strcasecmp(pHdr->header, "m") == 0)
		{
		    break;
		}
		
		if (pHdr->value_string && pHdr->header[0] == 'a' && memcmp(pHdr->value_string, "control:", mlen) == 0)
		{
			int rlen = (int)strlen(pHdr->value_string) - mlen;
			if (rlen > max_len)
			{
			    rlen = max_len;
			}
			
			int offset = 0;
			
			while (pHdr->value_string[offset+mlen] == ' ')
			{
			    offset++;
			}
			
			strcpy(ctl_buf, pHdr->value_string+offset+mlen);

			pps_lookup_end(&(rx_msg->sdp_ctx));
			
			return TRUE;
		}

		pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
	}

	pps_lookup_end(&(rx_msg->sdp_ctx));

	return FALSE;
}

// a=range:npt=0-20.735
BOOL rtsp_get_sdp_range(HRTSP_MSG * rx_msg, int * p_start, int * p_end)
{
    if (rx_msg == NULL)
	{
		return FALSE;
	}

	*p_start = 0;
    *p_end = 0;

	int mlen = (int)strlen("range:");
	
    HDRV * pHdr = (HDRV *)pps_lookup_start(&(rx_msg->sdp_ctx));
    pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
	while (pHdr != NULL)
	{
	    if (strcasecmp(pHdr->header, "m") == 0)
		{
		    break;
		}

		if (pHdr->value_string && pHdr->header[0] == 'a' && memcmp(pHdr->value_string, "range:", mlen) == 0)
		{
		    int i = 0;
		    int offset = 0;
		    int rlen = (int)strlen(pHdr->value_string) - mlen;
		    char start_buf[32] = {'\0'}, end_buf[32] = {'\0'};
		    char * p_buff = start_buf;

		    // skip space
			while (pHdr->value_string[offset+mlen] == ' ')
			{
			    offset++;
			}

			if (rlen < offset + 4)
			{
			    pps_lookup_end(&(rx_msg->sdp_ctx));
			    return FALSE;
			}

            if (pHdr->value_string[offset+mlen] != 'n' && 
                pHdr->value_string[offset+mlen+1] == 'p' && 
                pHdr->value_string[offset+mlen+2] == 't')
            {
                pps_lookup_end(&(rx_msg->sdp_ctx));
			    return FALSE;
            }

            offset += 3; // skip "npt"

            // skip space
            while (pHdr->value_string[offset+mlen] == ' ')
			{
			    offset++;
			}

			if (pHdr->value_string[offset+mlen] != '=')
            {
                pps_lookup_end(&(rx_msg->sdp_ctx));
			    return FALSE;
            }

            offset++; // skip '='
            
			while (pHdr->value_string[offset+mlen] != '\0')
			{
			    if (pHdr->value_string[offset+mlen] == '-')
			    {
			        i = 0;
			        p_buff = end_buf;
			    }
			    else if (pHdr->value_string[offset+mlen] != ' ')
			    {
			        p_buff[i++] = pHdr->value_string[offset+mlen];

    			    if (i >= 32)
    			    {
    			        pps_lookup_end(&(rx_msg->sdp_ctx));
    			        return FALSE;
    			    }
			    }

			    offset++;
			}

			*p_start = (int)(atof(start_buf) * 1000); // convert to millisecond 
			*p_end = (int)(atof(end_buf) * 1000);

			break;
		}

		pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
	}
	pps_lookup_end(&(rx_msg->sdp_ctx));

	return TRUE;
}

BOOL rtsp_is_support_mcast(HRTSP_MSG * rx_msg)
{
	BOOL ret = FALSE;

	HDRV * pHdr = (HDRV *)pps_lookup_start(&(rx_msg->sdp_ctx));
	while (pHdr != NULL)
	{
		if (strcasecmp(pHdr->header, "m") == 0)
		{
		    break;
		}
		
		if (strcasecmp(pHdr->header, "a") == 0)
		{
			if (strstr(pHdr->value_string, "type:broadcast"))
			{
				ret = TRUE;
				break;
			}
		}
		
		pHdr = (HDRV *)pps_lookup_next(&(rx_msg->sdp_ctx), pHdr);
	}
	pps_lookup_end(&(rx_msg->sdp_ctx));
	
	return ret;
}

BOOL rtsp_get_scale_info(HRTSP_MSG * rx_msg, int * p_scale)
{
    if (rx_msg == NULL || p_scale == NULL)
    {
		return FALSE;
    }
    
	HDRV * rx_line = rtsp_find_headline(rx_msg, "Scale");
	if (rx_line == NULL)
	{
		return FALSE;
    }
    
	char * ptr = rx_line->value_string;
	
	while (*ptr == ' ' || *ptr == '\t')
	{
	    ptr++;
    }
    
	double scale = strtod(ptr, NULL);
	if (scale == 0)
	{
		return FALSE;
    }
    
	*p_scale = (int)(scale * 100);

	return TRUE;
}

BOOL rtsp_get_rate_control(HRTSP_MSG * rx_msg, int * p_ratectrl)
{
    if (rx_msg == NULL || p_ratectrl == NULL)
    {
		return FALSE;
    }
    
	HDRV * rx_line = rtsp_find_headline(rx_msg, "Rate-Control");
	if (rx_line == NULL)
	{
		return FALSE;
    }
    
	char * ptr = rx_line->value_string;
	
	while (*ptr == ' ' || *ptr == '\t')
	{
	    ptr++;
    }

    int ratectrl = 1;
    
	if (strcasecmp(ptr, "no") == 0)
	{
	    ratectrl = 0;
	}
    
	*p_ratectrl = ratectrl;

	return TRUE;
}

BOOL rtsp_get_immediate(HRTSP_MSG * rx_msg, int * p_imme)
{
    if (rx_msg == NULL || p_imme == NULL)
    {
		return FALSE;
    }
    
	HDRV * rx_line = rtsp_find_headline(rx_msg, "Immediate");
	if (rx_line == NULL)
	{
		return FALSE;
    }
    
	char * ptr = rx_line->value_string;
	
	while (*ptr == ' ' || *ptr == '\t')
	{
	    ptr++;
    }

    int imme = 0;
    
	if (strcasecmp(ptr, "yes") == 0)
	{
	    imme = 1;
	}
    
	*p_imme = imme;

	return TRUE;
}

BOOL rtsp_get_frame_info(HRTSP_MSG * rx_msg, int * p_frame, int * p_interval)
{
    if (rx_msg == NULL || p_frame == NULL)
    {
		return FALSE;
    }
    
	HDRV * rx_line = rtsp_find_headline(rx_msg, "Frames");
	if (rx_line == NULL)
	{
		return FALSE;
    }
    
	char * ptr = rx_line->value_string;
	
	while (*ptr == ' ' || *ptr == '\t')
	{
	    ptr++;
    }

    int frame = 0; // all frames
    
	if (strncasecmp(ptr, "intra", 5) == 0)
	{
	    frame = 2; // I-frame

	    ptr += 5;

	    while (*ptr == ' ' || *ptr == '\t')
    	{
    	    ptr++;
        }

        if (*ptr == '/')
        {
            ptr++;

            if (p_interval)
            {
                *p_interval = atoi(ptr);
            }
        }	    
	}
	else if (strcasecmp(ptr, "predicted") == 0)
	{ 
	    frame = 1; // I-frame and P-frame
	}
    
	*p_frame = frame;

	return TRUE;
}


/*****************************************************************/
static PPSN_CTX * rtsp_msg_buf_fl = NULL;
static int rtsp_msg_buf_init_count = 0;
/*****************************************************************/
BOOL rtsp_msg_buf_init(int num)
{
	rtsp_msg_buf_init_count++;
    if (rtsp_msg_buf_fl)
    {
        return TRUE;
    }
    
	rtsp_msg_buf_fl = pps_ctx_fl_init(num, sizeof(HRTSP_MSG), TRUE);
	if (rtsp_msg_buf_fl == NULL)
	{
		return FALSE;
	}
	
	return TRUE;
}

void rtsp_msg_buf_deinit()
{
	rtsp_msg_buf_init_count--;
	if (rtsp_msg_buf_init_count == 0) {
		if (rtsp_msg_buf_fl)
		{
			pps_fl_free(rtsp_msg_buf_fl);
			rtsp_msg_buf_fl = NULL;
		}
	}
	if (rtsp_msg_buf_init_count < 0)rtsp_msg_buf_init_count = 0;

}

HRTSP_MSG * rtsp_get_msg_buf()
{
	HRTSP_MSG * tx_msg = (HRTSP_MSG *)pps_fl_pop(rtsp_msg_buf_fl);
	if (tx_msg == NULL)
	{
		return NULL;
	}
	
	memset(tx_msg, 0, sizeof(HRTSP_MSG));
	
	tx_msg->msg_buf = net_buf_get_idle();
	if (tx_msg->msg_buf == NULL)
	{
		rtsp_free_msg_buf(tx_msg);
		return NULL;
	}

	rtsp_msg_ctx_init(tx_msg);

	return tx_msg;
}

void rtsp_msg_ctx_init(HRTSP_MSG * msg)
{
	pps_ctx_ul_init_nm(hdrv_buf_fl, &(msg->rtsp_ctx));
	pps_ctx_ul_init_nm(hdrv_buf_fl, &(msg->sdp_ctx));
}

void rtsp_free_msg_buf(HRTSP_MSG * msg)
{
	pps_fl_push(rtsp_msg_buf_fl, msg);
}

uint32 rtsp_idle_msg_buf_num()
{
	return rtsp_msg_buf_fl->node_num;
}

BOOL rtsp_parse_buf_init(int nums)
{
	BOOL ret = rtsp_msg_buf_init(nums);
	return ret;
}

void rtsp_parse_buf_deinit()
{
	rtsp_msg_buf_deinit();
}



