All pastes #624292 Raw Edit

Server

public cpp v1 · immutable
·published 2007-07-18 05:10 UTC
rendered paste body
//Copyright (C) 2007 Ryan Houdek////This library is free software; you can redistribute it and/or//modify it under the terms of the GNU Lesser General Public//License as published by the Free Software Foundation; either//version 2.1 of the License, or (at your option) any later version.////This library is distributed in the hope that it will be useful,//but WITHOUT ANY WARRANTY; without even the implied warranty of//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU//Lesser General Public License for more details.////You should have received a copy of the GNU Lesser General Public//License along with this library; if not, write to the Free Software//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA#include <string.h>#include <stdarg.h>#include <stdlib.h>#ifndef WIN32#include <unistd.h>#endif#include <SDL/SDL.h>#include <SDL/SDL_net.h>#include "tcputil.h"unsigned char *Server;long ServerSize=0;char *mformat(char *format,...){	va_list ap;	Uint32 len=0;	static char *str=NULL;	char *p, *s;	char c;	int d;	unsigned int u;	if(str)	{		free(str);		str=NULL;	}	if(!format)		return(NULL);	va_start(ap,format);	for(p=format; *p; p++)	{		switch(*p)		{			case 's': // string				s=va_arg(ap, char*);				str=(char*)realloc(str,((len+strlen(s)+4)/4)*4);				sprintf(str+len,"%s",s);				break;			case 'c': // char				c=(char)va_arg(ap, int);				str=(char*)realloc(str,len+4);				sprintf(str+len,"%c",c);				break;			case 'd': // int				d=va_arg(ap, int);				str=(char*)realloc(str,((len+64)/4)*4);				sprintf(str+len,"%d",d);				break;			case 'u': // unsigned int				u=va_arg(ap, unsigned int);				str=(char*)realloc(str,((len+64)/4)*4);				sprintf(str+len,"%u",u);				break;		}		// set len to the new string length		if(str)			len=strlen(str);		else			len=0;	}	va_end(ap);	return(str);}typedef struct {	TCPsocket sock;	char *name;	void StartClient();	void EndClient();	float x;	float y;	float vely;	float velx;	float angle;	char jstate;	int dir;	int tmp[32];	int id;} Client;int idnum=0;void Client::StartClient(){		jstate		=	0;		vely 		=	0.0f;		velx 		=	0.0f;		angle		=	0.0f;		x			=	50.0f;		y			=	50.0f;		id=idnum;		idnum++;		putMsg(sock,mformat("ssd","ID"," ",id));		printf("hmmm\n");}void Client::EndClient(){}int running=1;Client *clients=NULL;int num_clients=0;TCPsocket server;#ifdef WIN32#define strcasecmp _stricmp#define strncasecmp _strnicmpchar *strsep(char **stringp, const char *delim){	char *p;		if(!stringp)		return(NULL);	p=*stringp;	while(**stringp && !strchr(delim,**stringp))		(*stringp)++;	if(**stringp)	{		**stringp='\0';		(*stringp)++;	}	else		*stringp=NULL;	return(p);}#endifvoid send_all(char *buf);int find_client_name(char *name);// this is a simplistic printf-like function the format only takes a string of// chars that represent datatypes.// it mallocs space and prints into that buffer.// it uses a static pointer so that the user doesn't have to free the buffer// terminate the nick at "bad" characters...void fix_nick(char *s){	unsigned int i;	if((i=strspn(s,"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ|_=+.,:;/\\?!@#$%^&*()~`"))!=strlen(s))		s[i]='\0';}// test for nice name uniqueness among already connected usersint unique_nick(char *s){	return(find_client_name(s)==-1);}// add a client into our array of clientsClient *add_client(TCPsocket sock, char *name){	fix_nick(name);	if(!strlen(name))	{		putMsg(sock,"Invalid Nickname...bye bye!");		SDLNet_TCP_Close(sock);		return(NULL);	}	if(!unique_nick(name))	{		putMsg(sock,"Duplicate Nickname...bye bye!");		SDLNet_TCP_Close(sock);		return(NULL);	}	clients=(Client*)realloc(clients, (num_clients+1)*sizeof(Client));	clients[num_clients].name=name;	clients[num_clients].sock=sock;	num_clients++;	// server side info	printf("--> %s\n",name);	// inform all clients, including the new one, of the joined user	send_all(mformat("ss","--> ",name));	return(&clients[num_clients-1]);}// find a client in our array of clients by it's socket.// the socket is always uniqueint find_client(TCPsocket sock){	int i;	for(i=0;i<num_clients;i++)		if(clients[i].sock==sock)			return(i);	return(-1);}// find a client in our array of clients by it's socket.// the name is always uniqueint find_client_name(char *name){	int i;	for(i=0;i<num_clients;i++)		if(!strcasecmp(clients[i].name,name))			return(i);	return(-1);}// remove a client from our array of clientsvoid remove_client(int i){	char *name=clients[i].name;	int client_id = clients[i].id;	if(i<0 && i>=num_clients)		return;		// close the old socket, even if it's dead...	SDLNet_TCP_Close(clients[i].sock);		num_clients--;	if(num_clients>i)		memmove(&clients[i], &clients[i+1], (num_clients-i)*sizeof(Client));	clients=(Client*)realloc(clients, num_clients*sizeof(Client));	// server side info	printf("<-- %s\n",name);	// inform all clients, excluding the old one, of the disconnected user	send_all(mformat("ssd","QUIT"," ",client_id));	if(name)		free(name);}// create a socket set that has the server socket and all the client socketsSDLNet_SocketSet create_sockset(){	static SDLNet_SocketSet set=NULL;	int i;	if(set)		SDLNet_FreeSocketSet(set);	set=SDLNet_AllocSocketSet(num_clients+1);	if(!set) {		printf("SDLNet_AllocSocketSet: %s\n", SDLNet_GetError());		exit(1); //most of the time this is a major error, but do what you want.	}	SDLNet_TCP_AddSocket(set,server);	for(i=0;i<num_clients;i++)		SDLNet_TCP_AddSocket(set,clients[i].sock);	return(set);}// send a buffer to all clientsvoid send_all(char *buf){	int cindex;	if(!buf || !num_clients)		return;	cindex=0;	while(cindex<num_clients)	{		// putMsg is in tcputil.h, it sends a buffer over a socket		// with error checking		if(putMsg(clients[cindex].sock,buf))			cindex++;		else			remove_client(cindex);	}}void do_command(char *msg, Client *client){	char *command,*p;	int len;	if(!msg || !strlen(msg) || !client)		return;	len=strlen(msg);	p=msg;	command=strsep(&p," \t");	// /NICK : change the clients name	if(!strcasecmp(command,"NICK"))	{		if(p && strlen(p))		{			char *old_name=client->name;						fix_nick(p);			if(!strlen(p))			{				putMsg(client->sock,"--- Invalid Nickname!");				return;			}			if(!unique_nick(p))			{				putMsg(client->sock,"--- Duplicate Nickname!");				return;			}			client->name=strdup(p);			send_all(mformat("ssss","--- ",old_name," --> ",p));			free(old_name);		}		else			putMsg(client->sock,"--- /NICK nickname");		return;	}	if(!strcasecmp(command,"GET"))	{		char tmp[256];		sprintf(tmp, "SIZE %i", ServerSize);		putMsg(client->sock, tmp);		client->dir = 0;		return;	}	if(!strcasecmp(command,"START"))	{		if(client->dir == 0)			putMsg(client->sock, "START");		if(client->dir > ServerSize)		{			putMsg(client->sock,"STOP");			return;		}		char tmp[16];		sprintf(tmp,"%d",Server[client->dir]);		//printf("%c",Server[client->dir]);		putMsg(client->sock,tmp);		client->dir++;		return;	}}#undef mainint main(int argc, char **argv){	IPaddress ip;	TCPsocket sock;	SDLNet_SocketSet set;	char *message=NULL,*host;	Uint32 ipaddr;	Uint16 port;			// initialize SDL	if(SDL_Init(0)==-1)	{		printf("SDL_Init: %s\n",SDL_GetError());		exit(1);	}	// initialize SDL_net	if(SDLNet_Init()==-1)	{		printf("SDLNet_Init: %s\n",SDLNet_GetError());		SDL_Quit();		exit(2);	}	// get the port from the commandline	port=5505;	// Resolve the argument into an IPaddress type	if(SDLNet_ResolveHost(&ip,NULL,port)==-1)	{		printf("SDLNet_ResolveHost: %s\n",SDLNet_GetError());		SDLNet_Quit();		SDL_Quit();		exit(3);	}	// perform a byte endianess correction for the next printf	ipaddr=SDL_SwapBE32(ip.host);	// output the IP address nicely	printf("IP Address : %d.%d.%d.%d\n",			ipaddr>>24,			(ipaddr>>16)&0xff,			(ipaddr>>8)&0xff,			ipaddr&0xff);	// resolve the hostname for the IPaddress	host=(char*)SDLNet_ResolveIP(&ip);	// print out the hostname we got	if(host)		printf("Hostname   : %s\n",host);	else		printf("Hostname   : N/A\n");	// output the port number	printf("Port       : %d\n",port);	// open the server socket	server=SDLNet_TCP_Open(&ip);	if(!server)	{		printf("SDLNet_TCP_Open: %s\n",SDLNet_GetError());		SDLNet_Quit();		SDL_Quit();		exit(4);	}	  FILE * pFile;  	long size;  	pFile = fopen ("Game","rb");  	if (pFile==NULL) perror ("Error opening file");  	else  	{  	  fseek (pFile, 0, SEEK_END);  	  size=ftell (pFile);  	  ServerSize = size;  	  rewind(pFile);  	  Server = (unsigned char*)malloc(size);  	  long result = fread ( Server, 1, size, pFile );  	  if (result != size) {fputs ("Reading error",stderr); exit (3);}  	  fclose (pFile);  	  printf ("Size of myfile.txt: %ld bytes.\n",size);  	}	while(1)	{		int numready,i;		set=create_sockset();		numready=SDLNet_CheckSockets(set, (Uint32)-1);		if(numready==-1)		{			printf("SDLNet_CheckSockets: %s\n",SDLNet_GetError());			break;		}		if(!numready)			continue;		if(SDLNet_SocketReady(server))		{			numready--;			//printf("Connection...\n");			sock=SDLNet_TCP_Accept(server);			if(sock)			{				char *name=NULL;				//printf("Accepted...\n");				if(getMsg(sock, &name))				{					Client *client;					client=add_client(sock,name);					if(client)					{						client->StartClient();						do_command("WHO",client);					}				}				else					SDLNet_TCP_Close(sock);			}		}		for(i=0; numready && i<num_clients; i++)		{			if(SDLNet_SocketReady(clients[i].sock))			{				if(getMsg(clients[i].sock, &message))				{					char *str;										numready--;					//printf("<%s> %s\n",clients[i].name,message);					// interpret commands					if(message[0]=='/' && strlen(message)>1)					{						do_command(message+1,&clients[i]);					}					else // it's a regular message					{						// forward message to ALL clients...						str=mformat("ssss","<",clients[i].name,"> ",message);						if(str)							send_all(str);					}					free(message);					message=NULL;				}				else					remove_client(i);			}		}	}	// shutdown SDL_net	SDLNet_Quit();	// shutdown SDL	SDL_Quit();	return(0);}