#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>

#include "ping.h"
#include "socket4.h"
#include "socket6.h"

int in_cksum( unsigned short *p, int n );
int random_data_flag = 1;

/* sized so as to be like traditional ping */
#define DEFAULT_PING_DATA_SIZE 56

int ping(char *ip_dest)
{
	int sockfd;
	struct sockaddr_in des_addr, recv_addr;
	unsigned char recv_buf[1024];
	int len;
	fd_set fds;
	struct timeval tv;
	int ret = -1;;

	int socktype4 = -1;
	sockfd = open_ping_socket_ipv4(&socktype4);
	if(sockfd < 0) {
		//printf("create socket failed\n");
		ret = -1;
		goto error;
	}else{
		//printf("sockfd = %d\n", sockfd);
	}

#if 1
	struct sockaddr_in local_addr;

	bzero(&local_addr, sizeof(struct sockaddr_in));
	local_addr.sin_family = AF_INET;
	local_addr.sin_addr.s_addr = htonl(INADDR_ANY);	//使用本机器上的任何一个可用IP
	local_addr.sin_port = htons(0);
	bind(sockfd, (struct sockaddr *)&local_addr, sizeof(struct sockaddr_in));
#endif

	/* send ping package */
	des_addr.sin_family = AF_INET;
	des_addr.sin_addr.s_addr = inet_addr(ip_dest);
	des_addr.sin_port = htons(0);
	init_ping_buffer_ipv4(DEFAULT_PING_DATA_SIZE);
	ret = socket_sendto_ping_ipv4(sockfd, (struct sockaddr *)&des_addr, sizeof(des_addr), 0, 61696);
	if(ret < 0){
		char buf[128] = "";

		strerror_r(errno, buf, sizeof(buf));
		//printf("socket_sendto_ping_ipv4 ret = %d, message: %s\n", ret, buf);
		ret = -6;
		goto error;
	}
	uninit_ping_buffer_ipv4();

	tv.tv_sec = 0;
	tv.tv_usec = 500*1000;
	FD_ZERO(&fds);
	FD_SET(sockfd, &fds);
	ret = select(FD_SETSIZE, &fds, NULL, NULL, &tv);
	if(ret < 0){
		//printf("ping seclect error\n");
		ret = -3;
		goto error;
	}else if(ret > 0){
		len = sizeof(recv_addr);
		ret = recvfrom(sockfd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&recv_addr, (socklen_t *)&len);
		if(ret < 0) {
			//printf("recvfrom failed!!\n");
			ret = -4;
			goto error;
		}
		//printf("ping success receive data from: %s\n", inet_ntoa(recv_addr.sin_addr));
		ret = 0;
		return ret;
	}else{
		//printf("ping time out\n");
		ret = -5;
		goto error;
	}
error:
	close(sockfd);
	return ret;
}
