tools/daemon/smud.cpp
author Matt Woodrow <pred@alliedmods.net>
Fri Dec 12 23:20:35 2008 -0500 (2008-12-12)
changeset 2462 6040047a9da1
parent 2444 5565c93eee91
permissions -rw-r--r--
Gamedata cleanup and security fix (bug 3351 r=dvander)
dvander@2444
     1
#include <errno.h>
pred@2129
     2
#include "smud.h"
pred@2129
     3
#include "smud_threads.h"
pred@2129
     4
pred@2129
     5
#define LISTEN_PORT 6500
pred@2129
     6
#define LISTEN_QUEUE_LENGTH 6
pred@2129
     7
pred@2129
     8
char fileNames[NUM_FILES][30] = {
pred@2129
     9
	"core.games.txt",
pred@2129
    10
	"sdktools.games.txt",
pred@2129
    11
	"sdktools.games.ep2.txt",
pred@2462
    12
	"sdktools.games.l4d.txt",
pred@2129
    13
	"sm-cstrike.games.txt",
pred@2129
    14
	"sm-tf2.games.txt",
pred@2129
    15
};
pred@2129
    16
pred@2129
    17
void *fileLocations[NUM_FILES];
pred@2129
    18
int fileLength[NUM_FILES];
pred@2129
    19
pred@2129
    20
int main(int argc, char **argv)
pred@2129
    21
{
pred@2129
    22
	ThreadPool *pool;
pred@2129
    23
	struct protoent *pProtocol;
pred@2129
    24
	struct sockaddr_in serverAddress;
pred@2129
    25
	struct sockaddr_in clientAddress;
pred@2129
    26
	int serverSocket;
pred@2129
    27
	int clientSocket;
pred@2129
    28
	int addressLen;
pred@2129
    29
	int opts;
pred@2129
    30
	int file;
pred@2129
    31
	char filename[100];
pred@2129
    32
	struct stat sbuf;
pred@2129
    33
dvander@2444
    34
#if defined DEBUG
dvander@2444
    35
	fprintf(stdout, "Loading Gamedata files into memory\n");
dvander@2444
    36
#endif
pred@2129
    37
pred@2129
    38
	for (int i=0; i<NUM_FILES; i++)
pred@2129
    39
	{
pred@2129
    40
		snprintf(filename, sizeof(filename), "./md5/%s", fileNames[i]);
pred@2129
    41
		file = open(filename, O_RDWR);
pred@2129
    42
pred@2129
    43
		if (!file)
pred@2129
    44
		{
dvander@2444
    45
			fprintf(stderr, "Could not find file: %s", filename);
pred@2129
    46
			return 1;
pred@2129
    47
		}
pred@2129
    48
pred@2129
    49
		if (stat(filename, &sbuf) == -1)
pred@2129
    50
		{
dvander@2444
    51
			fprintf(stderr, "Could not stat file: %s (error: %s)", filename, strerror(errno));
pred@2129
    52
			return 1;
pred@2129
    53
		}
pred@2129
    54
dvander@2444
    55
		if ((fileLocations[i] = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, file, 0)) == MAP_FAILED)
pred@2129
    56
		{
dvander@2444
    57
			fprintf(stderr, "Could not mmap file: %s (error: %s)", filename, strerror(errno));
pred@2129
    58
			return 1;
pred@2129
    59
		}
pred@2129
    60
pred@2129
    61
		fileLength[i] = sbuf.st_size;
pred@2129
    62
dvander@2444
    63
#if defined DEBUG
dvander@2444
    64
		fprintf(stdout, "Initialised file of %s of length %i\n", fileNames[i], fileLength[i]);
dvander@2444
    65
#endif
pred@2129
    66
	}
pred@2129
    67
dvander@2444
    68
#if defined DEBUG
dvander@2444
    69
	fprintf(stdout, "Initializing Thread Pool\n");
dvander@2444
    70
#endif
pred@2129
    71
pred@2129
    72
	pool = new ThreadPool();
pred@2129
    73
	
pred@2129
    74
	if (!pool->Start())
pred@2129
    75
	{
dvander@2444
    76
		fprintf(stderr, "Could not initialize thread pool!\n");
pred@2129
    77
		return 1;
pred@2129
    78
	}
pred@2129
    79
dvander@2444
    80
#if defined DEBUG
pred@2129
    81
	printf("Create Server Socket\n");
dvander@2444
    82
#endif
pred@2129
    83
pred@2129
    84
	memset(&serverAddress, 0, sizeof(serverAddress));
pred@2129
    85
	serverAddress.sin_family = AF_INET;
pred@2129
    86
	serverAddress.sin_addr.s_addr = INADDR_ANY;
pred@2129
    87
	serverAddress.sin_port = htons(LISTEN_PORT);
pred@2129
    88
pred@2129
    89
	pProtocol = getprotobyname("tcp");
pred@2129
    90
pred@2129
    91
	if (pProtocol == NULL)
pred@2129
    92
	{
dvander@2444
    93
		fprintf(stderr, "Could not get tcp proto: %s", strerror(errno));
pred@2129
    94
		return 1;
pred@2129
    95
	}
pred@2129
    96
pred@2129
    97
	serverSocket = socket(AF_INET, SOCK_STREAM, pProtocol->p_proto);
pred@2129
    98
pred@2129
    99
	if (serverSocket < 0) 
pred@2129
   100
	{
dvander@2444
   101
		fprintf(stderr, "Could not open socket: %s", strerror(errno));
pred@2129
   102
		return 1;
pred@2129
   103
	}
pred@2129
   104
pred@2129
   105
	opts = 1;
pred@2129
   106
	setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &opts, sizeof(opts));
pred@2129
   107
pred@2129
   108
	if (bind(serverSocket, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) < 0) 
pred@2129
   109
	{
dvander@2444
   110
		fprintf(stderr, "Could not bind socket: %s", strerror(errno));
pred@2129
   111
		return 1;
pred@2129
   112
	}
pred@2129
   113
pred@2129
   114
	if (listen(serverSocket, LISTEN_QUEUE_LENGTH) < 0) 
pred@2129
   115
	{
dvander@2444
   116
		fprintf(stderr, "Could not listen on socket: %s", strerror(errno));
pred@2129
   117
		return 1;
pred@2129
   118
	}
pred@2129
   119
dvander@2444
   120
	fprintf(stdout, "Server has started.\n");
pred@2129
   121
pred@2129
   122
	while (1)
pred@2129
   123
	{
pred@2129
   124
		addressLen = sizeof(clientAddress);
pred@2129
   125
dvander@2444
   126
		clientSocket = accept(serverSocket,
dvander@2444
   127
							  (struct sockaddr *)&clientAddress,
dvander@2444
   128
							  (socklen_t *)&addressLen);
dvander@2444
   129
		if (clientSocket < 0)
pred@2129
   130
		{
dvander@2444
   131
			fprintf(stderr, "Could not accept client: %s", strerror(errno));
pred@2129
   132
			continue;
pred@2129
   133
		}
pred@2129
   134
pred@2129
   135
		opts = fcntl(clientSocket, F_GETFL, 0);
pred@2129
   136
		if (fcntl(clientSocket, F_SETFL, opts|O_NONBLOCK) < 0)
pred@2129
   137
		{
dvander@2444
   138
			fprintf(stderr, "Could not non-block client: %s", strerror(errno));
pred@2129
   139
			closesocket(clientSocket);
pred@2129
   140
			continue;
pred@2129
   141
		}
pred@2129
   142
dvander@2444
   143
#if defined DEBUG
dvander@2444
   144
		fprintf(stdout,
dvander@2444
   145
				"Accepting connection from client (sock %d, ip %s)",
dvander@2444
   146
				clientSocket,
pred@2462
   147
				inet_ntoa(clientAddress.sin_addr));
dvander@2444
   148
#endif
pred@2129
   149
pred@2129
   150
		pool->AddConnection(clientSocket);
pred@2129
   151
	}
pred@2129
   152
pred@2129
   153
	delete pool;
pred@2129
   154
}
pred@2129
   155
pred@2129
   156
pred@2129
   157