#include "./include/radius_pub.h"

int radius_recv_udp_msg(void)
{
	struct sockaddr_in		radius_src_addr;
	int					i, len, addr_len = sizeof(struct sockaddr);
	RADIUS_ADDR		addr;
	int					nas_id;

	for (i = 0; i < RADIUS_MAX_UDP_MSG_GET_TIMES; i++)
	{
		len = recvfrom(radius_udp_access_socket_fd, radius_udp_msg_recv_buf, RADIUS_MAX_LEN_OF_UDP_MSG, \
			0, (struct sockaddr *)&radius_src_addr, (socklen_t*)&addr_len);
		if (len < 0)
			break;

		if (len >= RADIUS_MAX_LEN_OF_UDP_MSG)
			continue;

		memset(radius_udp_msg_recv_buf + len, 0, RADIUS_MAX_LEN_OF_UDP_MSG - len);

		addr.port = ntohs(radius_src_addr.sin_port);
		addr.addr.ipV4 = radius_src_addr.sin_addr.s_addr;

		if ((nas_id = radius_accord_ip_search_nas_info(radius_src_addr.sin_addr.s_addr)) < 0)
		{
			radius_log_warn("%s: recv msg from %s, no such nas ip\r\n", __FUNCTION__, inet_ntoa(radius_src_addr.sin_addr));
			continue;
		}

		radius_udp_msg_handling(radius_udp_msg_recv_buf, len, &addr, nas_id);
	}

	for (i = 0; i < RADIUS_MAX_UDP_MSG_GET_TIMES; i++)
	{
		len = recvfrom(radius_udp_account_socket_fd, radius_udp_msg_recv_buf, RADIUS_MAX_LEN_OF_UDP_MSG, \
			0, (struct sockaddr *)&radius_src_addr, (socklen_t*)&addr_len);
		if (len < 0)
			break;

		if (len >= RADIUS_MAX_LEN_OF_UDP_MSG)
			continue;

		memset(radius_udp_msg_recv_buf + len, 0, RADIUS_MAX_LEN_OF_UDP_MSG - len);

		addr.port = ntohs(radius_src_addr.sin_port);
		addr.addr.ipV4 = radius_src_addr.sin_addr.s_addr;

		if ((nas_id = radius_accord_ip_search_nas_info(radius_src_addr.sin_addr.s_addr)) < 0)
		{
			radius_log_warn("%s: recv msg from %s, no such nas ip\r\n", __FUNCTION__, inet_ntoa(radius_src_addr.sin_addr));
			continue;
		}

		radius_udp_msg_handling(radius_udp_msg_recv_buf, len, &addr, nas_id);
	}

	for (i = 0; i < RADIUS_MAX_UDP_MSG_GET_TIMES; i++)
	{
		len = recvfrom(radius_udp_disconnect_socket_fd, radius_udp_msg_recv_buf, RADIUS_MAX_LEN_OF_UDP_MSG, \
			0, (struct sockaddr *)&radius_src_addr, (socklen_t*)&addr_len);
		if (len < 0)
			break;

		if (len >= RADIUS_MAX_LEN_OF_UDP_MSG)
			continue;

		memset(radius_udp_msg_recv_buf + len, 0, RADIUS_MAX_LEN_OF_UDP_MSG - len);

		addr.port = ntohs(radius_src_addr.sin_port);
		addr.addr.ipV4 = radius_src_addr.sin_addr.s_addr;

		if ((nas_id = radius_accord_ip_search_nas_info(radius_src_addr.sin_addr.s_addr)) < 0)
		{
			radius_log_warn("%s: recv msg from %s, no such nas ip\r\n", __FUNCTION__, inet_ntoa(radius_src_addr.sin_addr));
			continue;
		}

		radius_udp_msg_handling(radius_udp_msg_recv_buf, len, &addr, nas_id);
	}

	return 0;
}

int radius_send_udp_msg(int pid)
{
	int					ret;
	int					len;
	RADIUS_PID			*pid_ptr;
	struct sockaddr_in		radius_dst_addr;
	int					socket_fd;

	pid_ptr = radius_get_pid_ptr(pid);

	len = pid_ptr->msg_len;

	if (len >= RADIUS_MAX_LEN_OF_MSG)
	{
		radius_log_err("%s: msg len=%d\r\n", __FUNCTION__, pid_ptr->msg_len);
		return -1;
	}

	if (radius_set_udp_dest_addr(&radius_dst_addr, &pid_ptr->peer_addr) < 0)
	{
		radius_log_err("%s: set destination address fail, pid=%d, dest_port=%d, dest_ip=0x%X\r\n", __FUNCTION__, pid, pid_ptr->peer_addr.port, pid_ptr->peer_addr.addr.ipV4);
		return -1;
	}

	if ((socket_fd = radius_get_sock_fd_according_msg_type(pid_ptr->sd_msg_type)) < 0)
	{
		radius_log_err("%s: msg type=%d get sock fd fail\r\n", __FUNCTION__, pid_ptr->sd_msg_type);
		return -1;
	}

	ret = sendto(socket_fd, pid_ptr->msg, len, 0, (struct sockaddr *)&radius_dst_addr, sizeof(struct sockaddr_in));

	radius_log_send_recv_msg(pid_ptr->msg, len, &pid_ptr->peer_addr, pid_ptr->sd_msg_type, RADIUS_SEND_MSG_FLAG);

	if (ret < 0)
	{
		radius_log_err("%s: send msg fail\r\n", __FUNCTION__);
	}
	
	return ret;
}

