#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <linux/if_packet.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/epoll.h>

#include "protocol.h"
#include "protocol_udp.h"
#include "raw_sock.h"
#include "ldp.h"

char g_adv_buf[ADV_FRAME_LEN_MAX];

ADV_FRAME g_adv_frame;
UDP_SEND_SOCK g_udp_send;
int g_raw_sock;
/* 网络设备名称 */
char g_wan_ifname[MAX_IFNAME_LENGTH] = {0};

int load_network_config(void)
{
	char dev_name[DEVNAME_SIZE] = {0};
	if (OK != get_product_name(dev_name))
	{
		return ERROR;
	}
	
	if (0 == strcmp(DEV_NAME_V3_LITE,dev_name)) 
	{
		strncpy(g_wan_ifname, "eth0", MAX_IFNAME_LENGTH);		
	}
	else if (0 == strcmp(DEV_NAME_V3,dev_name))
	{
		strncpy(g_wan_ifname, DEV_V3_LAN_NAME, MAX_IFNAME_LENGTH);		
	}
	else if (0 == strcmp("WooLink2004-W-4G",dev_name))
	{
		strncpy(g_wan_ifname, "eth0", MAX_IFNAME_LENGTH);		
	}
	else
	{
		strncpy(g_wan_ifname, "br-lan", MAX_IFNAME_LENGTH);	
	}

	return OK;
}

size_t strlcpy(char *dest, const char *src, size_t size)
{
	size_t ret = strlen(src);

	if (size) {
		size_t len = (ret >= size) ? size - 1 : ret;
		memcpy(dest, src, len);
		dest[len] = '\0';
	}
	return ret;
}

int main(int argc, char *argv[])
{
	int ret = 0;
	int epfd = 0;
	int epoll_ev_cnt = 0;
	int i = 0;

	struct epoll_event events[MAX_EPOLL_SIZE];
	struct epoll_event ev_udp, ev_mac;

	int udprecv_sock = 0;
	PROTOCOL_HDR *ph = NULL;
	socklen_t fromlen = sizeof(struct sockaddr);
	struct sockaddr    from;
	static char bbuf_for_main[PROTOCOL_BODY_LEN];
	static char rawdata_for_main[RAW_PACKET_LEN_MAX];

	memset(rawdata_for_main, 0, RAW_PACKET_LEN_MAX);
	memset(bbuf_for_main, 0, PROTOCOL_BODY_LEN);
	memset(&from, 0, sizeof(from));

	load_network_config();

	ret = advertisement_buf_init();
	if (ret != OK)
	{
		DPRINT_ERR("advertisement frame init failed\n");
		goto ERR;
	}
	
	dy_syslog(LOG_WARNING, "ldp ifname:%s", g_wan_ifname);

	udprecv_sock = udprecv_sock_init();
	if (0 > udprecv_sock)
	{
		DPRINT_ERR("udprecv socket create failed\n");
		goto ERR;
	}

	g_raw_sock = raw_socket_init(ETH_P_TP, g_wan_ifname);
	if (ERROR == g_raw_sock)
	{
		DPRINT_ERR("raw socket init failed\n");
		goto ERR;
	}
	g_udp_send.sock = udpsend_sock_init();
	if (0 >= g_udp_send.sock)
	{
		DPRINT_ERR("send sock init error:%d\n", g_udp_send.sock);
		goto ERR;
	}

	if ((epfd = epoll_create(MAX_EPOLL_SIZE)) < 0)
	{
		DPRINT_ERR("epoll create error\n");
		goto ERR;
	}

	ev_udp.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP;
	ev_udp.data.fd = udprecv_sock;
	if (epoll_ctl(epfd, EPOLL_CTL_ADD, udprecv_sock, &ev_udp) < 0)
	{
		DPRINT_ERR("add udp socket to epoll failed.\n");
		goto ERR;
	}

	ev_mac.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP;
	ev_mac.data.fd = g_raw_sock;
	if (epoll_ctl(epfd, EPOLL_CTL_ADD, g_raw_sock, &ev_mac) < 0)
	{
		DPRINT_ERR("add mac socket to epoll failed.\n");
		goto ERR;
	}

	while(1)
	{
		epoll_ev_cnt = epoll_wait(epfd, events, MAX_EPOLL_SIZE, -1);
        if (epoll_ev_cnt == -1)
        {
            DPRINT_ERR("error, epoll_wait error");
            break;
        }
		
		//dy_syslog(LOG_WARNING, "sock recv. epoll_ev_cnt:%d", epoll_ev_cnt);
		for (i = 0; i < epoll_ev_cnt; i++)
		{
			if (events[i].events & (EPOLLERR | EPOLLRDHUP | EPOLLHUP))
			{
				DPRINT_ERR("error, epoll_wait event");
				goto ERR;
			}

			if (events[i].events & EPOLLIN && events[i].data.fd == udprecv_sock)
			{				
				//dy_syslog(LOG_WARNING, "udp sock recv.");
				ret = recvfrom(udprecv_sock, bbuf_for_main, PROTOCOL_BODY_LEN, 0, &from, &fromlen);
				if (ERROR == ret)
				{
					continue;
				}

				ph = (PROTOCOL_HDR *)bbuf_for_main;
				ret = protocol_udp_handler(ph, &from);

				if (EC_SUCCESS != ret)
				{
					DPRINT_ERR("error, ret = %d\n", ret);
					continue;
				}
			}
#if 0
			if (events[i].events & EPOLLIN && events[i].data.fd == g_raw_sock)
			{				
				//dy_syslog(LOG_WARNING, "raw sock recv.");
				ret = recv(g_raw_sock, rawdata_for_main, RAW_PACKET_LEN_MAX, 0);
				if (ERROR == ret)
				{
					continue;
				}

				ret = protocol_mac_handler(rawdata_for_main);
				if (ERROR == ret)
				{
					DPRINT_ERR("msg handle error\n");
					continue;
				}
			}
#endif


		}
	}
ERR:
	if (udprecv_sock >= 0)
	{
		close(udprecv_sock);
	}

	advertisement_buf_deinit();

	if (g_raw_sock >= 0)
	{
		close(g_raw_sock);
	}
	if (g_udp_send.sock >= 0)
	{
		close(g_udp_send.sock);
	}

	if (epfd >= 0)
	{
		close(epfd);
	}

	return 0;
}


