EGong

git clone git://xatko.vsos.ethz.ch/EGong.git
Log | Files | Refs

Socket.c (4619B)


      1 #include <EGong/Util/Socket.h>
      2 #include <EGong/Util/Config.h>
      3 #include <EGong/Util/Log.h>
      4 #include <EGong/Packet.h>
      5 
      6 #ifdef _WIN32
      7 	#include <windows.h>
      8 	#include <winsock2.h>
      9 	#include <ws2tcpip.h>
     10 	#include <iphlpapi.h>
     11 #else
     12 	#include <sys/socket.h>
     13 	#include <sys/types.h>
     14 	#include <arpa/inet.h>
     15 	#include <stdlib.h>
     16 	#include <string.h>
     17 	#include <unistd.h>
     18 	#include <netinet/in.h>
     19 #endif
     20 #include <fcntl.h>
     21 #include <errno.h>
     22 
     23 SOCKET EGong_listen_sock;
     24 
     25 #ifdef _WIN32
     26 WSADATA wsaData;
     27 #endif
     28 int inet_aton(const char *cp, struct in_addr *inp){
     29 	inp->s_addr=inet_addr(cp);
     30 	if(inp->s_addr==-1){
     31 		return 0;
     32 	}
     33 	else{
     34 		return 1;
     35 	}
     36 }
     37 
     38 int EGong_sockets_setup(void){
     39 	do_log("Setting up sockets...", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG);
     40 	#ifdef _WIN32
     41 	int res=WSAStartup(MAKEWORD(2,2), &wsaData);
     42 	if(res!=0) {
     43 		do_log("WSAStartup failed", LOG_TYPE_NORMAL, LOG_LEVEL_FATAL);
     44 		return -1;
     45 	}
     46 	#endif
     47     return 0;
     48 }
     49 int EGong_sockets_shutdown(void){
     50 	do_log("Shutting down sockets...", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG);
     51 	#ifdef _WIN32
     52 		WSACleanup();
     53 	#endif
     54     return 0;
     55 }
     56 
     57 void EGong_socket_close(SOCKET *sock){
     58 	#ifdef _WIN32
     59 		closesocket(*sock);
     60 	#else
     61 		close(*sock);
     62 	#endif
     63 }
     64 int EGong_socket_open(SOCKET *sock){
     65 	do_log("Opening UDP-Socket...", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG);
     66 	*sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
     67 	#ifdef _WIN32
     68 	if(*sock==INVALID_SOCKET){
     69 	#else
     70 	if(*sock<0){
     71 	#endif
     72 		do_log("Couldn't initialize socket",LOG_TYPE_SOCKET, LOG_LEVEL_ERROR);
     73 		EGong_socket_close(sock);
     74 		return -1;
     75 	}
     76 	return 0;
     77 }
     78 int EGong_sockaddr_init(struct sockaddr_in *addr, const char *ip, unsigned int port, sa_family_t family){
     79 	memset(addr, 0, sizeof(*addr));
     80 	if(inet_aton((char *)ip,&addr->sin_addr)<0){
     81 		do_log("Couldn't convert bind address", LOG_TYPE_SIGNAL, LOG_LEVEL_ERROR);
     82 		return -1;
     83 	}
     84 	addr->sin_family = family;
     85 	addr->sin_port = htons(port);  
     86 	return 0;   
     87 } 
     88 int EGong_listener_init(SOCKET *sock, struct EGong_config_server *config){
     89 	struct sockaddr_in listen_server;
     90 	
     91 	if(config==NULL)
     92 		config=&EGong_global_configuration.server;
     93 	if(sock==NULL)
     94 		sock=&EGong_listen_sock;
     95 	
     96 	do_log("Initializing listener...", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG);
     97 	if(EGong_socket_open(sock)<0){
     98 		do_log("Couldn't open socket",LOG_TYPE_NORMAL, LOG_LEVEL_ERROR);
     99 		return -1;
    100 	}	
    101 	#ifdef _WIN32
    102     unsigned long nonblocking_long=1;
    103     do_log("Setting socket nonblocking...", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG);
    104     if (ioctlsocket(*sock, FIONBIO, &nonblocking_long)==SOCKET_ERROR){
    105 		do_log("Couldn't set listensocket nonblocking",LOG_TYPE_SIGNAL, LOG_LEVEL_ERROR);
    106 	}
    107     #endif
    108 	if(EGong_sockaddr_init(&listen_server, config->bind_ip.str.data, config->port, AF_INET)<0){
    109 		do_log("Couldn't initialize address",LOG_TYPE_NORMAL, LOG_LEVEL_ERROR);
    110 		EGong_socket_close(sock);
    111 		return -2;
    112 	}
    113 	do_log("Binding socket...", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG);
    114 	if(bind(*sock, (struct sockaddr *) &listen_server, sizeof(listen_server))<0){
    115 		do_log("Couldn't bind to sock", LOG_TYPE_SOCKET, LOG_LEVEL_ERROR);
    116 		EGong_socket_close(sock);
    117 		return -3;
    118 	}
    119 	do_log("Listening on socket...",LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG);
    120 	return 0;
    121 }
    122 int EGong_listener_get(SOCKET *sock, char *dest, int length, struct sockaddr *source, int flags){
    123 	if(sock==NULL)
    124 		sock=&EGong_listen_sock;
    125 	int ret;
    126 	socklen_t size=sizeof(*source);
    127 	if(source==NULL){
    128 		struct sockaddr test;
    129 		source=&test;
    130 	}
    131 	do_log("Receiving on socket...",LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG);
    132 	#ifdef _WIN32
    133 	ret=recvfrom(*sock,dest,length, flags&(~MSG_DONTWAIT), source, &size);
    134 	if((flags&MSG_PEEK)>0&&ret==SOCKET_ERROR&&WSAGetLastError()==WSAEMSGSIZE){
    135 		return length;
    136 	}
    137 	else if((flags&MSG_DONTWAIT)>0&&ret==SOCKET_ERROR&&(WSAGetLastError()==WSAEWOULDBLOCK)) {
    138 	#else
    139 	ret=recvfrom(*sock,dest,length, flags, source, &size);
    140 	if((flags&MSG_DONTWAIT)>0&&ret==-1&&(errno==EAGAIN||errno==EWOULDBLOCK)) {
    141 	#endif
    142 		return 0;
    143 	}
    144 	else if(ret<0){
    145 		do_log("Couldn't receive from socket", LOG_TYPE_SOCKET, LOG_LEVEL_ERROR);
    146 		return -1;
    147 	}
    148 	return ret;
    149 }
    150 void EGong_listener_close(SOCKET *sock){
    151 	if(sock==NULL){
    152 		sock=&EGong_listen_sock;
    153 	}
    154 	EGong_socket_close(sock);
    155 }
    156 int EGong_sendto(SOCKET *sock, const char *dest, const char *msg, size_t msg_len, struct EGong_config_server *config){
    157 	struct sockaddr_in server;
    158 	if(config==NULL)
    159 		config=&EGong_global_configuration.server;
    160 	EGong_sockaddr_init(&server, dest, config->port, AF_INET);
    161 	int ret=sendto(*sock, msg, msg_len, 0, (struct sockaddr *)&server, sizeof(server));
    162 	if(ret!=msg_len){
    163 		do_log("Error while sending message", LOG_TYPE_SIGNAL, LOG_LEVEL_ERROR);
    164 	}
    165 	return ret;
    166 }