-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back! *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment *
-* Holger Schemel *
-* Detmolder Strasse 189 *
-* 33604 Bielefeld *
-* Germany *
-* e-mail: info@artsoft.org *
-*----------------------------------------------------------*
-* netserv.c *
-***********************************************************/
-
-#include "libgame/platform.h"
-
-#if defined(NETWORK_AVALIABLE)
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+// Holger Schemel
+// info@artsoft.org
+// http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// netserv.c
+// ============================================================================
#include <fcntl.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
-#if defined(TARGET_SDL)
-#include "main.h"
-#else
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <sys/select.h> /* apparently needed for OS/2 port */
-#endif
-
#include "libgame/libgame.h"
#include "netserv.h"
+#include "main.h"
+
static int clients = 0;
static int onceonly = 0;
struct NetworkServerPlayerInfo
{
-#if defined(TARGET_SDL)
TCPsocket fd;
-#else
- int fd;
-#endif
-
char player_name[16];
unsigned char number;
struct NetworkServerPlayerInfo *next;
#define NEXT(player) ((player)->next ? (player)->next : first_player)
-#if defined(TARGET_SDL)
/* 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 */
-#else
-static struct sockaddr_in saddr;
-static int lfd; /* listening socket */
-static fd_set fds; /* socket set */
-static int tcp = -1;
-#endif
static unsigned char realbuffer[512], *buffer = realbuffer + 4;
{
if (player->nwrite)
{
-#if defined(TARGET_SDL)
SDLNet_TCP_Send(player->fd, player->writbuffer, player->nwrite);
-#else
- if (write(player->fd, player->writbuffer, player->nwrite) == -1)
- Error(ERR_WARN, "write() failed; %s", strerror(errno));
-#endif
+
player->nwrite = 0;
}
}
}
}
-#if defined(TARGET_SDL)
SDLNet_TCP_DelSocket(fds, player->fd);
SDLNet_TCP_Close(player->fd);
-#else
- close(player->fd);
-#endif
if (player->introduced)
{
}
}
-#if defined(TARGET_SDL)
static void AddPlayer(TCPsocket fd)
-#else
-static void AddPlayer(int fd)
-#endif
{
struct NetworkServerPlayerInfo *player, *v;
unsigned char nxn;
player->action = 0;
player->action_received = FALSE;
-#if defined(TARGET_SDL)
SDLNet_TCP_AddSocket(fds, fd);
-#endif
first_player = player;
}
player->number = nxn;
-#if !defined(TARGET_SDL)
- if (options.verbose)
- Error(ERR_NETWORK_SERVER, "client %d connecting from %s",
- nxn, inet_ntoa(saddr.sin_addr));
-#endif
clients++;
buffer[0] = 0;
broadcast(NULL, 6 + last_client_nr, 0);
-#if 0
- Error(ERR_NETWORK_SERVER, "sending ServerFrameCounter value %d",
- ServerFrameCounter);
-#endif
-
ServerFrameCounter++;
}
-#if defined(TARGET_SDL)
+void ExitNetworkServer(int exit_value)
+{
+ Error(ERR_NETWORK_SERVER, "exiting network server");
+
+ exit(exit_value);
+}
+
/* the following is not used for a standalone server;
the pointer points to an integer containing the port-number */
int NetworkServerThread(void *ptr)
/* should never be reached */
return 0;
}
-#endif
void NetworkServer(int port, int serveronly)
{
- int sl;
struct NetworkServerPlayerInfo *player;
int r;
unsigned int len;
-#if defined(TARGET_SDL)
IPaddress ip;
-#else
- int i, on;
- int is_daemon = 0;
- struct protoent *tcpproto;
- struct timeval tv;
- int mfd;
-#endif
#if defined(PLATFORM_UNIX) && !defined(PLATFORM_NEXT)
struct sigaction sact;
if (port == 0)
port = DEFAULT_SERVER_PORT;
+ // if only running the network server, exit on Ctrl-C
+ if (serveronly)
+ signal(SIGINT, ExitNetworkServer);
+
if (!serveronly)
onceonly = 1;
-#if !defined(TARGET_SDL)
- if ((tcpproto = getprotobyname("tcp")) != NULL)
- tcp = tcpproto->p_proto;
-#endif
-
#if defined(PLATFORM_UNIX)
#if defined(PLATFORM_NEXT)
signal(SIGPIPE, SIG_IGN);
#endif
#endif
-#if defined(TARGET_SDL)
-
- /* assume that SDL is already initialized */
-#if 0
- if (SDLNet_Init() == -1)
- Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_Init() failed");
- atexit(SDLNet_Quit);
-#endif
-
if (SDLNet_ResolveHost(&ip, NULL, port) == -1)
- Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_ResolveHost() failed");
-
- lfd = SDLNet_TCP_Open(&ip);
- if (!lfd)
- Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_Open() failed");
+ Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_ResolveHost() failed: %s",
+ SDLNet_GetError());
- fds = SDLNet_AllocSocketSet(MAX_PLAYERS+1);
- SDLNet_TCP_AddSocket(fds, lfd);
-
-#else
+ if ((fds = SDLNet_AllocSocketSet(MAX_PLAYERS + 1 + 1)) == NULL)
+ Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_AllocSocketSet() failed: %s"),
+ SDLNet_GetError();
- if ((lfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
- Error(ERR_EXIT_NETWORK_SERVER, "socket() failed");
+ if ((lfd = SDLNet_TCP_Open(&ip)) == NULL)
+ Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_Open() failed: %s"),
+ SDLNet_GetError();
- saddr.sin_family = AF_INET;
- saddr.sin_addr.s_addr = htonl(INADDR_ANY);
- saddr.sin_port = htons(port);
+ if (SDLNet_TCP_AddSocket(fds, lfd) == -1)
+ Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_AddSocket() failed: %s"),
+ SDLNet_GetError();
- on = 1;
+ if ((udp = SDLNet_UDP_Open(port)) == NULL)
+ Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_UDP_Open() failed: %s",
+ SDLNet_GetError());
- setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(int));
- if (bind(lfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
- Error(ERR_EXIT_NETWORK_SERVER, "bind() failed");
-
- listen(lfd, 5);
-#endif
-
-#if !defined(TARGET_SDL)
- if (is_daemon)
- {
- /* become a daemon, breaking all ties with the controlling terminal */
- options.verbose = FALSE;
- for (i = 0; i < 255; i++)
- {
- if (i != lfd)
- close(i);
- }
-
- if (fork())
- exit(0);
- setsid();
- if (fork())
- exit(0);
- if (chdir("/") == -1)
- Error(ERR_WARN, "chdir() failed; %s", strerror(errno));
-
- /* open a fake stdin, stdout, stderr, just in case */
- open("/dev/null", O_RDONLY);
- open("/dev/null", O_WRONLY);
- open("/dev/null", O_WRONLY);
- }
-#endif
+ if (SDLNet_UDP_AddSocket(fds, udp) == -1)
+ Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_AddSocket() failed: %s"),
+ SDLNet_GetError();
if (options.verbose)
{
for (player = first_player; player; player = player->next)
flushuser(player);
-#if defined(TARGET_SDL)
- if ((sl = SDLNet_CheckSockets(fds, 500000)) < 1)
- {
- Error(ERR_NETWORK_SERVER, "SDLNet_CheckSockets failed: %s",
- SDLNet_GetError());
- perror("SDLNet_CheckSockets");
- }
-
-#else
-
- FD_ZERO(&fds);
- mfd = lfd;
- player = first_player;
- while (player)
- {
- FD_SET(player->fd, &fds);
- if (player->fd > mfd)
- mfd = player->fd;
- player = player->next;
- }
- FD_SET(lfd, &fds);
- tv.tv_sec = 0;
- tv.tv_usec = 500000;
- if ((sl = select(mfd + 1, &fds, NULL, NULL, &tv)) < 0)
- {
- if (errno != EINTR)
- Error(ERR_EXIT_NETWORK_SERVER, "select() failed");
- else
- continue;
- }
-#endif
-
- if (sl < 0)
- continue;
-
- if (sl == 0)
+ // wait for 100 ms for activity on open network sockets
+ if (SDLNet_CheckSockets(fds, 100) < 1)
continue;
- /* accept incoming connections */
-#if defined(TARGET_SDL)
+ /* accept incoming TCP connections */
if (SDLNet_SocketReady(lfd))
{
+ Error(ERR_DEBUG, "got TCP packet");
+
TCPsocket newsock;
newsock = SDLNet_TCP_Accept(lfd);
AddPlayer(newsock);
}
-#else
-
- if (FD_ISSET(lfd, &fds))
+ /* accept incoming UDP packets */
+ if (SDLNet_SocketReady(udp))
{
- int newfd;
- socklen_t slen;
+ Error(ERR_DEBUG, "got UDP packet");
+
+ static UDPpacket packet;
+
+ int num_packets = SDLNet_UDP_Recv(udp, &packet);
- slen = sizeof(saddr);
- newfd = accept(lfd, (struct sockaddr *)&saddr, &slen);
- if (newfd < 0)
+ if (num_packets == 1)
{
- if (errno != EINTR)
- Error(ERR_EXIT_NETWORK_SERVER, "accept() failed");
+ // bounce packet
+ SDLNet_UDP_Send(udp, -1, &packet);
}
- else
- {
- if (tcp != -1)
- {
- on = 1;
- setsockopt(newfd, tcp, TCP_NODELAY, (char *)&on, sizeof(int));
- }
- AddPlayer(newfd);
- }
- continue;
}
-#endif
player = first_player;
- do
+ while (player && !interrupt)
{
-#if defined(TARGET_SDL)
if (SDLNet_SocketReady(player->fd))
-#else
- if (FD_ISSET(player->fd, &fds))
-#endif
{
-#if defined(TARGET_SDL)
/* read only 1 byte, because SDLNet blocks when we want more than is
in the buffer */
r = SDLNet_TCP_Recv(player->fd, player->readbuffer + player->nread, 1);
-#else
- r = read(player->fd, player->readbuffer + player->nread,
- MAX_BUFFER_SIZE - player->nread);
-#endif
if (r <= 0)
{
if (player && !interrupt)
player = player->next;
}
- while (player && !interrupt);
}
}
-
-#endif /* NETWORK_AVALIABLE */