blob: 163d8ccb45b95f9776ac6e80074d1d9097f6fbe5 [file] [log] [blame]
/*
* Copyright 2016 The Emscripten Authors. All rights reserved.
* Emscripten is available under two separate licenses, the MIT license and the
* University of Illinois/NCSA Open Source License. Both these licenses can be
* found in the LICENSE file.
*/
/*
* Compile with:
*
* gcc -Wall `sdl-config --cflags` sdl2_net_server.c -o sdl2_net_server `sdl-config --libs` -lSDL_net
*
* or
*
* emcc -Wall sdl2_net_server.c -s USE_SDL_NET=2 -s USE_SDL=2 -o sdl2_net_server.js
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#include "SDL_net.h"
#define MAX_SOCKETS 128
#define MAX_CLIENTS MAX_SOCKETS - 1
typedef struct {
TCPsocket clientSocket[MAX_CLIENTS];
SDLNet_SocketSet socketSet;
TCPsocket sd; /* Socket descriptor, Client socket descriptor */
} state_t;
state_t state;
void finish() { // untested
printf("Shutting down...\n");
SDLNet_TCP_Close(state.sd);
for (int loop = 0; loop < MAX_CLIENTS; loop++)
{
if (state.clientSocket[loop] != NULL)
{
SDLNet_TCP_Close(state.clientSocket[loop]);
state.clientSocket[loop] = NULL;
}
}
SDLNet_Quit();
#ifdef __EMSCRIPTEN__
emscripten_force_exit(0);
#else
exit(0);
#endif
}
void main_loop() {
char buffer[512];
IPaddress *remoteIP;
/* Check the sd if there is a pending connection.
* If there is one, accept that, and open a new socket for communicating */
SDLNet_CheckSockets(state.socketSet, 20);
int serverSocketActivity = SDLNet_SocketReady(state.sd);
if (serverSocketActivity)
{
printf("new server socket activity!\n");
TCPsocket csd = SDLNet_TCP_Accept(state.sd);
/* Now we can communicate with the client using csd socket
* sd will remain opened waiting other connections */
/* Get the remote address */
if ((remoteIP = SDLNet_TCP_GetPeerAddress(csd)))
{
/* Print the address, converting in the host format */
printf("Host connected: %x %d\n", SDLNet_Read32(&remoteIP->host), SDLNet_Read16(&remoteIP->port));
} else {
fprintf(stderr, "SDLNet_TCP_GetPeerAddress: %s\n", SDLNet_GetError());
}
for (int loop = 0; loop < MAX_CLIENTS; loop++)
{
if (state.clientSocket[loop] == NULL)
{
state.clientSocket[loop] = csd;
SDLNet_TCP_AddSocket(state.socketSet, state.clientSocket[loop]);
break;
}
}
}
for (int clientNumber = 0; clientNumber < MAX_CLIENTS; clientNumber++)
{
int clientSocketActivity = SDLNet_SocketReady(state.clientSocket[clientNumber]);
if (clientSocketActivity != 0)
{
int recvLen = SDLNet_TCP_Recv(state.clientSocket[clientNumber], buffer, 512);
if (recvLen > 0)
{
assert(buffer[recvLen-1] == '\0');
printf("Client %d says: %s\n", clientNumber, buffer);
if (SDLNet_TCP_Send(state.clientSocket[clientNumber], buffer, recvLen) < recvLen) {
printf("Failed to echo message %s\n", buffer);
} else {
printf("Echoed back %d bytes\n", recvLen);
}
if(strcmp(buffer, "exit") == 0) /* Terminate this connection */
{
printf("Terminate connection\n");
SDLNet_TCP_Close(state.clientSocket[clientNumber]);
state.clientSocket[clientNumber] = NULL;
}
if(strcmp(buffer, "quit") == 0) /* Quit the program */
{
printf("Quit program\n");
finish();
}
} else {
printf("Closing client socket\n");
SDLNet_TCP_Close(state.clientSocket[clientNumber]);
state.clientSocket[clientNumber] = NULL;
}
}
}
}
int main(int argc, char **argv)
{
IPaddress ip;
if (SDLNet_Init() < 0)
{
fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE);
}
/* Resolving the host using NULL make network interface to listen */
if (SDLNet_ResolveHost(&ip, INADDR_ANY, SOCKK) < 0)
{
fprintf(stderr, "SDLNet_ResolveHost: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE);
}
state.socketSet = SDLNet_AllocSocketSet(MAX_SOCKETS);
for (int loop = 0; loop < MAX_CLIENTS; loop++)
{
state.clientSocket[loop] = NULL;
}
/* Open a connection with the IP provided (listen on the host's port) */
if (!(state.sd = SDLNet_TCP_Open(&ip)))
{
fprintf(stderr, "SDLNet_TCP_Open: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE);
}
SDLNet_TCP_AddSocket(state.socketSet, state.sd);
/* Wait for a connection, send data and term */
#ifdef __EMSCRIPTEN__
emscripten_set_main_loop(main_loop, 60, 0);
#else
while (1) main_loop();
#endif
return EXIT_SUCCESS;
}