#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <termios.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "net_module.h"

int isNumberChar(char ch)
{
  if((ch >= '0')&&(ch <= '9')) return 1;
  else return 0;
}

void app_get_pid(char *str, char *pid)
{
  char *ptr = str;
  while(++ptr)   if(isNumberChar(*ptr))break;
  char *value_begin = ptr;
  while(++ptr)   if(!isNumberChar(*ptr))break;
  char *value_end = ptr;
  
  if(value_end - value_begin <= 5)
  {
	memcpy(pid, value_begin, value_end - value_begin);
  }
} 

int get_exec_info(char* command, char *res, int buf_len)
{
	FILE *fp;
	char* t;

	fp = popen(command, "r");
	if(!fp)
		return -1;

	sleep(1);
	
	t = fgets(res, buf_len-1, fp);
	
	if(fp)
		pclose(fp);
	
	return 0;
}

int get_usbnet_device(void)
{
	char  cmd[256]={0};
	
	int ret = get_exec_info("ls /dev/ttyUSB* | grep \"ttyUSB\" >&1", cmd, sizeof(cmd));
	if(ret)
	{
		printf("%s fail \n",__FUNCTION__);
		return 0;
	}

	if(strstr(cmd, "ttyUSB"))
		return 1;
	
	return 0;
}

int get_pppd_process(void)
{
	char  cmd[256]={0};
	
	int ret = get_exec_info("ps | grep \"pppd\" >&1", cmd, sizeof(cmd));
	if(ret)
	{
		printf("%s fail \n",__FUNCTION__);
		return 0;
	}

	if(strstr(cmd, "pppd call"))
		return 1;
	
	return 0;
}

int get_pppx_device(void)
{
	char  cmd[256]={0};
	
	int ret = get_exec_info("ifconfig | grep \"ppp\" >&1", cmd, sizeof(cmd));
	if(ret)
	{
		printf("%s fail \n",__FUNCTION__);
		return 0;
	}

	if(strstr(cmd, "ppp"))
		return 1;
	
	return 0;
}

int get_ping_status(void)
{
	char  cmd[256]={0};
	
	int ret = get_exec_info("ping -w 1 -c 1 183.129.159.163 | grep \"time=\" >&1", cmd, sizeof(cmd));
	if(ret)
	{
		printf("%s fail \n",__FUNCTION__);
		return 0;
	}

	if(strstr(cmd, "time"))
		return 1;
	
	return 0;
}

int exec_usbnet_device_reset(void)
{
	char  cmd[256]={0}, kill[64]={0};

	memset(cmd, 0x00, sizeof(cmd));
	int ret = get_exec_info("ps | grep \"pppd\" >&1", cmd, sizeof(cmd));
	if(ret)
	{
		printf("get pppd run info fail \n");
	}

	if(strstr(cmd, "pppd call"))
	{
		int i;
		#if 1
		memset(kill, 0x00, sizeof(kill));
		strcpy(kill, "kill -9 ");
		app_get_pid(cmd, &kill[strlen(kill)]);
		printf("%s \n", kill);
		system(kill);
		#else
		system("killall pppd");
		#endif
	}

	memset(cmd, 0x00, sizeof(cmd));
	ret = get_exec_info("pcie_rst | grep \"set gpio\" >&1", cmd, sizeof(cmd));
	if(ret)
	{
		printf("pcie_rst fail \n");
		return 0;
	}

	return 0;
}

int exec_usbnet_pppd(void)
{
	system("pppd call gprs & >&1");
	
	return 0;
}

int exec_dns_114(void)
{
	system("echo \"nameserver 114.114.114.114\" >>/etc/resolv.conf >&1");
	
	return 0;
}

int exec_route_add(void)
{
	char  cmd[256];
	
	int ret = get_exec_info("route add default gw 10.64.64.64 >&1", cmd, sizeof(cmd));
	if(ret)
	{
		printf("%s fail \n",__FUNCTION__);
		return 0;
	}
}

int exec_route_del(void)
{
	char  cmd[256];
	
	int ret = get_exec_info("route del default gw 10.64.64.64 >&1", cmd, sizeof(cmd));
	if(ret)
	{
		printf("%s fail \n",__FUNCTION__);
		return 0;
	}
}

int net_connection_fail_pro(void)
{
	exec_usbnet_pppd();
	usleep(10000000);
	exec_route_del();
	exec_route_add();
	exec_dns_114();
}

void* net_pthread(void* param)
{
	int pppdCnt=0,pingCnt=0,stateChg=0;
	int usbDev=0,pppd=0,pppx=0,ping=0;
	int useEth=0,okCnt=0,ethChg=0;

	while(!get_usbnet_device() && pppdCnt < 5)
	{
		pppdCnt++;
		if(get_ping_status())
		{
			useEth=1;
			break;
		}
		usleep(500000);
	}
	
	pppdCnt = 0;
	while(1)
	{	
		//本地网络连网监测
		if(get_ping_status())
		{
			if(usbDev && pppd && pppx)
			{
				useEth = 0;
				okCnt = 0;
			}
			else
				okCnt++;
			
			if(okCnt > 1)
				useEth = 1;
			
			if(useEth)
			{
				system("touch /tmp/net_ok");
				if(ethChg != 2)
					printf("net_supervisor: ETHX successful connection of the Internet... \n");
				ethChg = 2;
				usleep(2000000);
				continue;
			}
		}
		else
		{
			if(useEth)
			{
				if(access("/tmp/net_ok",F_OK) != -1)
					system("rm /tmp/net_ok");
				printf("ETHX unusual net_supervisor!!!\n");
				useEth = 0;
			}
			ethChg = 0;
			okCnt = 0;
		}

		if(!useEth)
		{
			//是否识别USB设备
			usbDev = get_usbnet_device();
			if(usbDev)
			{
				//是否拨号中
				pppd = get_pppd_process();
				if(pppd)
				{		
					pppdCnt = 0;
					//是否拨号成功
					pppx = get_pppx_device();
					if(pppx)
					{
						//是否联网成功
						ping = get_ping_status();
						if(ping)
						{
							pingCnt = 0;
						}
						else
						{
							exec_route_del();
							exec_route_add();
							pingCnt++;
						}
					}
					else
					{
						net_connection_fail_pro();
					}
				}
				else
				{
					pppdCnt++;
					net_connection_fail_pro();
				}
			}
			else
			{
				exec_usbnet_device_reset();
				usleep(10000000);
			}

			if(pingCnt >= 3 || pppdCnt >= 3)
			{
				pingCnt = 0;
				pppdCnt = 0;
				exec_usbnet_device_reset();
				usleep(10000000);
			}
			
			if(usbDev && pppd && pppx && ping)
			{	
				system("touch /tmp/net_ok");
				if(stateChg != 2)
					printf("net_supervisor: Congratulations on the successful connection of the Internet... \n");
				stateChg = 2;
				usleep(2000000);
			}
			else
			{
				if(access("/tmp/net_ok",F_OK) != -1)
					system("rm /tmp/net_ok");
				stateChg = 0;
				printf("unusual net_supervisor!!!\n");
				printf("net_supervisor usbDev %d pppd %d pppx %d ping %d pppdCnt %d pingCnt %d \n",usbDev,pppd,pppx,ping,pppdCnt,pingCnt);
				usleep(200000);
			}
		}
	}
}

//启动网络模块
int Net_start(void)
{
	pthread_t pthread_net;
	
	printf("%s %d \n",__FUNCTION__,__LINE__);
	pthread_create(&pthread_net, 0, net_pthread, NULL);
	
	return 0;
}

//停止网络模块
int Net_stop(void)
{
	printf("%s %d \n",__FUNCTION__,__LINE__);
	return 0;
}

