From bb8ea93cf34a36020e63e5d4ef4263eeb49fd17c Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Fri, 1 Jun 2018 18:06:38 +0200 Subject: [PATCH] added UDP broadcast to auto-detect network server in local network --- src/netserv.c | 36 +++++++++++++++++++---- src/network.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 109 insertions(+), 8 deletions(-) diff --git a/src/netserv.c b/src/netserv.c index 547c2c91..02a014fd 100644 --- a/src/netserv.c +++ b/src/netserv.c @@ -47,7 +47,8 @@ static struct NetworkServerPlayerInfo *first_player = NULL; #define NEXT(player) ((player)->next ? (player)->next : first_player) /* TODO: peer address */ -static TCPsocket lfd; /* listening socket */ +static TCPsocket lfd; /* listening TCP socket */ +static UDPsocket udp; /* listening UDP socket */ static SDLNet_SocketSet fds; /* socket set */ static unsigned char realbuffer[512], *buffer = realbuffer + 4; @@ -486,7 +487,7 @@ void NetworkServer(int port, int serveronly) Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_ResolveHost() failed: %s", SDLNet_GetError()); - if ((fds = SDLNet_AllocSocketSet(MAX_PLAYERS + 1)) == NULL) + if ((fds = SDLNet_AllocSocketSet(MAX_PLAYERS + 1 + 1)) == NULL) Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_AllocSocketSet() failed: %s"), SDLNet_GetError(); @@ -498,6 +499,14 @@ void NetworkServer(int port, int serveronly) Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_AddSocket() failed: %s"), SDLNet_GetError(); + if ((udp = SDLNet_UDP_Open(port)) == NULL) + Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_UDP_Open() failed: %s", + SDLNet_GetError()); + + if (SDLNet_UDP_AddSocket(fds, udp) == -1) + Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_AddSocket() failed: %s"), + SDLNet_GetError(); + if (options.verbose) { Error(ERR_NETWORK_SERVER, "started up, listening on port %d", port); @@ -516,9 +525,11 @@ void NetworkServer(int port, int serveronly) if (SDLNet_CheckSockets(fds, 100) < 1) continue; - /* accept incoming connections */ + /* accept incoming TCP connections */ if (SDLNet_SocketReady(lfd)) { + Error(ERR_DEBUG, "got TCP packet"); + TCPsocket newsock; newsock = SDLNet_TCP_Accept(lfd); @@ -527,9 +538,25 @@ void NetworkServer(int port, int serveronly) AddPlayer(newsock); } + /* accept incoming UDP packets */ + if (SDLNet_SocketReady(udp)) + { + Error(ERR_DEBUG, "got UDP packet"); + + static UDPpacket packet; + + int num_packets = SDLNet_UDP_Recv(udp, &packet); + + if (num_packets == 1) + { + // bounce packet + SDLNet_UDP_Send(udp, -1, &packet); + } + } + player = first_player; - do + while (player && !interrupt) { if (SDLNet_SocketReady(player->fd)) { @@ -628,7 +655,6 @@ void NetworkServer(int port, int serveronly) if (player && !interrupt) player = player->next; } - while (player && !interrupt); } } diff --git a/src/network.c b/src/network.c index b51402eb..1c9e0b0d 100644 --- a/src/network.c +++ b/src/network.c @@ -44,7 +44,8 @@ static struct NetworkClientPlayerInfo first_player = /* server stuff */ -static TCPsocket sfd; /* server socket */ +static TCPsocket sfd; /* TCP server socket */ +static UDPsocket udp; /* UDP server socket */ static SDLNet_SocketSet rfds; /* socket set */ static byte realbuffer[512]; @@ -121,25 +122,99 @@ static void StartNetworkServer(int port) boolean ConnectToServer(char *hostname, int port) { IPaddress ip; + int server_host = 0; int i; if (port == 0) port = DEFAULT_SERVER_PORT; + if (hostname == NULL) + { + // if no hostname given, try to auto-detect network server in local network + // by doing a UDP broadcast on the network server port and wait for answer + + SDLNet_SocketSet udp_socket_set = SDLNet_AllocSocketSet(1); + if (!udp_socket_set) + Error(ERR_EXIT, "SDLNet_AllocSocketSet() failed: %s"), SDLNet_GetError(); + + udp = SDLNet_UDP_Open(0); + if(!udp) + Error(ERR_EXIT, "SDLNet_UDP_Open() failed: %s", SDLNet_GetError()); + + if (SDLNet_UDP_AddSocket(udp_socket_set, udp) == -1) + Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_AddSocket() failed: %s"), + SDLNet_GetError(); + + char *data_ptr = "network server UDB broadcast"; + int data_len = strlen(data_ptr) + 1; + IPaddress ip_address; + + SDLNet_Write32(0xffffffff, &ip_address.host); /* 255.255.255.255 */ + SDLNet_Write16(port, &ip_address.port); + + UDPpacket packet = + { + -1, + (Uint8 *)data_ptr, + data_len, + data_len, + 0, + ip_address + }; + + SDLNet_UDP_Send(udp, -1, &packet); + + Error(ERR_DEBUG, "doing UDP broadcast for local network server ..."); + + if (SDLNet_CheckSockets(udp_socket_set, 1000) == 1) + { + int num_packets = SDLNet_UDP_Recv(udp, &packet); + + if (num_packets == 1) + { + Error(ERR_DEBUG, "network server found"); + + server_host = SDLNet_Read32(&packet.address.host); + } + else + { + Error(ERR_DEBUG, "no answer from network server"); + } + } + else + { + Error(ERR_DEBUG, "no network server found"); + } + } + rfds = SDLNet_AllocSocketSet(1); if (hostname) { SDLNet_ResolveHost(&ip, hostname, port); + if (ip.host == INADDR_NONE) Error(ERR_EXIT, "cannot locate host '%s'", hostname); + else + server_host = SDLNet_Read32(&ip.host); } else { - SDLNet_Write32(0x7f000001, &ip.host); /* 127.0.0.1 */ - SDLNet_Write16(port, &ip.port); + // if no hostname was given and no network server was auto-detected in the + // local network, try to connect to a network server at the local host + if (server_host == 0) + server_host = 0x7f000001; /* 127.0.0.1 */ + + SDLNet_Write32(server_host, &ip.host); + SDLNet_Write16(port, &ip.port); } + Error(ERR_DEBUG, "trying to connect to network server at %d.%d.%d.%d ...", + (server_host >> 24) & 0xff, + (server_host >> 16) & 0xff, + (server_host >> 8) & 0xff, + (server_host >> 0) & 0xff); + sfd = SDLNet_TCP_Open(&ip); if (sfd) -- 2.34.1