diff options
| -rw-r--r-- | src/base/system.c | 492 | ||||
| -rw-r--r-- | src/base/system.h | 13 | ||||
| -rw-r--r-- | src/engine/client/client.cpp | 28 | ||||
| -rw-r--r-- | src/engine/client/serverbrowser.cpp | 6 | ||||
| -rw-r--r-- | src/engine/server.h | 2 | ||||
| -rw-r--r-- | src/engine/server/server.cpp | 51 | ||||
| -rw-r--r-- | src/engine/server/server.h | 2 | ||||
| -rw-r--r-- | src/engine/serverbrowser.h | 2 | ||||
| -rw-r--r-- | src/engine/shared/network_client.cpp | 10 | ||||
| -rw-r--r-- | src/engine/shared/network_server.cpp | 2 | ||||
| -rw-r--r-- | src/game/server/gamecontext.cpp | 17 |
11 files changed, 477 insertions, 148 deletions
diff --git a/src/base/system.c b/src/base/system.c index c0b8edec..d4c81cf4 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -25,6 +25,7 @@ #include <netinet/in.h> #include <fcntl.h> #include <pthread.h> + #include <arpa/inet.h> #include <dirent.h> @@ -63,6 +64,8 @@ static int num_loggers = 0; static NETSTATS network_stats = {0}; static MEMSTATS memory_stats = {0}; +static NETSOCKET invalid_socket = {NETTYPE_INVALID, -1, -1}; + void dbg_logger(DBG_LOGGER logger) { loggers[num_loggers++] = logger; @@ -509,27 +512,55 @@ int64 time_freq() } /* ----- network ----- */ -static void netaddr_to_sockaddr(const NETADDR *src, struct sockaddr *dest) +static void netaddr_to_sockaddr_in(const NETADDR *src, struct sockaddr_in *dest) { - /* TODO: IPv6 support */ - struct sockaddr_in *p = (struct sockaddr_in *)dest; - mem_zero(p, sizeof(struct sockaddr_in)); - p->sin_family = AF_INET; - p->sin_port = htons(src->port); - p->sin_addr.s_addr = htonl(src->ip[0]<<24|src->ip[1]<<16|src->ip[2]<<8|src->ip[3]); + mem_zero(dest, sizeof(struct sockaddr_in)); + if(src->type != NETTYPE_IPV4) + { + dbg_msg("system", "couldn't convert NETADDR of type %d to ipv4", src->type); + return; + } + + dest->sin_family = AF_INET; + dest->sin_port = htons(src->port); + mem_copy(&dest->sin_addr.s_addr, src->ip, 4); +} + +static void netaddr_to_sockaddr_in6(const NETADDR *src, struct sockaddr_in6 *dest) +{ + mem_zero(dest, sizeof(struct sockaddr_in6)); + if(src->type != NETTYPE_IPV6) + { + dbg_msg("system", "couldn't not convert NETADDR of type %d to ipv6", src->type); + return; + } + + dest->sin6_family = AF_INET6; + dest->sin6_port = htons(src->port); + mem_copy(&dest->sin6_addr.s6_addr, src->ip, 16); } static void sockaddr_to_netaddr(const struct sockaddr *src, NETADDR *dst) { - /* TODO: IPv6 support */ - unsigned int ip = htonl(((struct sockaddr_in*)src)->sin_addr.s_addr); - mem_zero(dst, sizeof(NETADDR)); - dst->type = NETTYPE_IPV4; - dst->port = htons(((struct sockaddr_in*)src)->sin_port); - dst->ip[0] = (unsigned char)((ip>>24)&0xFF); - dst->ip[1] = (unsigned char)((ip>>16)&0xFF); - dst->ip[2] = (unsigned char)((ip>>8)&0xFF); - dst->ip[3] = (unsigned char)(ip&0xFF); + if(src->sa_family == AF_INET) + { + mem_zero(dst, sizeof(NETADDR)); + dst->type = NETTYPE_IPV4; + dst->port = htons(((struct sockaddr_in*)src)->sin_port); + mem_copy(dst->ip, &((struct sockaddr_in*)src)->sin_addr.s_addr, 4); + } + else if(src->sa_family == AF_INET6) + { + mem_zero(dst, sizeof(NETADDR)); + dst->type = NETTYPE_IPV6; + dst->port = htons(((struct sockaddr_in6*)src)->sin6_port); + mem_copy(dst->ip, &((struct sockaddr_in6*)src)->sin6_addr.s6_addr, 16); + } + else + { + mem_zero(dst, sizeof(struct sockaddr)); + dbg_msg("system", "couldn't convert sockaddr of family %d", src->sa_family); + } } int net_addr_comp(const NETADDR *a, const NETADDR *b) @@ -552,23 +583,70 @@ void net_addr_str(const NETADDR *addr, char *string, int max_length) str_format(string, max_length, "unknown type %d", addr->type); } +static int priv_net_extract(const char *hostname, char *host, int max_host, int *port) +{ + int i; + + *port = 0; + host[0] = 0; + + if(hostname[0] == '[') + { + // ipv6 mode + for(i = 1; i < max_host-1 && hostname[i] && hostname[i] != ']'; i++) + host[i-1] = hostname[i]; + host[i-1] = 0; + if(hostname[i] != ']') // malformatted + return -1; + + i++; + if(hostname[i] == ':') + *port = atol(hostname+i+1); + } + else + { + // generic mode (ipv4, hostname etc) + for(i = 0; i < max_host-1 && hostname[i] && hostname[i] != ':'; i++) + host[i] = hostname[i]; + host[i] = 0; + + if(hostname[i] == ':') + *port = atol(hostname+i+1); + } + + return 0; +} + int net_host_lookup(const char *hostname, NETADDR *addr, int types) { - /* TODO: IPv6 support */ struct addrinfo hints; struct addrinfo *result; int e; + char host[256]; + int port = 0; + + if(priv_net_extract(hostname, host, sizeof(host), &port)) + return -1; + /* + dbg_msg("host lookup", "host='%s' port=%d %d", host, port, types); + */ mem_zero(&hints, sizeof(hints)); - hints.ai_family = AF_INET; + + hints.ai_family = AF_UNSPEC; + + if(types == NETTYPE_IPV4) + hints.ai_family = AF_INET; + else if(types == NETTYPE_IPV6) + hints.ai_family = AF_INET6; - e = getaddrinfo(hostname, NULL, &hints, &result); + e = getaddrinfo(host, NULL, &hints, &result); if(e != 0 || !result) return -1; sockaddr_to_netaddr(result->ai_addr, addr); freeaddrinfo(result); - addr->port = 0; + addr->port = port; return 0; } @@ -629,7 +707,39 @@ int net_addr_from_str(NETADDR *addr, const char *string) if(str[0] == '[') { - /* TODO: ipv6 */ + /* ipv6 */ + struct sockaddr_in6 sa6; + char buf[128]; + int i, size; + for(i = 0; i < 127 && str[i] && str[i] != ']'; i++) + buf[i] = str[i]; + buf[i] = 0; + str += i; +#if defined(CONF_FAMILY_WINDOWS) + sa6.sin6_family = AF_INET6; + size = (int)sizeof(sa6); + if(WSAStringToAddress(buf, AF_INET6, NULL, (struct sockaddr *)&sa6, &size) != 0) + return -1; +#else + if(inet_pton(AF_INET6, buf, &sa6) != 1) + return -1; +#endif + sockaddr_to_netaddr((struct sockaddr *)&sa6, addr); + + if(*str == ']') + { + str++; + if(*str == ':') + { + str++; + if(parse_uint16(&addr->port, &str)) + return -1; + } + } + else + return -1; + + return 0; } else { @@ -653,25 +763,63 @@ int net_addr_from_str(NETADDR *addr, const char *string) return 0; } +static void priv_net_close_socket(int sock) +{ +#if defined(CONF_FAMILY_WINDOWS) + closesocket(sock); +#else + close(sock); +#endif +} -NETSOCKET net_udp_create(NETADDR bindaddr) +static int priv_net_close_all_sockets(NETSOCKET sock) { - /* TODO: IPv6 support */ - struct sockaddr addr; + /* close down ipv4 */ + if(sock.ipv4sock >= 0) + { + priv_net_close_socket(sock.ipv4sock); + sock.ipv4sock = -1; + sock.type &= ~NETTYPE_IPV4; + } + + /* close down ipv6 */ + if(sock.ipv6sock >= 0) + { + priv_net_close_socket(sock.ipv6sock); + sock.ipv6sock = -1; + sock.type &= ~NETTYPE_IPV6; + } + return 0; +} + +static int priv_net_create_socket(int domain, int type, struct sockaddr *addr, int sockaddrlen) +{ + int sock, e; unsigned long mode = 1; int broadcast = 1; /* create socket */ - int sock = socket(AF_INET, SOCK_DGRAM, 0); + sock = socket(domain, type, 0); if(sock < 0) - return NETSOCKET_INVALID; - - /* bind, we should check for error */ - netaddr_to_sockaddr(&bindaddr, &addr); - if(bind(sock, &addr, sizeof(addr)) != 0) { - net_udp_close(sock); - return NETSOCKET_INVALID; + dbg_msg("net", "failed to create socket with domain %d and type %d (%d '%s')", domain, type, errno, strerror(errno)); + return -1; + } + + /* set to IPv6 only if thats what we are creating */ + if(domain == AF_INET6) + { + int ipv6only = 1; + setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&ipv6only, sizeof(ipv6only)); + } + + /* bind the socket */ + e = bind(sock, addr, sockaddrlen); + if(e != 0) + { + dbg_msg("net", "failed to bind socket with domain %d and type %d (%d '%s')", domain, type, errno, strerror(errno)); + priv_net_close_socket(sock); + return -1; } /* set non-blocking */ @@ -684,23 +832,109 @@ NETSOCKET net_udp_create(NETADDR bindaddr) /* set boardcast */ setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast)); + /* return the newly created socket */ + return sock; +} + +NETSOCKET net_udp_create(NETADDR bindaddr) +{ + NETSOCKET sock = invalid_socket; + NETADDR tmpbindaddr = bindaddr; + + if(bindaddr.type&NETTYPE_IPV4) + { + struct sockaddr_in addr; + int socket = -1; + + /* bind, we should check for error */ + tmpbindaddr.type = NETTYPE_IPV4; + netaddr_to_sockaddr_in(&tmpbindaddr, &addr); + socket = priv_net_create_socket(AF_INET, SOCK_DGRAM, (struct sockaddr *)&addr, sizeof(addr)); + if(socket >= 0) + { + sock.type |= NETTYPE_IPV4; + sock.ipv4sock = socket; + } + } + + if(bindaddr.type&NETTYPE_IPV6) + { + struct sockaddr_in6 addr; + int socket = -1; + + /* bind, we should check for error */ + tmpbindaddr.type = NETTYPE_IPV6; + netaddr_to_sockaddr_in6(&tmpbindaddr, &addr); + socket = priv_net_create_socket(AF_INET6, SOCK_DGRAM, (struct sockaddr *)&addr, sizeof(addr)); + if(socket >= 0) + { + sock.type |= NETTYPE_IPV6; + sock.ipv6sock = socket; + } + } + /* return */ return sock; } int net_udp_send(NETSOCKET sock, const NETADDR *addr, const void *data, int size) { - struct sockaddr sa; - int d; - mem_zero(&sa, sizeof(sa)); - netaddr_to_sockaddr(addr, &sa); - d = sendto((int)sock, (const char*)data, size, 0, &sa, sizeof(sa)); + int d = -1; + + if(addr->type&NETTYPE_IPV4) + { + if(sock.ipv4sock >= 0) + { + struct sockaddr_in sa; + if(addr->type&NETTYPE_LINK_BROADCAST) + { + mem_zero(&sa, sizeof(sa)); + sa.sin_port = htons(addr->port); + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = INADDR_BROADCAST; + } + else + netaddr_to_sockaddr_in(addr, &sa); + + d = sendto((int)sock.ipv4sock, (const char*)data, size, 0, (struct sockaddr *)&sa, sizeof(sa)); + } + else + dbg_msg("net", "can't sent ipv4 traffic to this socket"); + } + + if(addr->type&NETTYPE_IPV6) + { + if(sock.ipv6sock >= 0) + { + struct sockaddr_in6 sa; + if(addr->type&NETTYPE_LINK_BROADCAST) + { + mem_zero(&sa, sizeof(sa)); + sa.sin6_port = htons(addr->port); + sa.sin6_family = AF_INET6; + sa.sin6_addr.s6_addr[0] = 0xff; /* multicast */ + sa.sin6_addr.s6_addr[1] = 0x02; /* link local scope */ + sa.sin6_addr.s6_addr[15] = 1; /* all nodes */ + } + else + netaddr_to_sockaddr_in6(addr, &sa); + + d = sendto((int)sock.ipv6sock, (const char*)data, size, 0, (struct sockaddr *)&sa, sizeof(sa)); + } + else + dbg_msg("net", "can't sent ipv6 traffic to this socket"); + } + /* + else + dbg_msg("net", "can't sent to network of type %d", addr->type); + */ + /*if(d < 0) { char addrstr[256]; net_addr_str(addr, addrstr, sizeof(addrstr)); - dbg_msg("net", "sendto error %d %x", d, d); + dbg_msg("net", "sendto error (%d '%s')", errno, strerror(errno)); dbg_msg("net", "\tsock = %d %x", sock, sock); dbg_msg("net", "\tsize = %d %x", size, size); dbg_msg("net", "\taddr = %s", addrstr); @@ -713,13 +947,25 @@ int net_udp_send(NETSOCKET sock, const NETADDR *addr, const void *data, int size int net_udp_recv(NETSOCKET sock, NETADDR *addr, void *data, int maxsize) { - struct sockaddr from; - int bytes; - socklen_t fromlen = sizeof(struct sockaddr); - bytes = recvfrom(sock, (char*)data, maxsize, 0, &from, &fromlen); + char sockaddrbuf[128]; + socklen_t fromlen;// = sizeof(sockaddrbuf); + int bytes = 0; + + if(bytes == 0 && sock.ipv4sock >= 0) + { + fromlen = sizeof(struct sockaddr_in); + bytes = recvfrom(sock.ipv4sock, (char*)data, maxsize, 0, (struct sockaddr *)&sockaddrbuf, &fromlen); + } + + if(bytes <= 0 && sock.ipv6sock >= 0) + { + fromlen = sizeof(struct sockaddr_in6); + bytes = recvfrom(sock.ipv6sock, (char*)data, maxsize, 0, (struct sockaddr *)&sockaddrbuf, &fromlen); + } + if(bytes > 0) { - sockaddr_to_netaddr(&from, addr); + sockaddr_to_netaddr((struct sockaddr *)&sockaddrbuf, addr); network_stats.recv_bytes += bytes; network_stats.recv_packets++; return bytes; @@ -731,27 +977,29 @@ int net_udp_recv(NETSOCKET sock, NETADDR *addr, void *data, int maxsize) int net_udp_close(NETSOCKET sock) { -#if defined(CONF_FAMILY_WINDOWS) - closesocket(sock); -#else - close((int)sock); -#endif - return 0; + return priv_net_close_all_sockets(sock); } +// TODO: make TCP stuff work again NETSOCKET net_tcp_create(const NETADDR *a) { /* TODO: IPv6 support */ - struct sockaddr addr; + NETSOCKET sock = invalid_socket; - /* create socket */ - int sock = socket(AF_INET, SOCK_STREAM, 0); - if(sock < 0) - return NETSOCKET_INVALID; + if(a->type&NETTYPE_IPV4) + { + struct sockaddr_in addr; + + /* create socket */ + sock.type |= NETTYPE_IPV4; + sock.ipv4sock = socket(AF_INET, SOCK_STREAM, 0); + if(sock.ipv4sock < 0) + return invalid_socket; - /* bind, we should check for error */ - netaddr_to_sockaddr(a, &addr); - bind(sock, &addr, sizeof(addr)); + /* bind, we should check for error */ + netaddr_to_sockaddr_in(a, &addr); + bind(sock.ipv4sock, (struct sockaddr *)&addr, sizeof(addr)); + } /* return */ return sock; @@ -760,26 +1008,58 @@ NETSOCKET net_tcp_create(const NETADDR *a) int net_tcp_set_non_blocking(NETSOCKET sock) { unsigned long mode = 1; + if(sock.ipv4sock >= 0) + { #if defined(CONF_FAMILY_WINDOWS) - return ioctlsocket(sock, FIONBIO, &mode); + ioctlsocket(sock.ipv4sock, FIONBIO, (unsigned long *)&mode); #else - return ioctl(sock, FIONBIO, &mode); + ioctl(sock.ipv4sock, FIONBIO, (unsigned long *)&mode); #endif + } + + if(sock.ipv6sock >= 0) + { +#if defined(CONF_FAMILY_WINDOWS) + ioctlsocket(sock.ipv6sock, FIONBIO, (unsigned long *)&mode); +#else + ioctl(sock.ipv6sock, FIONBIO, (unsigned long *)&mode); +#endif + } + + return 0; } int net_tcp_set_blocking(NETSOCKET sock) { unsigned long mode = 0; + if(sock.ipv4sock >= 0) + { +#if defined(CONF_FAMILY_WINDOWS) + ioctlsocket(sock.ipv4sock, FIONBIO, (unsigned long *)&mode); +#else + ioctl(sock.ipv4sock, FIONBIO, (unsigned long *)&mode); +#endif + } + + if(sock.ipv6sock >= 0) + { #if defined(CONF_FAMILY_WINDOWS) - return ioctlsocket(sock, FIONBIO, &mode); + ioctlsocket(sock.ipv6sock, FIONBIO, (unsigned long *)&mode); #else - return ioctl(sock, FIONBIO, &mode); + ioctl(sock.ipv6sock, FIONBIO, (unsigned long *)&mode); #endif + } + + return 0; } int net_tcp_listen(NETSOCKET sock, int backlog) { - return listen(sock, backlog); + if(sock.ipv4sock >= 0) + listen(sock.ipv4sock, backlog); + if(sock.ipv6sock >= 0) + listen(sock.ipv6sock, backlog); + return 0; } int net_tcp_accept(NETSOCKET sock, NETSOCKET *new_sock, NETADDR *a) @@ -788,61 +1068,80 @@ int net_tcp_accept(NETSOCKET sock, NETSOCKET *new_sock, NETADDR *a) socklen_t sockaddr_len; struct sockaddr addr; + *new_sock = invalid_socket; + sockaddr_len = sizeof(addr); - s = accept(sock, &addr, &sockaddr_len); + if(sock.ipv4sock >= 0) + { + s = accept(sock.ipv4sock, &addr, &sockaddr_len); + + if (s != -1) + { + sockaddr_to_netaddr(&addr, a); + new_sock->type = NETTYPE_IPV4; + new_sock->ipv4sock = s; + return s; + } + } - if (s != -1) + if(sock.ipv6sock >= 0) { - sockaddr_to_netaddr(&addr, a); - *new_sock = s; + s = accept(sock.ipv6sock, &addr, &sockaddr_len); + + if (s != -1) + { + sockaddr_to_netaddr(&addr, a); + new_sock->type = NETTYPE_IPV6; + new_sock->ipv6sock = s; + return s; + } } - return s; + + return 0; } int net_tcp_connect(NETSOCKET sock, const NETADDR *a) { - struct sockaddr addr; - - netaddr_to_sockaddr(a, &addr); - return connect(sock, &addr, sizeof(addr)); + /*struct sockaddr addr; + netaddr_to_sockaddr(a, &addr); + return connect(sock, &addr, sizeof(addr)); + */ + return 0; } int net_tcp_connect_non_blocking(NETSOCKET sock, const NETADDR *a) { struct sockaddr addr; - int res; + int res = 0; + /* netaddr_to_sockaddr(a, &addr); net_tcp_set_non_blocking(sock); res = connect(sock, &addr, sizeof(addr)); net_tcp_set_blocking(sock); + */ return res; } int net_tcp_send(NETSOCKET sock, const void *data, int size) { - int d; - d = send((int)sock, (const char*)data, size, 0); - return d; + int bytes = 0; + /* bytes = send((int)sock, (const char*)data, size, 0); */ + return bytes; } int net_tcp_recv(NETSOCKET sock, void *data, int maxsize) { - int bytes; - bytes = recv((int)sock, (char*)data, maxsize, 0); - return bytes; + int bytes = 0; + /* bytes = recv((int)sock, (char*)data, maxsize, 0); */ + return bytes; } int net_tcp_close(NETSOCKET sock) { -#if defined(CONF_FAMILY_WINDOWS) - closesocket(sock); -#else - close((int)sock); -#endif - return 0; + return priv_net_close_all_sockets(sock); } int net_errno() @@ -1077,17 +1376,34 @@ int net_socket_read_wait(NETSOCKET sock, int time) { struct timeval tv; fd_set readfds; + int sockid; tv.tv_sec = 0; tv.tv_usec = 1000*time; + sockid = 0; FD_ZERO(&readfds); - FD_SET(sock, &readfds); + if(sock.ipv4sock >= 0) + { + FD_SET(sock.ipv4sock, &readfds); + sockid = sock.ipv4sock; + } + if(sock.ipv6sock >= 0) + { + FD_SET(sock.ipv6sock, &readfds); + if(sock.ipv6sock > sockid) + sockid = sock.ipv6sock; + } /* don't care about writefds and exceptfds */ - select(sock+1, &readfds, NULL, NULL, &tv); - if(FD_ISSET(sock, &readfds)) - return 1; + select(sockid+1, &readfds, NULL, NULL, &tv); + + if(sock.ipv4sock >= 0 && FD_ISSET(sock.ipv4sock, &readfds)) + return 1; + + if(sock.ipv6sock >= 0 && FD_ISSET(sock.ipv6sock, &readfds)) + return 1; + return 0; } diff --git a/src/base/system.h b/src/base/system.h index ed46cef7..fea9e452 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -418,15 +418,22 @@ int64 time_freq(); unsigned time_timestamp(); /* Group: Network General */ -typedef int NETSOCKET; +typedef struct +{ + int type; + int ipv4sock; + int ipv6sock; +} NETSOCKET; + enum { - NETSOCKET_INVALID = -1, + NETADDR_MAXSTRSIZE = 1+(8*4+7)+1+1+5+1, // [XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX]:XXXXX NETTYPE_INVALID = 0, NETTYPE_IPV4 = 1, NETTYPE_IPV6 = 2, - NETTYPE_ALL = ~0 + NETTYPE_LINK_BROADCAST = 4, + NETTYPE_ALL = NETTYPE_IPV4|NETTYPE_IPV6 }; typedef struct diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 198f5f1a..a39bfb5b 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -692,20 +692,8 @@ void CClient::Connect(const char *pAddress) m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf); ServerInfoRequest(); - str_copy(aBuf, m_aServerAddressStr, sizeof(aBuf)); - for(int k = 0; aBuf[k]; k++) - { - if(aBuf[k] == ':') - { - Port = str_toint(aBuf+k+1); - aBuf[k] = 0; - break; - } - } - - // TODO: IPv6 support - if(net_host_lookup(aBuf, &m_ServerAddress, NETTYPE_IPV4) != 0) + if(net_host_lookup(m_aServerAddressStr, &m_ServerAddress, NETTYPE_ALL) != 0) { char aBufMsg[256]; str_format(aBufMsg, sizeof(aBufMsg), "could not find the address of %s, connecting to localhost", aBuf); @@ -714,7 +702,8 @@ void CClient::Connect(const char *pAddress) } m_RconAuthed = 0; - m_ServerAddress.port = Port; + if(m_ServerAddress.port == 0) + m_ServerAddress.port = Port; m_NetClient.Connect(&m_ServerAddress); SetState(IClient::STATE_CONNECTING); @@ -1119,9 +1108,7 @@ void CClient::ProcessConnlessPacket(CNetChunk *pPacket) Info.m_NumPlayers < 0 || Info.m_NumPlayers > Info.m_NumClients || Info.m_MaxPlayers < 0 || Info.m_MaxPlayers > Info.m_MaxClients) return; - str_format(Info.m_aAddress, sizeof(Info.m_aAddress), "%d.%d.%d.%d:%d", - pPacket->m_Address.ip[0], pPacket->m_Address.ip[1], pPacket->m_Address.ip[2], - pPacket->m_Address.ip[3], pPacket->m_Address.port); + net_addr_str(&pPacket->m_Address, Info.m_aAddress, sizeof(Info.m_aAddress)); for(int i = 0; i < Info.m_NumClients; i++) { @@ -1868,7 +1855,12 @@ void CClient::Run() { NETADDR BindAddr; mem_zero(&BindAddr, sizeof(BindAddr)); - m_NetClient.Open(BindAddr, 0); + BindAddr.type = NETTYPE_ALL; + if(!m_NetClient.Open(BindAddr, 0)) + { + dbg_msg("client", "couldn't start network"); + return; + } } // connect to the server if wanted diff --git a/src/engine/client/serverbrowser.cpp b/src/engine/client/serverbrowser.cpp index d4efe975..55d25f8a 100644 --- a/src/engine/client/serverbrowser.cpp +++ b/src/engine/client/serverbrowser.cpp @@ -492,12 +492,10 @@ void CServerBrowser::Refresh(int Type) mem_copy(Buffer, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO)); Buffer[sizeof(SERVERBROWSE_GETINFO)] = m_CurrentToken; + /* do the broadcast version */ Packet.m_ClientID = -1; mem_zero(&Packet, sizeof(Packet)); - Packet.m_Address.ip[0] = 255; - Packet.m_Address.ip[1] = 255; - Packet.m_Address.ip[2] = 255; - Packet.m_Address.ip[3] = 255; + Packet.m_Address.type = NETTYPE_ALL|NETTYPE_LINK_BROADCAST; Packet.m_Flags = NETSENDFLAG_CONNLESS; Packet.m_DataSize = sizeof(Buffer); Packet.m_pData = Buffer; diff --git a/src/engine/server.h b/src/engine/server.h index 7e11d865..c8e55110 100644 --- a/src/engine/server.h +++ b/src/engine/server.h @@ -30,7 +30,7 @@ public: virtual int ClientCountry(int ClientID) = 0; virtual bool ClientIngame(int ClientID) = 0; virtual int GetClientInfo(int ClientID, CClientInfo *pInfo) = 0; - virtual void GetClientIP(int ClientID, char *pIPString, int Size) = 0; + virtual void GetClientAddr(int ClientID, char *pAddrStr, int Size) = 0; virtual int *LatestInput(int ClientID, int *pSize) = 0; virtual int SendMsg(CMsgPacker *pMsg, int Flags, int ClientID) = 0; diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index c3ba583b..f1d2e6e1 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -333,12 +333,13 @@ int CServer::GetClientInfo(int ClientID, CClientInfo *pInfo) return 0; } -void CServer::GetClientIP(int ClientID, char *pIPString, int Size) +void CServer::GetClientAddr(int ClientID, char *pAddrStr, int Size) { if(ClientID >= 0 && ClientID < MAX_CLIENTS && m_aClients[ClientID].m_State == CClient::STATE_INGAME) { NETADDR Addr = m_NetServer.ClientAddr(ClientID); - str_format(pIPString, Size, "%d.%d.%d.%d", Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3]); + Addr.port = 0; + net_addr_str(&Addr, pAddrStr, Size); } } @@ -587,12 +588,10 @@ int CServer::DelClientCallback(int ClientID, const char *pReason, void *pUser) CServer *pThis = (CServer *)pUser; NETADDR Addr = pThis->m_NetServer.ClientAddr(ClientID); + char aAddrStr[NETADDR_MAXSTRSIZE]; + net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "client dropped. cid=%d ip=%d.%d.%d.%d reason=\"%s\"", - ClientID, - Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3], - pReason - ); + str_format(aBuf, sizeof(aBuf), "client dropped. cid=%d addr=%s reason='%s'", ClientID, aAddrStr, pReason); pThis->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf); // notify the mod about the drop @@ -732,10 +731,11 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) if(m_aClients[ClientID].m_State == CClient::STATE_CONNECTING) { Addr = m_NetServer.ClientAddr(ClientID); + char aAddrStr[NETADDR_MAXSTRSIZE]; + net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "player is ready. ClientID=%x ip=%d.%d.%d.%d", - ClientID, Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3]); + str_format(aBuf, sizeof(aBuf), "player is ready. ClientID=%x addr=%s", ClientID, aAddrStr); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf); m_aClients[ClientID].m_State = CClient::STATE_READY; GameServer()->OnClientConnected(ClientID); @@ -747,10 +747,11 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) if(m_aClients[ClientID].m_State == CClient::STATE_READY && GameServer()->IsClientReady(ClientID)) { Addr = m_NetServer.ClientAddr(ClientID); + char aAddrStr[NETADDR_MAXSTRSIZE]; + net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "player has entered the game. ClientID=%x ip=%d.%d.%d.%d", - ClientID, Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3]); + str_format(aBuf, sizeof(aBuf), "player has entered the game. ClientID=%x addr=%s", ClientID, aAddrStr); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); m_aClients[ClientID].m_State = CClient::STATE_INGAME; GameServer()->OnClientEnter(ClientID); @@ -1102,9 +1103,8 @@ int CServer::Run() } // start server - // TODO: IPv6 support NETADDR BindAddr; - if(g_Config.m_SvBindaddr[0] && net_host_lookup(g_Config.m_SvBindaddr, &BindAddr, NETTYPE_IPV4) == 0) + if(g_Config.m_SvBindaddr[0] && net_host_lookup(g_Config.m_SvBindaddr, &BindAddr, NETTYPE_ALL) == 0) { // sweet! BindAddr.port = g_Config.m_SvPort; @@ -1112,6 +1112,7 @@ int CServer::Run() else { mem_zero(&BindAddr, sizeof(BindAddr)); + BindAddr.type = NETTYPE_ALL; BindAddr.port = g_Config.m_SvPort; } @@ -1342,8 +1343,11 @@ void CServer::ConUnban(IConsole::IResult *pResult, void *pUser) if(net_addr_from_str(&Addr, pStr) == 0 && !pServer->BanRemove(Addr)) { + char aAddrStr[NETADDR_MAXSTRSIZE]; + net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); + char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "unbanned %d.%d.%d.%d", Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3]); + str_format(aBuf, sizeof(aBuf), "unbanned %s", aAddrStr); pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); } else if(StrAllnum(pStr)) @@ -1354,8 +1358,11 @@ void CServer::ConUnban(IConsole::IResult *pResult, void *pUser) pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "invalid ban index"); else if(!pServer->BanRemove(Info.m_Addr)) { + char aAddrStr[NETADDR_MAXSTRSIZE]; + net_addr_str(&Info.m_Addr, aAddrStr, sizeof(aAddrStr)); + char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "unbanned %d.%d.%d.%d", Info.m_Addr.ip[0], Info.m_Addr.ip[1], Info.m_Addr.ip[2], Info.m_Addr.ip[3]); + str_format(aBuf, sizeof(aBuf), "unbanned %s", aAddrStr); pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); } } @@ -1367,6 +1374,7 @@ void CServer::ConBans(IConsole::IResult *pResult, void *pUser) { unsigned Now = time_timestamp(); char aBuf[1024]; + char aAddrStr[NETADDR_MAXSTRSIZE]; CServer* pServer = (CServer *)pUser; int Num = pServer->m_NetServer.BanNum(); @@ -1375,15 +1383,16 @@ void CServer::ConBans(IConsole::IResult *pResult, void *pUser) CNetServer::CBanInfo Info; pServer->m_NetServer.BanGet(i, &Info); NETADDR Addr = Info.m_Addr; + net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); if(Info.m_Expires == -1) { - str_format(aBuf, sizeof(aBuf), "#%d %d.%d.%d.%d for life", i, Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3]); + str_format(aBuf, sizeof(aBuf), "#%s for life", i, aAddrStr); } else { unsigned t = Info.m_Expires - Now; - str_format(aBuf, sizeof(aBuf), "#%d %d.%d.%d.%d for %d minutes and %d seconds", i, Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3], t/60, t%60); + str_format(aBuf, sizeof(aBuf), "#%s for %d minutes and %d seconds", i, aAddrStr, t/60, t%60); } pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf); } @@ -1396,6 +1405,7 @@ void CServer::ConStatus(IConsole::IResult *pResult, void *pUser) int i; NETADDR Addr; char aBuf[1024]; + char aAddrStr[NETADDR_MAXSTRSIZE]; CServer* pServer = (CServer *)pUser; for(i = 0; i < MAX_CLIENTS; i++) @@ -1403,13 +1413,12 @@ void CServer::ConStatus(IConsole::IResult *pResult, void *pUser) if(pServer->m_aClients[i].m_State != CClient::STATE_EMPTY) { Addr = pServer->m_NetServer.ClientAddr(i); + net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); if(pServer->m_aClients[i].m_State == CClient::STATE_INGAME) - str_format(aBuf, sizeof(aBuf), "id=%d addr=%d.%d.%d.%d:%d name='%s' score=%d", - i, Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3], Addr.port, + str_format(aBuf, sizeof(aBuf), "id=%d addr=%s name='%s' score=%d", i, aAddrStr, pServer->m_aClients[i].m_aName, pServer->m_aClients[i].m_Score); else - str_format(aBuf, sizeof(aBuf), "id=%d addr=%d.%d.%d.%d:%d connecting", - i, Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3], Addr.port); + str_format(aBuf, sizeof(aBuf), "id=%d addr=%s connecting", i, aAddrStr); pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf); } } diff --git a/src/engine/server/server.h b/src/engine/server/server.h index 848b485a..00c1c648 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -141,7 +141,7 @@ public: bool IsAuthed(int ClientID); int GetClientInfo(int ClientID, CClientInfo *pInfo); - void GetClientIP(int ClientID, char *pIPString, int Size); + void GetClientAddr(int ClientID, char *pAddrStr, int Size); const char *ClientName(int ClientID); const char *ClientClan(int ClientID); int ClientCountry(int ClientID); diff --git a/src/engine/serverbrowser.h b/src/engine/serverbrowser.h index f0310421..1ac22056 100644 --- a/src/engine/serverbrowser.h +++ b/src/engine/serverbrowser.h @@ -44,7 +44,7 @@ public: char m_aName[64]; char m_aMap[32]; char m_aVersion[32]; - char m_aAddress[24]; + char m_aAddress[NETADDR_MAXSTRSIZE]; CClient m_aClients[MAX_CLIENTS]; }; diff --git a/src/engine/shared/network_client.cpp b/src/engine/shared/network_client.cpp index d3adfd20..82a09474 100644 --- a/src/engine/shared/network_client.cpp +++ b/src/engine/shared/network_client.cpp @@ -5,11 +5,17 @@ bool CNetClient::Open(NETADDR BindAddr, int Flags) { + // open socket + NETSOCKET Socket; + Socket = net_udp_create(BindAddr); + if(!Socket.type) + return false; + // clean it mem_zero(this, sizeof(*this)); - // open socket - m_Socket = net_udp_create(BindAddr); + // init + m_Socket = Socket; m_Connection.Init(m_Socket); return true; } diff --git a/src/engine/shared/network_server.cpp b/src/engine/shared/network_server.cpp index 3b5ef317..88aac789 100644 --- a/src/engine/shared/network_server.cpp +++ b/src/engine/shared/network_server.cpp @@ -33,7 +33,7 @@ bool CNetServer::Open(NETADDR BindAddr, int MaxClients, int MaxClientsPerIP, int // open socket m_Socket = net_udp_create(BindAddr); - if(m_Socket == NETSOCKET_INVALID) + if(!m_Socket.type) return false; // clamp clients diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 6a7cc1f9..d008787a 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -414,10 +414,10 @@ void CGameContext::OnTick() if(m_VoteUpdate) { // count votes - char aaBuf[MAX_CLIENTS][64] = {{0}}; + char aaBuf[MAX_CLIENTS][NETADDR_MAXSTRSIZE] = {{0}}; for(int i = 0; i < MAX_CLIENTS; i++) if(m_apPlayers[i]) - Server()->GetClientIP(i, aaBuf[i], 64); + Server()->GetClientAddr(i, aaBuf[i], NETADDR_MAXSTRSIZE); bool aVoteChecked[MAX_CLIENTS] = {0}; for(int i = 0; i < MAX_CLIENTS; i++) { @@ -709,9 +709,10 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) str_format(aCmd, sizeof(aCmd), "kick %d Kicked by vote", KickID); else { - char aBuf[64] = {0}; - Server()->GetClientIP(KickID, aBuf, sizeof(aBuf)); - str_format(aCmd, sizeof(aCmd), "ban %s %d Banned by vote", aBuf, g_Config.m_SvVoteKickBantime); + char aAddrStr[NETADDR_MAXSTRSIZE] = {0}; + Server()->GetClientAddr(KickID, aAddrStr, sizeof(aAddrStr)); + str_format(aCmd, sizeof(aCmd), "ban %s %d Banned by vote", aAddrStr, g_Config.m_SvVoteKickBantime); + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aCmd); } } else if(str_comp_nocase(pMsg->m_Type, "spectate") == 0) @@ -1229,9 +1230,9 @@ void CGameContext::ConForceVote(IConsole::IResult *pResult, void *pUserData) } else { - char aIP[64] = {0}; - pSelf->Server()->GetClientIP(KickID, aIP, sizeof(aIP)); - str_format(aBuf, sizeof(aBuf), "ban %s %d %s", aIP, g_Config.m_SvVoteKickBantime, pReason); + char aAddrStr[NETADDR_MAXSTRSIZE] = {0}; + pSelf->Server()->GetClientAddr(KickID, aAddrStr, sizeof(aAddrStr)); + str_format(aBuf, sizeof(aBuf), "ban %s %d %s", aAddrStr, g_Config.m_SvVoteKickBantime, pReason); pSelf->Console()->ExecuteLine(aBuf); } } |