//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 #include #include #ifndef WIN32 #include #endif #include #include #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 _strnicmp char *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); } #endif void 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 users int unique_nick(char *s) { return(find_client_name(s)==-1); } // add a client into our array of clients Client *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 unique int find_client(TCPsocket sock) { int i; for(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 sockets SDLNet_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;iname; 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 main int 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 %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); }