#include "./include/rtp_pub.h"
#include "./include/rtp.h"
#include "./include/rtp_const.h"
#include "./include/rtp_def.h"
#include "./include/rtp_struct.h"

extern void rtp_port_init(WORD port);
extern int rtp_release_udp_port(WORD hdlPort);

int rtp_recv_msg_handling(WORD hdlPort, BYTE *rtpMsgRvBuf, WORD len)
{
	RTP_PACKET	*packet = (RTP_PACKET *) rtpMsgRvBuf;
	RTP_PORT	*port = &rtpHdlPort[hdlPort];
	RTP_SAP		*sap;
	BYTE		cc, csLen;
	WORD        sn;
	
	if ((port->mode != RTP_MODE_RECVONLY) &&
		(port->mode != RTP_MODE_SENDRECV))
		return -1;
	
	if (port->sapIndex >= RTP_MAX_NUM_OF_SAP)
		return -1;
	
	sap = &rtpSap[port->sapIndex];
	
	if (sap->rtp_recv == NULL)
		return -1;
	
	cc = packet->ver & 0x0F;
	csLen = cc * 4;
	
	sn = ntohs(packet->sn);
	
	return (sap->rtp_recv(port->usrPort, hdlPort, packet->pt & 0x7F, packet->sn, rtpMsgRvBuf + 12 + csLen, len - 12 - csLen));
}

int rtp_handshake_proc(WORD hdlPort)
{
	RTP_PORT	*port = &rtpHdlPort[hdlPort];
	RTP_SAP		*sap;
	
	if (port->sapIndex >= RTP_MAX_NUM_OF_SAP)
		return -1;
	
	sap = &rtpSap[port->sapIndex];
	if (sap->rtp_handshake == NULL)
		return -1;
	
	if (sap->rtp_handshake(port->usrPort, hdlPort, port->rtpPort * 2 + RTP_BASE_UDP_PORT) == -1)
	{
		if (++port->times >= 3)
		{
			rtp_release_udp_port(hdlPort);
			rtp_port_init(hdlPort);
			return -1;
		}
	}
	
	port->timer = RTP_HANDSHAKE_TIMER;
	
	return 0;
}

int rtp_recv_udp_msg()
{
	int	port, i, len, addrLen = sizeof(struct sockaddr);
	
	for (port = 0; port < RTP_MAX_NUM_OF_PORT; port++)
	{
		if (rtpHdlPort[port].flag == 0)
			continue;
		
		if (rtpHdlPort[port].timer > 0)
		{
			if (--rtpHdlPort[port].timer == 0)
				rtp_handshake_proc(port);
		}
		
		if (rtpHdlPort[port].fd == -1)
			continue;
			
	    if (rtpHdlPortFd[port] != rtpHdlPort[port].fd)
	    {
		    printf("fd has been changed: fd: %d, HdlPortFd: %d\n", rtpHdlPort[port].fd, rtpHdlPortFd[port]);
            continue;	
	    }
		
		for (i = 0; i < 5; i++)
		{
			len = recvfrom(rtpHdlPort[port].fd, rtpMsgRvBuf, RTP_MAX_UDP_MSG_LEN, 
	                   			0, (struct sockaddr *)&rtpSrcInAddr, &addrLen);
			if (len < 0)
				break;
			
			if (len >= RTP_MAX_UDP_MSG_LEN)
				continue;
			
			rtp_recv_msg_handling(port, rtpMsgRvBuf, len);
		}
	}
	
	return 0;
}

int	rtp_send_udp_msg(WORD hdlPort, BYTE *msg, WORD len)
{
	int ret, fd = rtpHdlPort[hdlPort].fd;
	
	if (len >= RTP_MAX_PAYLOAD_SIZE)
		return -1;
	
	if (fd < 0)
		return -1;
	
	rtpDstInAddr.sin_addr.s_addr = rtpHdlPort[hdlPort].sess.dstIp;
	rtpDstInAddr.sin_port = htons(rtpHdlPort[hdlPort].sess.dstPort);
	
	ret = sendto(fd, msg, len, 0, (struct sockaddr *) &rtpDstInAddr, sizeof(rtpDstInAddr));
	
	return ret;
}

int rtp_send(BYTE sapIndex, WORD usrPort, WORD hdlPort, WORD sn, RTP_PAYLOAD *payload, WORD len)
{
	RTP_PACKET	*packet = (RTP_PACKET *) payload;
	
	if ((hdlPort >= RTP_MAX_NUM_OF_PORT) ||
		(len > RTP_MAX_PAYLOAD_SIZE) ||
		(payload == NULL))
		return -1;
	
	if ((rtpHdlPort[hdlPort].sapIndex != sapIndex) ||
		(rtpHdlPort[hdlPort].usrPort != usrPort))
		return -1;
	
	if (rtpHdlPort[hdlPort].mode < RTP_MODE_SENDONLY)
		return -1;
	
	packet->ver = 0x80;
	packet->pt = rtpHdlPort[hdlPort].sess.plType;
	packet->sn = htons(sn);
	rtpHdlPort[hdlPort].timeStamp += rtpHdlPort[hdlPort].inc;
	packet->timeStamp = htonl(rtpHdlPort[hdlPort].timeStamp); 
	packet->ssrc = htonl(sapIndex + usrPort + hdlPort);
	
	return rtp_send_udp_msg(hdlPort, (BYTE *) packet, len + 12);
}
