Code:
/**************************************************************************\
* Type * Bits*byte* Possible Values *
**************************************************************************
* short * 16 *2 * -32768 to 65536 *
* unsigned short* 16 *2 * 0 to 65536 *
* * * * *
* int * 32 *4 * -2147483648 to 4294967295 *
* long * 32 *4 * -2147483648 to 4294967295 *
* unsigned int * 32 *4 * 0 to 4294967295 *
* long long * 64 *8 * -9223372036854778838 to 18446744073709551616*
**************************************************************************
* char long float volatile *
* short signed double void *
* int unsigned const *
* *
* char, signed char, unsigned char *
* int, signed int, unsigned int *
* short int, signed short int, unsigned short int *
* long int, signed long int, unsigned long int *
* float, double, long double *
\**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include "color.h"
/* Game state's, maximum allowed 65536 */
#define SAY_GOODBY 0 /* Character log off */
#define CHARACTER_LOGIN 1 /* Character login */
#define CREATE_CHARACTER 2 /* Character creation */
#define CHARACTER_LOGGED_IN 3 /* Character is logged in*/
/* Game create_state's, maximum allowed 65536 */
#define CREATE_NAME 1 /* Tells create_character to check for the character's name */
#define CREATE_PASSWORD 2 /* Tells create_character to check for the character's password */
#define VERIFY_PASSWORD 3 /* Tells create_character to verify the character's password */
#define CHOOSE_SEX 4 /* Tells create_character to check for the character's sex */
#define CHOOSE_RACE 5 /* Tells create_character to check for the character's race */
#define CHOOSE_CLASS 6 /* Tells create_character to check for the character's class */
struct descr *descr_list= NULL;
struct game_time
{
int second;
int minute;
int hour;
int day;
int month;
int year;
};
struct real_time
{
int second;
int minute;
int hour;
char day;
char month;
int year;
int ampm;
};
struct descr
{
int newfd; /* Player socket */
char char_name[11]; /* Character's name */
char char_pass[25]; /* Character's password */
short int sex; /* Character's sex */
short int char_class; /* Characters class */
short int char_race; /* Characters race */
short int state; /* Game state */
short int create_state;/* Character creation state */
struct descr *next; /* Used to create a linked list */
struct descr *list; /* Used to define the top of the linked list */
};
void fatal(const char *message) {
char error_message[100];
strcpy(error_message, "[!!] Fatal Error : ");
strncat(error_message, message, 83);
perror(error_message);
exit(EXIT_FAILURE);
}
void nonfatal(const char *message) {
char error_message[100];
strcpy(error_message, "[!!] Non Fatal Error : ");
strncat(error_message, message, 83);
perror(error_message);
}
int initialize_descr(int newfd, struct descr **p)
{
struct descr *d;
if(!(d = malloc(sizeof(struct descr))))
{
nonfatal("malloc failure initializing descr");
return 0;
}
d->newfd = newfd;
d->state = CHARACTER_LOGIN;
d->next = NULL;
d->list = descr_list;
*p = d;
if(descr_list == NULL)
{
descr_list = d;
descr_list->list = descr_list;
}
else
{
while(descr_list->next != NULL)
{
descr_list=descr_list->next;
}
descr_list->next = d;
descr_list->next->list = descr_list->list;
descr_list = descr_list->list;
}
return 1;
}
int character_login(struct descr *d)
{
int rbytes = 0;
char buffer[12];
const char er[] = "Character name must be less then, twelve characters.\r\n";
const char ln[] = "Character name or (n)ew: ";
if ((rbytes = recv(d->newfd, buffer, 12, 0)) <= 0)
{
if (rbytes == 0)
printf("Socket %d hung up\n", d->newfd);
else
nonfatal("Receiving a file descriptor");
d->state=0;
return -1;
}
else if (rbytes > 11)
{
send(d->newfd, er, sizeof er, 0);
send(d->newfd, ln, sizeof ln, 0);
return 0;
}
else
{
if(buffer == "n" || buffer == "N")
{
send(d->newfd, "By what name do you wish to be known? ", 38, 0);
d->state = CREATE_CHARACTER; /* Now we know to Create a new character */
d->create_state = CREATE_NAME; /* Here we know to check for the username */
return 1;
}
else
{/*
FILE *player = fopen(buffer,"r");
if( player ) {
d->state = ENTER_PASSWORD; Enter character password
fclose(fp);
}
else
{
send(d->newfd, "Character does not exist", 24, 0);
}*/
}
}
return 1;
}
int create_character(struct descr *d)
{
int rbytes = 0;
char buffer[27];
const char ne[] = "Character name must be less then, twelve characters.\r\n";
const char nl[] = "By what name do you wish to be known? ";
const char pe[] = "Password must be less then twenty six characters\r\n";
const char pl[] = "Enter a password for you're character: ";
const char vpe[]= "Passwords are not the same\r\n";
const char vp[] = "Please varify you're password: ";
const char se[] = "Please enter m , f or n\r\n";
const char sl[] = "Please choose you're sex, \r\n(m)ale, (f)emale, or (n)one? ";
const char race_menu[] =
"Human\r\n"
"Drow\r\n"
"Barbarian\r\n"
"\r\n"
"Highlighted races are available: ";
const char class_menu[] =
"(M)age\r\n"
"(W)arrior\r\n"
"(C)leric\r\n"
"(T)hief\r\n"
"\r\n"
"Highlighted classes are available: ";
if ((rbytes = recv(d->newfd, buffer, 27, 0)) <= 0)
{
if (rbytes == 0)
printf("Socket %d hung up\n", d->newfd);
else
nonfatal("Receiving a file descriptor, function create_character");
d->state=0;
return -1;
}
if ( d->create_state == CREATE_NAME)
{
if (rbytes > 11)
{
send(d->newfd, ne, sizeof ne, 0);
send(d->newfd, nl, sizeof nl, 0);
return 0;
}
strcpy(d->char_name, buffer);
d->create_state == CREATE_PASSWORD;
send(d->newfd, pl, sizeof pl, 0);
}
else if (d->create_state == CREATE_PASSWORD)
{
if (rbytes > 25)
{
send(d->newfd, pe, sizeof pe, 0);
send(d->newfd, pl, sizeof pl, 0);
return 0;
}
strcpy (d->char_pass, buffer);
d->create_state = VERIFY_PASSWORD;
send(d->newfd, vp, sizeof vp, 0);
}
else if (d->create_state == VERIFY_PASSWORD)
{
if (rbytes > 25 || buffer != d->char_pass)
{
send(d->newfd, vpe, sizeof vpe, 0);
send(d->newfd, pl, sizeof pl, 0);
d->create_state = CREATE_PASSWORD;
return 0;
}
strcpy(d->char_pass, buffer);
d->create_state = CHOOSE_SEX;
send(d->newfd, sl, sizeof sl, 0);
}
else if (d->create_state == CHOOSE_SEX)
{
if(buffer == "m" || buffer == "M"){d->sex = 0;}
else if(buffer == "f" || buffer == "F"){d->sex = 1;}
else if(buffer == "n" || buffer == "N"){d->sex = -1;}
else
{
send(d->newfd, de, sizeof se, 0);
send(d->newfd, sl, sizeof sl, 0);
return 0;
}
d->create_state = CHOOSE_RACE;
send(d->newfd, race_menu, sizeof race_menu, 0);
}
else if (d->create_state == CHOOSE_RACE)
{
d->create_state = CHOOSE_CLASS;
send(d->newfd, class_menu, sizeof class_menu, 0);
}
else if (d->create_state == CHOOSE_CLASS)
{
d->state = CHARACTER_LOGGED_IN;
d->state = CREATE_CHARACTER;
d->create_state = CREATE_NAME;
}
}
int main()
{
struct sockaddr_in serv;
struct sockaddr_in inco;
struct game_time rtime;
struct timeval seconds;
socklen_t inclen;
int simpleSocket;
int yes = 1;
int fdmax; /* maximum file descriptor number */
int newfd;
unsigned int heart_pulse = 0;
fd_set master; /* master file descriptor list */
fd_set read_fds; /* will be watched to see if characters become available for reading */
fd_set write_fds; /* will be watched to see if a write will not block */
fd_set except_fds; /* will be watched for exceptions. */
seconds.tv_sec = 0; /* seconds for select to wait for connections */
seconds.tv_usec = 1000; /* microseconds for select to wait for connections
* there are 1,000 microseconds in a millisecond
* there are 1,000 milliseconds in a second
* thus there are 1,000,000 Microseconds in one
* second, and there are 60 seconds in one minute */
printf("Process id #%i\n", getpid());
FD_ZERO(&master); // clear the master and temp sets
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
FD_ZERO(&except_fds);
if ((simpleSocket=socket(AF_INET, SOCK_STREAM,0)) == -1)
{
fatal("Creating simpleSocket, AF_INET SOCK_STREAM failed");
}
fcntl(simpleSocket, F_SETFL, O_NONBLOCK);
setsockopt(simpleSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
/*struct sockaddr_in
{
short sin_family; must be AF_INET
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8]; Not used, must be zero
};
struct in_addr { int s_addr; }; */
serv.sin_family = AF_INET;
serv.sin_addr.s_addr = INADDR_ANY;
serv.sin_port = htons(2000);
if (bind(simpleSocket,(struct sockaddr *)&serv,sizeof(serv)) == -1)
{
close(simpleSocket);
fatal("Binding simpleSocket, AF_INET SOCK_STREAM failed");
}
if (listen(simpleSocket, 1000) == -1)
{
close(simpleSocket);
fatal("Listening to simpleSocket, AF_INET SOCK_STREAM failed");
}
// add the listener to the master set
FD_SET(simpleSocket, &master);
// keep track of the biggest file descriptor
fdmax = simpleSocket; // so far, it's this one
for(;;)
{
struct descr *keepsake, *r;
read_fds = master;
write_fds = master;
except_fds = master;
/* Wait for connections for seconds amount of time and set the
specific file descriptor for each connection */
if (select(fdmax+1, &read_fds, &write_fds, &except_fds, &seconds) == -1)
nonfatal("Select failed");
/* handle new connections */
if (FD_ISSET(simpleSocket, &read_fds))
{
/* Accept the next pending connection from simpleSocket */
newfd = accept(simpleSocket, (struct sockaddr *)&inco, &inclen);
if(newfd == -1)
nonfatal("Accepting a file descriptor");
else
{
struct descr *init;
FD_SET(newfd, &master); /* add to master set */
if (newfd > fdmax) /* keep track of the max */
fdmax = newfd;
const char name_prompt[] = "Character name or (n)ew: ";
const char error_prompt[]= "Unable to proceed please report this problem.";
if(initialize_descr(newfd, &init) == 0)
{
send(newfd, error_prompt, sizeof error_prompt, 0);
FD_CLR(newfd, &master);
close(newfd);
}
else
{
send(init->newfd, name_prompt, sizeof name_prompt, 0);
printf("New connection: on socket: %d,\r\n", init->newfd);
printf(" sin_addr: %s\r\n", inet_ntoa(inco.sin_addr));
}
}
} /* END FD_ISSET(simpleSocket, &read_fds) */
heart_pulse++;
if (heart_pulse == 15000) /* Longest int type unsigned long long int 18446744073709551616 */
{
if(rtime.second > -1)
rtime.second++;
if(rtime.second > 0x29) /* 41 */
{
rtime.second = 0x0; /* 0 */
rtime.minute++;
if(rtime.minute > 0x25) /* 37 */
{
rtime.minute = 0x0; /* 0 */
rtime.hour++;
if(rtime.hour > 0x15) /* 21 */
{
rtime.hour = 0x0; /* 0 */
rtime.day++;
if(rtime.day > 0x1b) /* 27 */
{
rtime.day = 0x1; /* 1 */
rtime.month++;
if(rtime.month > 0xA) /* 10 */
{
rtime.month = 0x1; /* 1 */
rtime.year++;
if(rtime.year > 0x17cf87f) /* 24967295 */
{
rtime.second = -1;
rtime.minute = -1;
rtime.hour = -1;
rtime.day = -1;
rtime.month = -1;
rtime.year = -1; /* Apocolypse */
}
}
}
}
}
}
int j;
const char tick[] = "tick.";
for(j = 0; j <= fdmax; j++)
{
/* send to everyone! */
if (FD_ISSET(j, &master))
{
send(j, tick, sizeof tick, 0);
}
}
heart_pulse = 0;
}
keepsake = descr_list;
while(keepsake != NULL)
{
if(FD_ISSET(keepsake->newfd, &read_fds))
{
if(keepsake->state == CHARACTER_LOGIN) /* Character login */
character_login(keepsake);
else if(keepsake->state==CREATE_CHARACTER) /* Character creation */
create_character(keepsake);
}
keepsake = keepsake->next;
}
keepsake = descr_list;
while(descr_list != NULL)
{
r = descr_list->next;
if(descr_list->state == SAY_GOODBY)
{
close(descr_list->newfd);
FD_CLR(descr_list->newfd, &master);
free(descr_list);
}
descr_list = r;
}
descr_list = keepsake;
}/* END for(;;).*/
close(simpleSocket);
exit(EXIT_SUCCESS);
}