-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back! *
-*----------------------------------------------------------*
-* (c) 1995-98 Artsoft Entertainment *
-* Holger Schemel *
-* Oststrasse 11a *
-* 33604 Bielefeld *
-* phone: ++49 +521 290471 *
-* email: aeglos@valinor.owl.de *
-*----------------------------------------------------------*
-* network.c *
-***********************************************************/
-
-#ifndef MSDOS
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+// Holger Schemel
+// info@artsoft.org
+// http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// netserv.c
+// ============================================================================
+
+#include "libgame/platform.h"
+
+#if defined(NETWORK_AVALIABLE)
#include <fcntl.h>
#include <sys/time.h>
#include <signal.h>
-#include <sys/socket.h>
#include <errno.h>
-#include <string.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
+
+#include "main.h"
+
+#include "libgame/libgame.h"
#include "netserv.h"
-#include "misc.h"
static int clients = 0;
static int onceonly = 0;
struct NetworkServerPlayerInfo
{
- int fd;
+ TCPsocket fd;
char player_name[16];
unsigned char number;
struct NetworkServerPlayerInfo *next;
#define NEXT(player) ((player)->next ? (player)->next : first_player)
-static struct sockaddr_in saddr;
-static int lfd;
+/* TODO: peer address */
+static TCPsocket lfd; /* listening socket */
+static SDLNet_SocketSet fds; /* socket set */
+
static unsigned char realbuffer[512], *buffer = realbuffer + 4;
static int interrupt;
-static int tcp = -1;
-
-static unsigned long ServerFrameCounter = 0;
-static fd_set fds;
+static unsigned int ServerFrameCounter = 0;
static void addtobuffer(struct NetworkServerPlayerInfo *player,
unsigned char *b, int len)
{
if (player->nwrite)
{
- write(player->fd, player->writbuffer, player->nwrite);
+ SDLNet_TCP_Send(player->fd, player->writbuffer, player->nwrite);
+
player->nwrite = 0;
}
}
realbuffer[0] = realbuffer[1] = realbuffer[2] = 0;
realbuffer[3] = (unsigned char)len;
- for (player=first_player; player; player=player->next)
- if (player != except && (player->active || !activeonly) && player->introduced)
+ for (player = first_player; player; player = player->next)
+ if (player != except && player->introduced &&
+ (player->active || !activeonly))
addtobuffer(player, realbuffer, 4 + len);
}
first_player = player->next;
else
{
- for (v=first_player; v; v=v->next)
+ for (v = first_player; v; v = v->next)
{
if (v->next && v->next == player)
{
}
}
}
- close(player->fd);
+
+ SDLNet_TCP_DelSocket(fds, player->fd);
+ SDLNet_TCP_Close(player->fd);
if (player->introduced)
{
}
}
-static void AddPlayer(int fd)
+static void AddPlayer(TCPsocket fd)
{
struct NetworkServerPlayerInfo *player, *v;
unsigned char nxn;
+ boolean again = TRUE;
player = checked_malloc(sizeof (struct NetworkServerPlayerInfo));
player->action = 0;
player->action_received = FALSE;
+ SDLNet_TCP_AddSocket(fds, fd);
+
first_player = player;
nxn = 1;
- again:
- v = player->next;
- while(v)
+ while (again)
{
- if (v->number == nxn)
+ again = FALSE;
+ v = player->next;
+
+ while (v)
{
- nxn++;
- goto again;
+ if (v->number == nxn)
+ {
+ nxn++;
+
+ again = TRUE;
+ break;
+ }
+ v = v->next;
}
- v = v->next;
}
player->number = nxn;
- if (options.verbose)
- Error(ERR_NETWORK_SERVER, "client %d connecting from %s",
- nxn, inet_ntoa(saddr.sin_addr));
clients++;
buffer[0] = 0;
Error(ERR_NETWORK_SERVER, "client %d (%s) wants to switch to # %d",
player->number, player->player_name, nr_wanted);
- for (v=first_player; v; v=v->next)
+ for (v = first_player; v; v = v->next)
{
if (v->number == nr_wanted)
{
Error(ERR_NETWORK_SERVER, "client %d (%s) switches to # %d",
player->number, player->player_name, nr_wanted);
else if (player->number == nr_wanted)
- Error(ERR_NETWORK_SERVER, "client %d (%s) still has # %d",
+ Error(ERR_NETWORK_SERVER, "client %d (%s) already has # %d",
player->number, player->player_name, nr_wanted);
else
Error(ERR_NETWORK_SERVER,
- "client %d (%s) cannot switch (client %d still exists)",
+ "client %d (%s) cannot switch (client %d already exists)",
player->number, player->player_name, nr_wanted);
}
len=16;
memcpy(player->player_name, &buffer[2], len-2);
player->player_name[len-2] = 0;
- for (i=0; i<len-2; i++)
+ for (i = 0; i < len - 2; i++)
{
if (player->player_name[i] < ' ' ||
((unsigned char)(player->player_name[i]) > 0x7e &&
if (!player->introduced)
{
- for (v=first_player; v; v=v->next)
+ for (v = first_player; v; v = v->next)
{
if (v != player && v->introduced)
{
if (options.verbose)
Error(ERR_NETWORK_SERVER,
- "client %d (%s) starts game [level %d from levedir %d (%s)]",
+ "client %d (%s) starts game [level %d from leveldir %d (%s)]",
player->number, player->player_name,
(buffer[2] << 8) + buffer[3],
(buffer[4] << 8) + buffer[5],
- &buffer[6]);
+ &buffer[10]);
- for (w=first_player; w; w=w->next)
+ for (w = first_player; w; w = w->next)
if (w->introduced)
w->active = 1;
/* reset frame counter */
ServerFrameCounter = 0;
+ Error(ERR_NETWORK_SERVER, "resetting ServerFrameCounter to 0");
+
/* reset player actions */
- for (v=first_player; v; v=v->next)
+ for (v = first_player; v; v = v->next)
{
v->action = 0;
v->action_received = FALSE;
static void Handle_OP_STOP_PLAYING(struct NetworkServerPlayerInfo *player)
{
+ int cause_for_stopping = buffer[2];
+
if (options.verbose)
- Error(ERR_NETWORK_SERVER, "client %d (%s) stops game",
- player->number, player->player_name);
- broadcast(NULL, 2, 0);
+ Error(ERR_NETWORK_SERVER, "client %d (%s) stops game [%d]",
+ player->number, player->player_name, cause_for_stopping);
+ broadcast(NULL, 3, 0);
}
-static void Handle_OP_MOVE_FIGURE(struct NetworkServerPlayerInfo *player)
+static void Handle_OP_MOVE_PLAYER(struct NetworkServerPlayerInfo *player)
{
struct NetworkServerPlayerInfo *v;
int last_client_nr = 0;
int i;
/* store player action */
- for (v=first_player; v; v=v->next)
+ for (v = first_player; v; v = v->next)
{
if (v->number == player->number)
{
}
/* check if server received action from each player */
- for (v=first_player; v; v=v->next)
+ for (v = first_player; v; v = v->next)
{
if (!v->action_received)
return;
}
/* initialize all player actions to zero */
- for (i=0; i<last_client_nr; i++)
+ for (i = 0; i < last_client_nr; i++)
buffer[6 + i] = 0;
/* broadcast actions of all players to all players */
- for (v=first_player; v; v=v->next)
+ for (v = first_player; v; v = v->next)
{
buffer[6 + v->number-1] = v->action;
v->action = 0;
ServerFrameCounter++;
}
+/* the following is not used for a standalone server;
+ the pointer points to an integer containing the port-number */
+int NetworkServerThread(void *ptr)
+{
+ NetworkServer(*((int *) ptr), 0);
+
+ /* should never be reached */
+ return 0;
+}
+
void NetworkServer(int port, int serveronly)
{
- int i, sl, on;
+ int sl;
struct NetworkServerPlayerInfo *player;
- int mfd;
int r;
unsigned int len;
- struct protoent *tcpproto;
- struct timeval tv;
- int is_daemon = 0;
+ IPaddress ip;
-#ifndef NeXT
+#if defined(PLATFORM_UNIX) && !defined(PLATFORM_NEXT)
struct sigaction sact;
#endif
if (!serveronly)
onceonly = 1;
- if ((tcpproto = getprotobyname("tcp")) != NULL)
- tcp = tcpproto->p_proto;
-
-#ifdef NeXT
+#if defined(PLATFORM_UNIX)
+#if defined(PLATFORM_NEXT)
signal(SIGPIPE, SIG_IGN);
#else
sact.sa_handler = SIG_IGN;
sigemptyset(&sact.sa_mask);
sact.sa_flags = 0;
sigaction(SIGPIPE, &sact, NULL);
+#endif
#endif
+ if (SDLNet_ResolveHost(&ip, NULL, port) == -1)
+ Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_ResolveHost() failed");
- if ((lfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
- Error(ERR_EXIT_NETWORK_SERVER, "socket() failed");
-
- saddr.sin_family = AF_INET;
- saddr.sin_addr.s_addr = htonl(INADDR_ANY);
- saddr.sin_port = htons(port);
-
- on = 1;
-
- 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);
-
- if (is_daemon)
- {
- /* become a daemon, breaking all ties with the controlling terminal */
- options.verbose = 0;
- for (i=0; i<255; i++)
- {
- if (i != lfd)
- close(i);
- }
+ lfd = SDLNet_TCP_Open(&ip);
+ if (!lfd)
+ Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_Open() failed");
- if (fork())
- exit(0);
- setsid();
- if (fork())
- exit(0);
- chdir("/");
-
- /* open a fake stdin, stdout, stderr, just in case */
- open("/dev/null", O_RDONLY);
- open("/dev/null", O_WRONLY);
- open("/dev/null", O_WRONLY);
- }
+ fds = SDLNet_AllocSocketSet(MAX_PLAYERS+1);
+ SDLNet_TCP_AddSocket(fds, lfd);
if (options.verbose)
{
PROTOCOL_VERSION_1, PROTOCOL_VERSION_2, PROTOCOL_VERSION_3);
}
- while(1)
+ while (1)
{
interrupt = 0;
- for (player=first_player; player; player=player->next)
+ for (player = first_player; player; player = player->next)
flushuser(player);
- FD_ZERO(&fds);
- mfd = lfd;
- player = first_player;
- while (player)
+ if ((sl = SDLNet_CheckSockets(fds, 500000)) < 1)
{
- 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;
+ Error(ERR_NETWORK_SERVER, "SDLNet_CheckSockets failed: %s",
+ SDLNet_GetError());
+ perror("SDLNet_CheckSockets");
}
if (sl < 0)
if (sl == 0)
continue;
- if (FD_ISSET(lfd, &fds))
+ /* accept incoming connections */
+ if (SDLNet_SocketReady(lfd))
{
- int newfd, slen;
+ TCPsocket newsock;
- slen = sizeof(saddr);
- newfd = accept(lfd, (struct sockaddr *)&saddr, &slen);
- if (newfd < 0)
- {
- if (errno != EINTR)
- Error(ERR_EXIT_NETWORK_SERVER, "accept() failed");
- }
- else
- {
- if (tcp != -1)
- {
- on = 1;
- setsockopt(newfd, tcp, TCP_NODELAY, (char *)&on, sizeof(int));
- }
- AddPlayer(newfd);
- }
- continue;
+ newsock = SDLNet_TCP_Accept(lfd);
+
+ if (newsock)
+ AddPlayer(newsock);
}
player = first_player;
do
{
- if (FD_ISSET(player->fd, &fds))
+ if (SDLNet_SocketReady(player->fd))
{
- r = read(player->fd, player->readbuffer + player->nread, MAX_BUFFER_SIZE - player->nread);
+ /* 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);
+
if (r <= 0)
{
if (options.verbose)
break;
}
- switch(buffer[1])
+ switch (buffer[1])
{
case OP_PLAYER_NAME:
Handle_OP_PLAYER_NAME(player, len);
Handle_OP_STOP_PLAYING(player);
break;
- case OP_MOVE_FIGURE:
- Handle_OP_MOVE_FIGURE(player);
+ case OP_MOVE_PLAYER:
+ Handle_OP_MOVE_PLAYER(player);
break;
case OP_BROADCAST_MESSAGE:
}
}
-#endif /* !MSDOS */
+#endif /* NETWORK_AVALIABLE */