#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/if_ether.h> 
#include <net/ethernet.h>
#include <netinet/ether.h> 
#include <netinet/ip.h> 
#include <netinet/tcp.h> 
#include <sys/types.h>
#include <net/if.h>
#include <linux/sockios.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#define INET_UDP 0

int init_socket(unsigned int local_addr, short local_port, char stype, int noblock_flag)
{
    struct sockaddr_in sin_addr;
    int on=1, sockfd;
    
    memset((void *)&sin_addr,0x00,sizeof(struct sockaddr_in));
    sin_addr.sin_family = AF_INET;
    sin_addr.sin_port = htons(local_port);
    if(local_addr == 0)
		sin_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	else
		sin_addr.sin_addr.s_addr = local_addr;
   	 //sin_addr.sin_addr.s_addr = htonl(local_addr);
   	
    bzero((void *)&(sin_addr.sin_zero),8);
    
    if(stype == INET_UDP)
        sockfd = socket(AF_INET,SOCK_DGRAM,0);
    else
        sockfd = socket(AF_INET,SOCK_STREAM,0);
    
    setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
    
    if(stype != INET_UDP)
    {
        setsockopt(sockfd,IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
        setsockopt(sockfd,SOL_TCP, TCP_NODELAY, &on, sizeof(on));
    }
    if(noblock_flag)
        fcntl(sockfd,F_SETFL,O_NONBLOCK);
    
    bind(sockfd,(struct sockaddr*)&sin_addr,sizeof(struct sockaddr));
    
 //   listen(sockfd,1);
   
    return sockfd; 
}

int setnodelay(int fd)
{
    int on=1;
        
    setsockopt(fd,IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
    setsockopt(fd,SOL_TCP, TCP_NODELAY, &on, sizeof(on));
    
    return 1;
}

void set_peer_addr(struct sockaddr_in *peer_addr, char *peer_ip,short peer_port)
{
    peer_addr->sin_family = AF_INET;
    peer_addr->sin_port = htons(peer_port);
    peer_addr->sin_addr.s_addr = inet_addr(peer_ip);
    bzero((void *)&(peer_addr->sin_zero),8);
    
}/*set_config*/

int udp_send(int fd, int peer_ip, short peer_port, char *buf, short len)
{
    struct sockaddr_in	sin_addr;
    int ret;
	
    memset(&sin_addr, 0, sizeof(struct sockaddr));
   
    sin_addr.sin_addr.s_addr = peer_ip;
    sin_addr.sin_port = htons(peer_port);

    ret = sendto(fd, buf, len, 0, (struct sockaddr*)&sin_addr, sizeof(struct sockaddr));
	
    return ret;
}

int udp_recv(int fd, char *buf, short MAX_LEN)
{
    int len, addr_len;
    struct sockaddr_in	sin_addr;
   
    addr_len = sizeof(struct sockaddr);
    memset(&sin_addr, 0, addr_len);

    len = recvfrom(fd, buf, MAX_LEN, 0, (struct sockaddr*)&sin_addr, (socklen_t*)&addr_len);
    if(len < 0)
    	return 0;
    return len;
}

int udp_recv_with_ip_info(int fd, char *buf, short MAX_LEN, int *peer_ip, short *peer_port)
{
    int len, addr_len;
    struct sockaddr_in	sin_addr;
   
    addr_len = sizeof(struct sockaddr);
    memset(&sin_addr, 0, addr_len);

    len = recvfrom(fd, buf, MAX_LEN, 0, (struct sockaddr*)&sin_addr, (socklen_t*)&addr_len);
    if(len < 0)
    	return 0;

    *peer_ip = sin_addr.sin_addr.s_addr;
     *peer_port = htons(sin_addr.sin_port);

	return len;
}

