./ MultiCS.r82 / sockets.c
#include "common.h" #include <stdio.h> #include <string.h> #include <stdarg.h> #include <unistd.h> #ifdef WIN32 #include <windows.h> #include <sys/types.h> #include <sys/_default_fcntl.h> #include <sys/poll.h> #include <cygwin/types.h> #include <cygwin/socket.h> #include <sys/errno.h> #include <cygwin/in.h> #include <sched.h> #include <netdb.h> #include <netinet/tcp.h> #else #include <sys/time.h> #include <time.h> #include <pthread.h> #include <sys/socket.h> #include <unistd.h> #include <netdb.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/tcp.h> #include <poll.h> #include <fcntl.h> #include <errno.h> #endif #include "debug.h" #include "tools.h" #include "sockets.h" // CONVERTION uint32_t hostname2ip( const char *hostname ) { struct hostent *phostent; unsigned int hostaddr; unsigned char *temp; phostent = gethostbyname(hostname); if (phostent==NULL) { //printf(" Error gethostbyname(%s)\n",hostname); return 0; } temp = ((unsigned char *) phostent->h_addr_list[0]); hostaddr = *(unsigned int*)temp;// *(*temp<<24) + ( *(temp+1)<<16 ) + ( *(temp+2)<<8 ) + (*(temp+3)); //printf("IP = %03d.%03d.%03d.%03d\n", *temp, *(temp+1), *(temp+2), *(temp+3)); //if (hostaddr==0x7F000001) hostaddr=0; return hostaddr; } char *iptoa(char *dest, unsigned int ip ) { sprintf(dest,"%d.%d.%d.%d", 0xFF&(ip), 0xFF&(ip>>8), 0xFF&(ip>>16), 0xFF&(ip>>24)); return dest; } char ip_string[3][0x40]; int ip_string_counter = 0; char *ip2string( unsigned int ip ) { ip_string_counter++; if (ip_string_counter>2) ip_string_counter = 0; return iptoa(ip_string[ip_string_counter], ip ); } //////////////////////////////////////////////////////////////////////////////// // SOCKETS FUNCTIONS //////////////////////////////////////////////////////////////////////////////// int fdstatus_read(int s) { fd_set readfds; int retval; struct timeval timeout; FD_ZERO(&readfds); FD_SET(s, &readfds); timeout.tv_usec = 0; timeout.tv_sec = 0; //do { retval = select(s+1, &readfds, NULL, NULL,&timeout); //} while(retval<0 && errno==EINTR); return retval; } int fdstatus_readt(int s, int tim) { fd_set readfds; int retval; struct timeval timeout; FD_ZERO(&readfds); FD_SET(s, &readfds); timeout.tv_usec = (tim%1000)*1000; timeout.tv_sec = tim/1000; // do { retval = select(s+1, &readfds, NULL, NULL,&timeout); //} while(retval<0 && errno==EINTR); return retval; } int fdstatus_writet(int s, int tim) { fd_set writefds; int retval; struct timeval timeout; FD_ZERO(&writefds); FD_SET(s, &writefds); timeout.tv_usec = (tim%1000)*1000; timeout.tv_sec = tim/1000; do { retval = select(s+1, NULL, &writefds, NULL,&timeout); } while( (retval<0) && ( (errno==EINTR)||(errno==EAGAIN) ) ); return retval; } int fdstatus_write(int s) { fd_set writefds; int retval; struct timeval timeout; FD_ZERO(&writefds); FD_SET(s, &writefds); timeout.tv_sec = 0; timeout.tv_usec = 100; do { retval = select(s+1, NULL, &writefds, NULL,&timeout); } while ( (retval<0) && ( (errno==EINTR)||(errno==EAGAIN) ) ); return retval; } int fdstatus_accept(int s) { fd_set fd; int retval; struct timeval timeout; FD_ZERO(&fd); FD_SET(s, &fd); timeout.tv_usec = 1000; timeout.tv_sec = 0; do { retval = select(s+1, &fd, NULL, NULL,&timeout); } while(retval<0 && errno==EINTR); return retval; } int SetSocketTimeout(int connectSocket, int milliseconds) { struct timeval tv; tv.tv_sec = milliseconds / 1000 ; tv.tv_usec = ( milliseconds % 1000) * 1000 ; setsockopt (connectSocket, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof tv); setsockopt (connectSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof tv); return 0; } /* Disable the Nagle (TCP No Delay) algorithm */ int SetSocketNoDelay(int sock) { int val = 1; if ( setsockopt( sock, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) < 0) return -1; return 0; } int SetSocketKeepalive(int sock) { int val = 1; if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) < 0) return -1; /* val = 60; if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, (void*)&val, sizeof(val)) < 0) return -1; val = 30; if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, (void*)&val, sizeof(val)) < 0) return -1; val = 4; if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, (void*)&val, sizeof(val)) < 0) return -1; */ return 0; } void SetSoketNonBlocking(int fd) { int flags = fcntl( fd, F_GETFL ); fcntl( fd, F_SETFL, flags|O_NONBLOCK ); } /* int SetSocketPriority(int sock) { setsockopt(sock, SOL_SOCKET, SO_PRIORITY, (void *)&cfg->netprio, sizeof(ulong)); } */ int SetSocketReuseAddr(int sock) { int reuse = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(int))< 0) return 0; else return 1; } /////////////////////////////////////////////////////////////////////////////// // UDP CONNECTION /////////////////////////////////////////////////////////////////////////////// int CreateServerSockUdp(int port, uint32_t ip) { int sock; sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock==-1) { printf("socket() failed\n"); return -1; } struct sockaddr_in saddr; memset((char *)&saddr, 0, sizeof(saddr)); saddr.sin_family = PF_INET; if (ip) saddr.sin_addr.s_addr = ip; else saddr.sin_addr.s_addr = htonl( INADDR_ANY ); if (port) saddr.sin_port = htons(port); int reuse = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(int))< 0) { close(sock); printf("setsockopt() failed\n"); return -1; } if ( bind( sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)) == -1 ) { close(sock); //if (errno==99) pthread_exit(0); /////////////////////////// XXX //printf("bind() failed\n"); return -1; } return sock; } int CreateClientSockUdp(int port, uint32_t ip) { int sock = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP); if (sock==-1) { printf("failed to create udp socket (errno=%d)\n",errno); return -1; } if (port && ip) { struct sockaddr_in saddr; saddr.sin_family = PF_INET; saddr.sin_port = htons(port); saddr.sin_addr.s_addr = ip; if ( connect(sock,(struct sockaddr *)&saddr,sizeof(struct sockaddr_in)) != 0) { close(sock); return -1; } } return sock; } /////////////////////////////////////////////////////////////////////////////// // TCP CONNECTION /////////////////////////////////////////////////////////////////////////////// int CreateServerSockTcp(int port, uint32_t ip) { int sock; sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if ( sock==-1 ) { printf("socket() failed\n"); return -1; } struct sockaddr_in saddr; saddr.sin_family = PF_INET; if (ip) saddr.sin_addr.s_addr = ip; else saddr.sin_addr.s_addr = INADDR_ANY; saddr.sin_port = htons(port); int reuse=1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(int))< 0) { close(sock); printf("setsockopt(SO_REUSEADDR) failed\n"); return -1; } if ( bind(sock, (struct sockaddr*)&saddr, sizeof(struct sockaddr))==SOCKET_ERROR ) { close(sock); //if (errno==99) pthread_exit(0); //printf("bind() failed (Port:%d)\n",port); return -1; } if (listen(sock, SOMAXCONN) == SOCKET_ERROR) { close(sock); printf("listen() failed\n"); return -1; } return sock; } int CreateClientSockTcp(uint32_t netip, int port) { int sock = socket(PF_INET,SOCK_STREAM,0); if( sock<0 ) { //printf("Invalid Socket\n"); return -1; } struct sockaddr_in saddr; memset(&saddr,0, sizeof(saddr)); saddr.sin_family = PF_INET; saddr.sin_port = htons(port); saddr.sin_addr.s_addr = netip; if ( connect(sock,(struct sockaddr *)&saddr,sizeof(struct sockaddr_in)) != 0 ) { close(sock); return -1; } return sock; } /////////////////////////////////////////////////////////////////////////////// // NON BLOCKED TCP CONNECTION /////////////////////////////////////////////////////////////////////////////// int CreateClientSockTcp_nonb(unsigned int netip, int port) { int ret, flags, error; socklen_t len; int sockfd; struct sockaddr_in saddr; sockfd = socket(AF_INET, SOCK_STREAM, 0); if( sockfd<0 ) return -1; flags = fcntl(sockfd,F_GETFL); if (flags<0) { close(sockfd); return -1; } if ( fcntl(sockfd,F_SETFL,flags|O_NONBLOCK)<0 ) { close(sockfd); return -1; } memset(&saddr,0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_port = htons(port); saddr.sin_addr.s_addr = netip; do { ret = connect( sockfd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in) ); } while ( ret && (errno==EINTR) ); if (ret) { if (errno==EINPROGRESS || errno==EALREADY) { struct pollfd pfd; pfd.fd = sockfd; pfd.events = POLLOUT; errno = 0; do { ret = poll(&pfd, 1, 1000); } while (ret < 0 && errno == EINTR); if (ret < 0) { close(sockfd); return -1; } else if (ret == 0) { errno = ETIMEDOUT; close(sockfd); return -1; } else { if ( pfd.revents && (pfd.revents & POLLOUT) ) { len = sizeof(error); if ( getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) ) { close(sockfd); return -1; } if (error) { errno = error; close(sockfd); return -1; } } else { errno = ECONNABORTED; close(sockfd); return -1; } } } else if (errno!=EISCONN) { close(sockfd); return -1; } } flags &=~ O_NONBLOCK; fcntl(sockfd, F_SETFL, flags); /* restore file status flags */ return sockfd; } int CreateServerSockTcp_nonb(int port, uint32_t ip) { struct protoent *ptrp; int p_proto; if ((ptrp = getprotobyname("tcp"))) p_proto = ptrp->p_proto; else p_proto = 6; int sock; sock = socket(AF_INET, SOCK_STREAM, p_proto); if ( sock<0 ) { printf("socket() failed\n"); return -1; } int flgs=fcntl(sock,F_GETFL); if(flgs<0) { close(sock); printf("socket: fcntl GETFL failed\n"); return -1; } if ( fcntl(sock,F_SETFL,flgs|O_NONBLOCK)<0 ) { close(sock); printf("socket: fcntl SETFL failed\n"); return -1; } int reuse=1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(int))< 0) { close(sock); printf("setsockopt(SO_REUSEADDR) failed\n"); return -1; } struct sockaddr_in saddr; saddr.sin_family = AF_INET; if (ip) saddr.sin_addr.s_addr = ip; else saddr.sin_addr.s_addr = INADDR_ANY; saddr.sin_port = htons(port); if ( bind(sock, (struct sockaddr*)&saddr, sizeof(struct sockaddr))==SOCKET_ERROR ) { close(sock); //if (errno==99) pthread_exit(0); //printf("bind() failed (Port:%d, errno=%d)\n",port,errno); return -1; } if (listen(sock, SOMAXCONN) == SOCKET_ERROR) { close(sock); printf("listen() failed\n"); return -1; } return sock; } // >0 : received ok // =0 : disconnected // =-1 : error // =-2 : timeout int recv_nonb(int sock,uint8_t *buf,int len,int timeout) { int ret; int index = 0; uint32_t now = GetTickCount(); uint32_t last = now + timeout; while (1) { struct pollfd pfd; pfd.fd = sock; pfd.events = POLLIN | POLLPRI; ret = poll(&pfd, 1, last-now); if (ret>0) { if ( pfd.revents & (POLLIN|POLLPRI) ) { ret = recv( sock, buf+index, len-index, MSG_NOSIGNAL|MSG_DONTWAIT ); if (ret>0) { index+=ret; if (index==len) return index; } else if (ret==0) return 0; // disconected else if ( (ret==-1)&&(errno!=EAGAIN)&&(errno!=EWOULDBLOCK)&&(errno!=EINTR) ) return -1; // error } if ( pfd.revents & (POLLHUP|POLLNVAL) ) return 0; // disconnected } else if (ret==0) return -2; // timeout else if ( (errno!=EINTR)&&(errno!=EAGAIN) ) return -1; // error now = GetTickCount(); if (now>last) return -2; // timeout } } int send_nonb00(int sock,uint8_t *buf,int len,int to) { if (sock<=0) return FALSE; int remain = len; uint8_t *ptr = buf; while (remain) { struct pollfd pfd; pfd.fd = sock; pfd.events = POLLOUT; int ret = poll(&pfd, 1, 100); if (ret==0) return FALSE; else if ( (ret==-1)&&(errno!=EINTR)&&(errno!=EAGAIN) ) return FALSE; else if ( pfd.revents & POLLOUT ) { int got = send( sock, (void *) ptr, (size_t) remain, MSG_NOSIGNAL|MSG_DONTWAIT); if (got >= 0) { remain -= got; ptr += got; } else if ( errno != EWOULDBLOCK && errno != EAGAIN && errno != EINTR ) { debugf(getdbgflag(DBG_ERROR,0,0)," send_nonb(%d): error(%d) (sent %d from %d)\n", sock, errno, len-remain,len ); return FALSE; } } else if ( pfd.revents & (POLLHUP|POLLERR|POLLNVAL) ) return FALSE; } return TRUE; } int send_nonb(int sock,uint8_t *buf,int len,int to) { if (sock<=0) return FALSE; int remain = len; uint8_t *ptr = buf; int got = send( sock, (void *) ptr, (size_t) remain, MSG_NOSIGNAL|MSG_DONTWAIT); if (got >= 0) { remain -= got; ptr += got; } else if ( errno != EWOULDBLOCK && errno != EAGAIN && errno != EINTR ) { //debugf(getdbgflag(DBG_ERROR,0,0)," send_nonb(%d): error(%d) (sent %d from %d)\n", sock, errno, len-remain,len ); return FALSE; } while (remain) { struct pollfd pfd; pfd.fd = sock; pfd.events = POLLOUT; int ret = poll(&pfd, 1, 100); if (ret==0) return FALSE; else if ( (ret==-1)&&(errno!=EINTR)&&(errno!=EAGAIN) ) return FALSE; else if ( pfd.revents & POLLOUT ) { int got = send( sock, (void *) ptr, (size_t) remain, MSG_NOSIGNAL|MSG_DONTWAIT); if (got >= 0) { remain -= got; ptr += got; } else if ( errno != EWOULDBLOCK && errno != EAGAIN && errno != EINTR ) { //debugf(getdbgflag(DBG_ERROR,0,0)," send_nonb(%d): error(%d) (sent %d from %d)\n", sock, errno, len-remain,len ); return FALSE; } } else if ( pfd.revents & (POLLHUP|POLLERR|POLLNVAL) ) return FALSE; } return TRUE; }