#include <stdio.h>
#include <string.h>
#include "./include/ipbcp.h"

int sdp_decode_orig(SdpOrig_struct *dst_ptr, char *src_ptr)
{
	char			*token;
	unsigned char	field_id = 0;
	
	while((token = strsep(&src_ptr, " ")) != NULL)
	{
		switch(++field_id)
		{
			case 1:
				sprintf(dst_ptr->username, token);
				strcat(dst_ptr->username, "\0");
				break;
			case 2:
				sprintf(dst_ptr->session_id, token);
				strcat(dst_ptr->session_id, "\0");
				break;
			case 3:
				sprintf(dst_ptr->version, token);
				strcat(dst_ptr->version, "\0");
				break;
			case 4:
				sprintf(dst_ptr->network_type, token);
				strcat(dst_ptr->network_type, "\0");
				break;
			case 5:
				sprintf(dst_ptr->address_type, token);
				strcat(dst_ptr->address_type, "\0");
				break;
			case 6:
				sprintf(dst_ptr->address, token);
				strcat(dst_ptr->address, "\0");
				break;
			default:
				return 0;
		}
	}
	if(field_id != 6)
		return 0;
	else
		return 1;
}

int sdp_decode_conn(SdpConn_struct *dst_ptr, char *src_ptr)
{
	char			*token;
	unsigned char	field_id = 0;
	
	while((token = strsep(&src_ptr, " ")) != NULL)
	{
		switch(++field_id)
		{
			case 1:
				sprintf(dst_ptr->network_type, token);
				strcat(dst_ptr->network_type, "\0");
				break;
			case 2:
				sprintf(dst_ptr->address_type, token);
				strcat(dst_ptr->address_type, "\0");
				break;
			case 3:
				sprintf(dst_ptr->address, token);
				strcat(dst_ptr->address, "\0");
				break;
			default:
				return 0;
		}
	}
	if(field_id != 3)
		return 0;
	else
		return 1;
}

int sdp_decode_time(SdpTime_struct *dst_ptr, char *src_ptr)
{
	char			*token;
	unsigned char	field_id = 0;
	
	while((token = strsep(&src_ptr, " ")) != NULL)
	{
		switch(++field_id)
		{
			case 1:
				sprintf(dst_ptr->start, token);
				strcat(dst_ptr->start, "\0");
				break;
			case 2:
				sprintf(dst_ptr->stop, token);
				strcat(dst_ptr->stop, "\0");
				break;
			default:
				return 0;
		}
	}
	if(field_id != 2)
		return 0;
	else
		return 1;
}

int sdp_decode_attrib(SdpAttrib_struct *dst_ptr, char *src_ptr)
{
	char			*token;
	unsigned char	field_id = 0;
	
	if(strstr(src_ptr, "ipbcp:") != src_ptr)
		return 0;
	src_ptr += strlen("ipbcp:");
	while((token = strsep(&src_ptr, " ")) != NULL)
	{
		switch(++field_id)
		{
			case 1:
				sprintf(dst_ptr->version, token);
				strcat(dst_ptr->version, "\0");
				break;
			case 2:
				sprintf(dst_ptr->type, token);
				strcat(dst_ptr->type, "\0");
				break;
			default:
				return 0;
		}
	}
	if(field_id != 2)
		return 0;
	else
		return 1;
}

int sdp_decode_mediaAnn(SdpMediaAnn_struct *dst_ptr, char *src_ptr)
{
	char			*token;
	unsigned char	field_id = 0;
	
	while((token = strsep(&src_ptr, " ")) != NULL)
	{
		switch(++field_id)
		{
			case 1:
				sprintf(dst_ptr->media, token);
				strcat(dst_ptr->media, "\0");
				break;
			case 2:
				sprintf(dst_ptr->port, token);
				strcat(dst_ptr->port, "\0");	
				break;
			case 3:
				sprintf(dst_ptr->transport, token);
				strcat(dst_ptr->transport, "\0");	
				strcpy(dst_ptr->fmt_list, src_ptr);
				strcat(dst_ptr->fmt_list, "\0");	
				break;
			case 4:
			//	sprintf(dst_ptr->fmt_list, token);
				break;
			default:
				break;
		}
	}
	if(field_id < 4)
		return 0;
	else
		return 1;
}

int sdp_decode_mediaAtt(SdpMediaAtt_struct *dst_ptr, char *src_ptr)
{
	char			*token;
	unsigned char	field_id = 0;
	
	if(strstr(src_ptr, "rtpmap:") != src_ptr)
		return 0;
	src_ptr += strlen("rtpmap:");
	while((token = strsep(&src_ptr, " /")) != NULL)
	{
		switch(++field_id)
		{
			case 1:
				sprintf(dst_ptr->payload, token);
				strcat(dst_ptr->payload, "\0");	
				break;
			case 2:
				sprintf(dst_ptr->encoding_name, token);
				strcat(dst_ptr->encoding_name, "\0");	
				break;
			case 3:
				sprintf(dst_ptr->clock_rate, token);
				strcat(dst_ptr->clock_rate, "\0");	
				break;
			case 4:
//				sprintf(dst_ptr->p_time, token);
				field_id --;//to avoid 4 fields
				break;
			default:
				return 0;
		}
	}
	if(field_id != 3)
		return 0;
	else
		return 1;
}


int sdp_decode_ptime(char* p_time, char *src_ptr)
{
	char *token;
        if((token = strstr(src_ptr, "ptime:")) == NULL)
		return 0;
        token = strtok(token, ":");
        token = strtok(NULL, ":");
//	p_time = token;
//	if(strlen(token)<8)
	if(token)
	{
		sprintf(p_time, token);
		strcat(p_time, "\0");	
	}
	return 1;
	
}

int ipbcp_decode(IPBCP_struct *ipbcp_ptr, const char *ptr)
{
	char 			*token;
	unsigned char	field_id = 0;
	char			temp_ipbcp[200];
	char			*temp_ptr;
	
	strncpy(temp_ipbcp, ptr, 200);
	temp_ptr = temp_ipbcp;
	memset(ipbcp_ptr, 0, sizeof(IPBCP_struct));
	while((token = strsep(&temp_ptr, "\r\n")) != NULL)
	{
		if(strlen(token) == 0)
			continue;
		switch(++field_id)
		{
			case 1:
				if((token[0] != 'v') || (token[1] != '='))
					return 0;
				sprintf(ipbcp_ptr->proto_ver, token+2);
				strcat(ipbcp_ptr->proto_ver, "\0");	
				break;
			case 2:
				if((token[0] != 'o') || (token[1] != '='))
					return 0;
				if(!sdp_decode_orig(&ipbcp_ptr->orig, token+2))
					return 0;
				break;
			case 3:
				if((token[0] != 's') || (token[1] != '='))
					return 0;
				sprintf(ipbcp_ptr->session_name, token+2);
				
				strcat(ipbcp_ptr->session_name, "\0");	
				break;
			case 4:
				if((token[0] != 'c') || (token[1] != '='))
					return 0;
				if(!sdp_decode_conn(&ipbcp_ptr->conn_data, token+2))
					return 0;
				break;
			case 5:
				if((token[0] != 't') || (token[1] != '='))
					return 0;
				if(!sdp_decode_time(&ipbcp_ptr->time, token+2))
					return 0;
				break;
			case 6:
				if((token[0] != 'a') || (token[1] != '='))
					return 0;
				if(!sdp_decode_attrib(&ipbcp_ptr->attrib, token+2))
					return 0;
				break;
			case 7:
				if((token[0] != 'm') || (token[1] != '='))
					return 0;
				if(!sdp_decode_mediaAnn(&ipbcp_ptr->m_ann, token+2))
					return 0;
				break;
			case 8:
				if((token[0] != 'a') || (token[1] != '='))
					return 0;
				if(sdp_decode_mediaAtt(&ipbcp_ptr->m_att, token+2))
				//	return 0;
					;
				else if(!sdp_decode_ptime(ipbcp_ptr->ptime, token+2))
                                        return 0;

				break;
			case 9:
				if((token[0] != 'a') || (token[1] != '='))
					return 0;
				if(!sdp_decode_ptime(ipbcp_ptr->ptime, token+2))
					return 0;
			default:
				break;
		}
	}
	return 1;
}

int ipbcp_encode(char *ptr, const IPBCP_struct *ipbcp_ptr)
{
	char tmp_buf[128];
	
	sprintf(ptr, "v=%s\r\n", ipbcp_ptr->proto_ver);
	
	sprintf(tmp_buf, "o=%s %s %s %s %s %s\r\n", 
		ipbcp_ptr->orig.username, 
		ipbcp_ptr->orig.session_id, 
		ipbcp_ptr->orig.version, 
		ipbcp_ptr->orig.network_type, 
		ipbcp_ptr->orig.address_type, 
		ipbcp_ptr->orig.address);
	strcat(ptr, tmp_buf);
	
	sprintf(tmp_buf, "s=%s\r\n", ipbcp_ptr->session_name);
	strcat(ptr, tmp_buf);
	
	sprintf(tmp_buf, "c=%s %s %s\r\n", 
		ipbcp_ptr->conn_data.network_type, 
		ipbcp_ptr->conn_data.address_type, 
		ipbcp_ptr->conn_data.address);
	strcat(ptr, tmp_buf);
	
	sprintf(tmp_buf, "t=%s %s\r\n", ipbcp_ptr->time.start, ipbcp_ptr->time.stop);
	strcat(ptr, tmp_buf);
	
	sprintf(tmp_buf, "a=ipbcp:%s %s\r\n", ipbcp_ptr->attrib.version, ipbcp_ptr->attrib.type);
	strcat(ptr, tmp_buf);
	
	sprintf(tmp_buf, "m=%s %s %s %s\r\n", 
		ipbcp_ptr->m_ann.media, 
		ipbcp_ptr->m_ann.port, 
		ipbcp_ptr->m_ann.transport, 
		ipbcp_ptr->m_ann.fmt_list);
	strcat(ptr, tmp_buf);
	
	if(strlen(ipbcp_ptr->m_att.payload) != 0)
	{
		sprintf(tmp_buf, "a=rtpmap:%s %s/%s\r\n", 
			ipbcp_ptr->m_att.payload, 
			ipbcp_ptr->m_att.encoding_name, 
			ipbcp_ptr->m_att.clock_rate);
		strcat(ptr, tmp_buf);
	}
	//ipbcp_ptr->ptime[7]='\0';
	if((ipbcp_ptr->ptime[0] != '\0') && (strlen(ipbcp_ptr->ptime)<8))
	{
        	sprintf(tmp_buf, "a=ptime:%s\r\n", ipbcp_ptr->ptime);
        	strcat(ptr, tmp_buf);
	}
	return strlen(ptr);
}
