Arachno331
11-14-2007, 12:43 AM
After trying to run my game the following error is logged:
Tue Nov 13 23:33:51 2007 [?:90.195.66.251:4122] Socket connection timed out in Do_get_socket_string.
So here is the code for socket.c, please help. :)
/*
* socket.c - routines to handle all socket matters for Phantasia
*/
#include "include.h"
extern void *Do_start_thread(void *c);
extern server_hook;
extern randData;
/************************************************************************
/
/ FUNCTION NAME: Do_initialize_socket(struct server_t *server)
/
/ FUNCTION: To initialize the program's socket
/
/ AUTHOR: Brian Kelly, 4/12/99
/
/ ARGUMENTS:
/ struct server_t *s - address of the server's main data strcture
/
/ RETURN VALUE:
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
/ - strip non-printing characters (unless Wizard)
/ - echo, if desired
/ - redraw the screen if CH_REDRAW is entered
/ - read in only 'mx - 1' characters or less characters
/ - nul-terminate string, and throw away newline
/
/ 'mx' is assumed to be at least 2.
/
*************************************************************************/
int Do_init_server_socket()
{
struct sockaddr_in bind_address;
char error_msg[SZ_ERROR_MESSAGE];
int the_socket, error, on=1;
/* create a socket */
errno = 0;
if ((the_socket=socket(AF_INET, SOCK_STREAM, 0)) == -1) {
sprintf(error_msg,
"[0.0.0.0:?] Socket creation failed in Do_init_server_socket: %s\n",
strerror(errno));
Do_log_error(error_msg);
exit(SOCKET_CREATE_ERROR);
}
error = setsockopt(the_socket, SOL_SOCKET, SO_REUSEADDR,
(char *) &on, sizeof(on));
if (error != 0) {
sprintf(error_msg, "[0.0.0.0:?] setsockopt failed with error code of %d in Do_init_server_socket.\n", error);
Do_log_error(error_msg);
exit(SOCKET_CREATE_ERROR);
}
/* set up the bind address */
bind_address.sin_family = AF_INET;
bind_address.sin_addr.s_addr = INADDR_ANY;
bind_address.sin_port = PHANTASIA_PORT;
/* bind to that socket */
error = bind(the_socket, (struct sockaddr *) &bind_address,
sizeof(bind_address));
if (error != 0) {
sprintf(error_msg, "[0.0.0.0:?] bind to socket failed with error code of %d in Do_init_server_socket.\n", error);
Do_log_error(error_msg);
exit(SOCKET_BIND_ERROR);
}
/* start listening on the socket */
error = listen(the_socket, SOMAXCONN);
if (error != 0) {
sprintf(error_msg, "[0.0.0.0:?] listen command failed with error code of %d in Do_init_server_socket\n", error);
Do_log_error(error_msg);
exit(SOCKET_LISTEN_ERROR);
}
if (error = fcntl(the_socket, F_SETOWN, getpid()) < 0) {
sprintf(error_msg, "[0.0.0.0:?] fcntl F_SETOWN failed with error code of %d in Do_init_server_socket.\n", error);
Do_log_error(error_msg);
exit(SOCKET_BIND_ERROR);
}
if (error = fcntl(the_socket, F_SETFL, O_ASYNC) < 0) {
sprintf(error_msg, "[0.0.0.0:?] fcntl F_SETFL failed with error code of %d in Do_init_server_socket.\n", error);
Do_log_error(error_msg);
exit(SOCKET_BIND_ERROR);
}
return the_socket; /* no problems */
}
/************************************************************************
/
/ FUNCTION NAME: Do_accept_connections(struct server_t *s)
/
/ FUNCTION: Create new games for new connections on the socket
/
/ AUTHOR: Brian Kelly, 4/12/99
/
/ ARGUMENTS:
/ struct server_t *s - address of the server's main data strcture
/
/ RETURN VALUE: int error
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
/ - strip non-printing characters (unless Wizard)
/ - echo, if desired
/ - redraw the screen if CH_REDRAW is entered
/ - read in only 'mx - 1' characters or less characters
/ - nul-terminate string, and throw away newline
/
/ 'mx' is assumed to be at least 2.
/
*************************************************************************/
int Do_accept_connections(struct server_t *s)
{
struct game_t *game_ptr;
struct client_t *client_ptr;
pthread_attr_t thread_attr;
size_t addrlen;
char error_msg[SZ_ERROR_MESSAGE];
int theError, on=1, terms, itemp;
char gethost_buffer[16384], *string_ptr, *string_ptr_two;
struct hostent *host_info, host_buffer;
struct in_addr theNetwork;
while (Do_check_socket(s->the_socket)) {
/* on a new connection, seed the random number generator */
srandom_r (time(NULL), (struct random_data *)&randData);
/* create a structure for the thread information */
client_ptr = (struct client_t *) Do_malloc(SZ_CLIENT);
/* accept the new connection */
addrlen = sizeof(client_ptr->address);
errno = 0;
client_ptr->socket = accept(s->the_socket,
(struct sockaddr *)&client_ptr->address, &addrlen);
if (client_ptr->socket == -1) {
sprintf(error_msg,
"[0.0.0.0:%d] accept socket failed in Do_accept_connections: %s.\n",
s->realm.serverPid, strerror(errno));
Do_log_error(error_msg);
free((void *)client_ptr);
return SOCKET_ACCEPT_ERROR;
}
/* log the connection */
sprintf(error_msg, "New connection on socket %d.\n",
client_ptr->socket);
Do_log(SERVER_LOG, error_msg);
/* set the socket variables */
client_ptr->socket_up = TRUE;
client_ptr->out_buffer_size = 0;
client_ptr->in_buffer_size = 0;
client_ptr->date_connected = time(NULL);
client_ptr->run_level = SIGNING_IN;
client_ptr->machineID = 0;
client_ptr->events = NULL;
client_ptr->channel = 1;
client_ptr->timeout = 120;
client_ptr->timeoutFlag = 0;
client_ptr->broadcast = FALSE;
client_ptr->stuck = FALSE;
client_ptr->knightEnergy = 0;
client_ptr->knightQuickness = 0;
client_ptr->ageCount = 0;
client_ptr->morgothCount = 0;
client_ptr->suspended = FALSE;
client_ptr->accountLoaded = FALSE;
client_ptr->characterLoaded = FALSE;
client_ptr->characterAnnounced = FALSE;
client_ptr->muteUntil = 0;
client_ptr->tagUntil = 0;
client_ptr->hearBroadcasts = TRUE;
client_ptr->swearCount = 0;
client_ptr->battle.rounds = 0;
client_ptr->battle.timeouts = 0;
client_ptr->previousName[0] = '\0';
client_ptr->wizaccount[0] = '\0';
client_ptr->wizIP[0] = '\0';
for (terms = 0; terms < 10; terms++) {
client_ptr->chatTimes[terms] = 0;
client_ptr->chatLength[terms] = 0;
}
/* set the from and name fields */
/* determine the dns entry of this connection */
/* I've had major problems getting the reentrant fuction
working with linux as it is not standard. I hope the normal
function run in main process is okay */
host_info = NULL;
theError = 0;
/*
gethostbyaddr_r((char *)&client_ptr->address.sin_addr,
sizeof(client_ptr->address.sin_addr), AF_INET, &host_buffer,
gethost_buffer, 16384, &host_info, &theError);
*/
/*
errno = 0;
host_info = gethostbyaddr((char *)&client_ptr->address.sin_addr,
sizeof(client_ptr->address.sin_addr), AF_INET);
theError = errno;
*/
/* if we received host information */
if (host_info != NULL) {
/* copy over the hostname */
strncpy(&client_ptr->IP, host_info->h_name, SZ_FROM - 1);
client_ptr->IP[SZ_FROM - 1] = '\0';
/* determine the network address of this connection */
string_ptr = client_ptr->IP;
/* skip the first term (assume host name) */
while (*string_ptr != '\0' && *string_ptr++ != '.') {}
/* if we found a null, there is no network (local machine) */
if (*string_ptr == '\0') {
strncpy(client_ptr->network, client_ptr->IP, SZ_FROM - 1);
client_ptr->network[SZ_FROM - 1] = '\0';
client_ptr->addressResolved = FALSE;
}
else {
/* count the number or remaining terms */
terms = 1;
string_ptr_two = string_ptr;
while (*string_ptr_two != '\0') {
if (*string_ptr_two++ == '.')
++terms;
}
/* remove terms until we find one without numbers or hex or
we have only two terms left */
string_ptr_two = string_ptr;
while (*string_ptr != '\0' || terms > 2) {
if (isxdigit(*string_ptr)) {
++string_ptr;
}
else if (*string_ptr == '.') {
string_ptr_two = ++string_ptr;
}
else {
break;
}
}
/* put this shortened hostname into place */
strncpy(client_ptr->network, string_ptr_two, SZ_FROM - 1);
client_ptr->network[SZ_FROM - 1];
client_ptr->addressResolved = TRUE;
}
}
else {
/* use the IP address */
string_ptr = (char *) inet_ntoa(client_ptr->address.sin_addr);
strncpy(client_ptr->IP, string_ptr, SZ_FROM - 1);
client_ptr->IP[SZ_FROM - 1] = '\0';
/* get the class C network address */
theNetwork.s_addr = client_ptr->address.sin_addr.s_addr &
0x00FFFFFF;
client_ptr->addressResolved = FALSE;
string_ptr = (char *) inet_ntoa(theNetwork);
strncpy(client_ptr->network, string_ptr, SZ_FROM - 1);
client_ptr->network[SZ_FROM - 1] = '\0';
/* stop logging this an an error - too common */
/*
sprintf(error_msg,
"[%s:?] gethostbyaddress returned error %d in Do_accept_connections.\n",
client_ptr->IP, theError);
Do_log_error(error_msg);
*/
}
sprintf(error_msg, "Connection, IP=%s, Network=%s.\n", client_ptr->IP, client_ptr->network);
Do_log(DEBUG_LOG, error_msg);
/* create a new game object */
game_ptr = (struct game_t *) Do_malloc(SZ_GAME);
/* set up the game variables */
game_ptr->cleanup_thread = FALSE;
game_ptr->virtual = FALSE;
game_ptr->hearAllChannels = HEAR_SELF;
game_ptr->chatFilter = TRUE;
game_ptr->sendEvents = FALSE;
game_ptr->the_socket = client_ptr->socket;
game_ptr->description = NULL;
game_ptr->it_combat = NULL;
game_ptr->events_in = NULL;
game_ptr->account[0] = '\0';
strcpy(game_ptr->IP, client_ptr->IP);
strcpy(game_ptr->network, client_ptr->network);
game_ptr->machineID = 0;
/* initialize the event queue locks */
Do_init_mutex(&game_ptr->events_in_lock);
/* lock the game list */
Do_lock_mutex(&s->realm.realm_lock);
/* put the temp game into the list of games */
game_ptr->next_game = s->realm.games;
s->realm.games = game_ptr;
/* unlock the game list */
Do_unlock_mutex(&s->realm.realm_lock);
/* init the pthread_att strcture */
theError = pthread_attr_init(&thread_attr);
if (theError) {
sprintf(error_msg, "[0.0.0.0:%d] init of pthread_attr_t failed with error code of %d in Do_accept_connections.\n", s->realm.serverPid, theError);
Do_log_error(error_msg);
free((void *)client_ptr);
return PTHREAD_ATTR_ERROR;
}
/*
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
pthread_attr_setstacksize(&thread_attr, 0xfffffff);
*/
/* set up all information to be passed to the thread */
client_ptr->realm = &s->realm;
client_ptr->game = game_ptr;
/* create the new thread */
theError = pthread_create(&game_ptr->the_thread, NULL,
Do_start_thread, (void *)client_ptr);
if (theError) {
sprintf(error_msg, "[0.0.0.0:%d] thread creation failed with an error code of %d in Do_accept_connections.\n", s->realm.serverPid, theError);
Do_log_error(error_msg);
free((void *)client_ptr);
return PTHREAD_CREATE_ERROR;
}
++s->num_games;
}
return 0;
}
/************************************************************************
/
/ FUNCTION NAME: Do_check_socket(int the_socket)
/
/ FUNCTION: Checks for data waiting on the socket
/
/ AUTHOR: Brian Kelly, 4/23/99
/
/ ARGUMENTS:
/ int the_socket - the socket to check for data
/
/ RETURN VALUE:
/ bool - true if there is data waiting on the socket
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
int Do_check_socket(int the_socket)
{
fd_set rmask;
static struct timeval timeout = { 0, 0 }; /* no timeout */
char error_msg[SZ_ERROR_MESSAGE];
int error;
/* set rmask to check our socket */
FD_ZERO(&rmask);
FD_SET(the_socket, &rmask);
/* check for connections to be accepted */
error = select(the_socket + 1, &rmask, 0, 0, &timeout);
if (error < 0) {
sprintf(error_msg, "[0.0.0.0:?] select on socket failed with error code of %d in Do_check_socket\n", error);
Do_log_error(error_msg);
exit(SOCKET_SELECT_ERROR);
}
/* if select found no matches, return */
if (error == 0) {
return FALSE;
}
/* if our socket flag is not set, something is wrong */
if (!FD_ISSET(the_socket, &rmask)) {
sprintf(error_msg, "[0.0.0.0:?] select returned %d, but socket flag is off in Do_check_socket.\n", error);
Do_log_error(error_msg);
exit (SOCKET_SELECT_ERROR);
}
return TRUE;
}
/************************************************************************
/
/ FUNCTION NAME: Do_send_buffer(int the_socket)
/
/ FUNCTION: Send data over the socket to the player
/
/ AUTHOR: Brian Kelly, 4/23/99
/
/ ARGUMENTS:
/ int the_socket - the socket to send the information on
/ size_t the_size - the number of byest to send
/ void *the_data - a pointer to the data to be sent
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
Do_send_buffer(struct client_t *c)
{
/*
char error_msg[SZ_ERROR_MESSAGE];
*/
char error_msg[2048];
int bytes_sent;
if (c->socket_up && c->out_buffer_size > 0) {
/* send off the data */
errno = 0;
c->out_buffer[c->out_buffer_size] = '\0';
#ifdef SEND_DEBUG
sprintf(error_msg, "[%s] sending %d bytes\n", c->connection_id,
c->out_buffer_size);
Do_log(DEBUG_LOG, error_msg);
#endif
#ifdef SEND_PACKET_DEBUG
sprintf(error_msg, "[%s] (%s)\n", c->connection_id, c->out_buffer);
Do_log(DEBUG_LOG, error_msg);
#endif
bytes_sent = send(c->socket, c->out_buffer, c->out_buffer_size, 0);
if (bytes_sent != c->out_buffer_size) {
sprintf(error_msg,
"[%s] send on socket sent %d out of %d bytes in Do_send_buffer: %s.\n",
c->connection_id, bytes_sent, c->out_buffer_size, strerror(errno));
Do_log_error(error_msg);
c->socket_up = FALSE;
sprintf(error_msg, "[%s] Error on socket while sending.\n",
c->connection_id);
Do_log(CONNECTION_LOG, error_msg);
}
c->out_buffer_size = 0;
}
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_send_out(struct client_t *c, void *the_data, size_t the_size)
/
/ FUNCTION: Send data over the socket to the player
/
/ AUTHOR: Brian Kelly, 5/6/99
/
/ ARGUMENTS:
/ int the_socket - the socket to send the information on
/ size_t the_size - the number of byest to send
/ void *the_data - a pointer to the data to be sent
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
Do_send_out(struct client_t *c, void *the_data, size_t the_size)
{
char error_msg[SZ_ERROR_MESSAGE];
char string_buffer[SZ_LINE], string_buffer2[SZ_LINE];
if (c->socket_up) {
if (the_size > SZ_OUT_BUFFER) {
sprintf(error_msg,
"[%s] buffer_out overflow with %d bytes in Do_send_out.\n",
c->connection_id, the_size);
Do_log_error(error_msg);
Do_send_error(c, error_msg);
c->socket_up = FALSE;
return;
}
if (the_size + c->out_buffer_size > SZ_OUT_BUFFER) {
Do_send_buffer(c);
if (the_size + c->out_buffer_size > SZ_OUT_BUFFER) {
return;
}
}
#ifdef SEND_QUEUE_DEBUG
memcpy(string_buffer, the_data, the_size);
/* remove the "\n" */
string_buffer[the_size - 1] = '\0';
sprintf(string_buffer2, "[%s] Queued (%s)\n", c->connection_id,
string_buffer);
Do_log(DEBUG_LOG, string_buffer2);
#endif
memcpy(&c->out_buffer[c->out_buffer_size], the_data, the_size);
c->out_buffer_size += the_size;
}
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_send_string(struct client_t *c, char *theMessage)
/
/ FUNCTION: Send data over the socket to the player
/
/ AUTHOR: Brian Kelly, 8/11/99
/
/ ARGUMENTS:
/ int the_socket - the socket to send the information on
/ size_t the_size - the number of byest to send
/ void *the_data - a pointer to the data to be sent
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
Do_send_string(struct client_t *c, char *theMessage)
{
int theSize;
/* determine the string size */
theSize = strlen(theMessage);
/* send the data */
Do_send_out(c, theMessage, theSize);
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_send_double(struct client_t *c, double theDouble)
/
/ FUNCTION: Send data over the socket to the player
/
/ AUTHOR: Brian Kelly, 8/13/99
/
/ ARGUMENTS:
/ int the_socket - the socket to send the information on
/ size_t the_size - the number of byest to send
/ void *the_data - a pointer to the data to be sent
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
Do_send_double(struct client_t *c, double theDouble)
{
char tmpDouble[SZ_NUMBER];
/* determine the string size */
sprintf(tmpDouble, "%0.lf\n", theDouble);
/* send the data */
Do_send_string(c, tmpDouble);
return;
}
Tue Nov 13 23:33:51 2007 [?:90.195.66.251:4122] Socket connection timed out in Do_get_socket_string.
So here is the code for socket.c, please help. :)
/*
* socket.c - routines to handle all socket matters for Phantasia
*/
#include "include.h"
extern void *Do_start_thread(void *c);
extern server_hook;
extern randData;
/************************************************************************
/
/ FUNCTION NAME: Do_initialize_socket(struct server_t *server)
/
/ FUNCTION: To initialize the program's socket
/
/ AUTHOR: Brian Kelly, 4/12/99
/
/ ARGUMENTS:
/ struct server_t *s - address of the server's main data strcture
/
/ RETURN VALUE:
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
/ - strip non-printing characters (unless Wizard)
/ - echo, if desired
/ - redraw the screen if CH_REDRAW is entered
/ - read in only 'mx - 1' characters or less characters
/ - nul-terminate string, and throw away newline
/
/ 'mx' is assumed to be at least 2.
/
*************************************************************************/
int Do_init_server_socket()
{
struct sockaddr_in bind_address;
char error_msg[SZ_ERROR_MESSAGE];
int the_socket, error, on=1;
/* create a socket */
errno = 0;
if ((the_socket=socket(AF_INET, SOCK_STREAM, 0)) == -1) {
sprintf(error_msg,
"[0.0.0.0:?] Socket creation failed in Do_init_server_socket: %s\n",
strerror(errno));
Do_log_error(error_msg);
exit(SOCKET_CREATE_ERROR);
}
error = setsockopt(the_socket, SOL_SOCKET, SO_REUSEADDR,
(char *) &on, sizeof(on));
if (error != 0) {
sprintf(error_msg, "[0.0.0.0:?] setsockopt failed with error code of %d in Do_init_server_socket.\n", error);
Do_log_error(error_msg);
exit(SOCKET_CREATE_ERROR);
}
/* set up the bind address */
bind_address.sin_family = AF_INET;
bind_address.sin_addr.s_addr = INADDR_ANY;
bind_address.sin_port = PHANTASIA_PORT;
/* bind to that socket */
error = bind(the_socket, (struct sockaddr *) &bind_address,
sizeof(bind_address));
if (error != 0) {
sprintf(error_msg, "[0.0.0.0:?] bind to socket failed with error code of %d in Do_init_server_socket.\n", error);
Do_log_error(error_msg);
exit(SOCKET_BIND_ERROR);
}
/* start listening on the socket */
error = listen(the_socket, SOMAXCONN);
if (error != 0) {
sprintf(error_msg, "[0.0.0.0:?] listen command failed with error code of %d in Do_init_server_socket\n", error);
Do_log_error(error_msg);
exit(SOCKET_LISTEN_ERROR);
}
if (error = fcntl(the_socket, F_SETOWN, getpid()) < 0) {
sprintf(error_msg, "[0.0.0.0:?] fcntl F_SETOWN failed with error code of %d in Do_init_server_socket.\n", error);
Do_log_error(error_msg);
exit(SOCKET_BIND_ERROR);
}
if (error = fcntl(the_socket, F_SETFL, O_ASYNC) < 0) {
sprintf(error_msg, "[0.0.0.0:?] fcntl F_SETFL failed with error code of %d in Do_init_server_socket.\n", error);
Do_log_error(error_msg);
exit(SOCKET_BIND_ERROR);
}
return the_socket; /* no problems */
}
/************************************************************************
/
/ FUNCTION NAME: Do_accept_connections(struct server_t *s)
/
/ FUNCTION: Create new games for new connections on the socket
/
/ AUTHOR: Brian Kelly, 4/12/99
/
/ ARGUMENTS:
/ struct server_t *s - address of the server's main data strcture
/
/ RETURN VALUE: int error
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
/ - strip non-printing characters (unless Wizard)
/ - echo, if desired
/ - redraw the screen if CH_REDRAW is entered
/ - read in only 'mx - 1' characters or less characters
/ - nul-terminate string, and throw away newline
/
/ 'mx' is assumed to be at least 2.
/
*************************************************************************/
int Do_accept_connections(struct server_t *s)
{
struct game_t *game_ptr;
struct client_t *client_ptr;
pthread_attr_t thread_attr;
size_t addrlen;
char error_msg[SZ_ERROR_MESSAGE];
int theError, on=1, terms, itemp;
char gethost_buffer[16384], *string_ptr, *string_ptr_two;
struct hostent *host_info, host_buffer;
struct in_addr theNetwork;
while (Do_check_socket(s->the_socket)) {
/* on a new connection, seed the random number generator */
srandom_r (time(NULL), (struct random_data *)&randData);
/* create a structure for the thread information */
client_ptr = (struct client_t *) Do_malloc(SZ_CLIENT);
/* accept the new connection */
addrlen = sizeof(client_ptr->address);
errno = 0;
client_ptr->socket = accept(s->the_socket,
(struct sockaddr *)&client_ptr->address, &addrlen);
if (client_ptr->socket == -1) {
sprintf(error_msg,
"[0.0.0.0:%d] accept socket failed in Do_accept_connections: %s.\n",
s->realm.serverPid, strerror(errno));
Do_log_error(error_msg);
free((void *)client_ptr);
return SOCKET_ACCEPT_ERROR;
}
/* log the connection */
sprintf(error_msg, "New connection on socket %d.\n",
client_ptr->socket);
Do_log(SERVER_LOG, error_msg);
/* set the socket variables */
client_ptr->socket_up = TRUE;
client_ptr->out_buffer_size = 0;
client_ptr->in_buffer_size = 0;
client_ptr->date_connected = time(NULL);
client_ptr->run_level = SIGNING_IN;
client_ptr->machineID = 0;
client_ptr->events = NULL;
client_ptr->channel = 1;
client_ptr->timeout = 120;
client_ptr->timeoutFlag = 0;
client_ptr->broadcast = FALSE;
client_ptr->stuck = FALSE;
client_ptr->knightEnergy = 0;
client_ptr->knightQuickness = 0;
client_ptr->ageCount = 0;
client_ptr->morgothCount = 0;
client_ptr->suspended = FALSE;
client_ptr->accountLoaded = FALSE;
client_ptr->characterLoaded = FALSE;
client_ptr->characterAnnounced = FALSE;
client_ptr->muteUntil = 0;
client_ptr->tagUntil = 0;
client_ptr->hearBroadcasts = TRUE;
client_ptr->swearCount = 0;
client_ptr->battle.rounds = 0;
client_ptr->battle.timeouts = 0;
client_ptr->previousName[0] = '\0';
client_ptr->wizaccount[0] = '\0';
client_ptr->wizIP[0] = '\0';
for (terms = 0; terms < 10; terms++) {
client_ptr->chatTimes[terms] = 0;
client_ptr->chatLength[terms] = 0;
}
/* set the from and name fields */
/* determine the dns entry of this connection */
/* I've had major problems getting the reentrant fuction
working with linux as it is not standard. I hope the normal
function run in main process is okay */
host_info = NULL;
theError = 0;
/*
gethostbyaddr_r((char *)&client_ptr->address.sin_addr,
sizeof(client_ptr->address.sin_addr), AF_INET, &host_buffer,
gethost_buffer, 16384, &host_info, &theError);
*/
/*
errno = 0;
host_info = gethostbyaddr((char *)&client_ptr->address.sin_addr,
sizeof(client_ptr->address.sin_addr), AF_INET);
theError = errno;
*/
/* if we received host information */
if (host_info != NULL) {
/* copy over the hostname */
strncpy(&client_ptr->IP, host_info->h_name, SZ_FROM - 1);
client_ptr->IP[SZ_FROM - 1] = '\0';
/* determine the network address of this connection */
string_ptr = client_ptr->IP;
/* skip the first term (assume host name) */
while (*string_ptr != '\0' && *string_ptr++ != '.') {}
/* if we found a null, there is no network (local machine) */
if (*string_ptr == '\0') {
strncpy(client_ptr->network, client_ptr->IP, SZ_FROM - 1);
client_ptr->network[SZ_FROM - 1] = '\0';
client_ptr->addressResolved = FALSE;
}
else {
/* count the number or remaining terms */
terms = 1;
string_ptr_two = string_ptr;
while (*string_ptr_two != '\0') {
if (*string_ptr_two++ == '.')
++terms;
}
/* remove terms until we find one without numbers or hex or
we have only two terms left */
string_ptr_two = string_ptr;
while (*string_ptr != '\0' || terms > 2) {
if (isxdigit(*string_ptr)) {
++string_ptr;
}
else if (*string_ptr == '.') {
string_ptr_two = ++string_ptr;
}
else {
break;
}
}
/* put this shortened hostname into place */
strncpy(client_ptr->network, string_ptr_two, SZ_FROM - 1);
client_ptr->network[SZ_FROM - 1];
client_ptr->addressResolved = TRUE;
}
}
else {
/* use the IP address */
string_ptr = (char *) inet_ntoa(client_ptr->address.sin_addr);
strncpy(client_ptr->IP, string_ptr, SZ_FROM - 1);
client_ptr->IP[SZ_FROM - 1] = '\0';
/* get the class C network address */
theNetwork.s_addr = client_ptr->address.sin_addr.s_addr &
0x00FFFFFF;
client_ptr->addressResolved = FALSE;
string_ptr = (char *) inet_ntoa(theNetwork);
strncpy(client_ptr->network, string_ptr, SZ_FROM - 1);
client_ptr->network[SZ_FROM - 1] = '\0';
/* stop logging this an an error - too common */
/*
sprintf(error_msg,
"[%s:?] gethostbyaddress returned error %d in Do_accept_connections.\n",
client_ptr->IP, theError);
Do_log_error(error_msg);
*/
}
sprintf(error_msg, "Connection, IP=%s, Network=%s.\n", client_ptr->IP, client_ptr->network);
Do_log(DEBUG_LOG, error_msg);
/* create a new game object */
game_ptr = (struct game_t *) Do_malloc(SZ_GAME);
/* set up the game variables */
game_ptr->cleanup_thread = FALSE;
game_ptr->virtual = FALSE;
game_ptr->hearAllChannels = HEAR_SELF;
game_ptr->chatFilter = TRUE;
game_ptr->sendEvents = FALSE;
game_ptr->the_socket = client_ptr->socket;
game_ptr->description = NULL;
game_ptr->it_combat = NULL;
game_ptr->events_in = NULL;
game_ptr->account[0] = '\0';
strcpy(game_ptr->IP, client_ptr->IP);
strcpy(game_ptr->network, client_ptr->network);
game_ptr->machineID = 0;
/* initialize the event queue locks */
Do_init_mutex(&game_ptr->events_in_lock);
/* lock the game list */
Do_lock_mutex(&s->realm.realm_lock);
/* put the temp game into the list of games */
game_ptr->next_game = s->realm.games;
s->realm.games = game_ptr;
/* unlock the game list */
Do_unlock_mutex(&s->realm.realm_lock);
/* init the pthread_att strcture */
theError = pthread_attr_init(&thread_attr);
if (theError) {
sprintf(error_msg, "[0.0.0.0:%d] init of pthread_attr_t failed with error code of %d in Do_accept_connections.\n", s->realm.serverPid, theError);
Do_log_error(error_msg);
free((void *)client_ptr);
return PTHREAD_ATTR_ERROR;
}
/*
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
pthread_attr_setstacksize(&thread_attr, 0xfffffff);
*/
/* set up all information to be passed to the thread */
client_ptr->realm = &s->realm;
client_ptr->game = game_ptr;
/* create the new thread */
theError = pthread_create(&game_ptr->the_thread, NULL,
Do_start_thread, (void *)client_ptr);
if (theError) {
sprintf(error_msg, "[0.0.0.0:%d] thread creation failed with an error code of %d in Do_accept_connections.\n", s->realm.serverPid, theError);
Do_log_error(error_msg);
free((void *)client_ptr);
return PTHREAD_CREATE_ERROR;
}
++s->num_games;
}
return 0;
}
/************************************************************************
/
/ FUNCTION NAME: Do_check_socket(int the_socket)
/
/ FUNCTION: Checks for data waiting on the socket
/
/ AUTHOR: Brian Kelly, 4/23/99
/
/ ARGUMENTS:
/ int the_socket - the socket to check for data
/
/ RETURN VALUE:
/ bool - true if there is data waiting on the socket
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
int Do_check_socket(int the_socket)
{
fd_set rmask;
static struct timeval timeout = { 0, 0 }; /* no timeout */
char error_msg[SZ_ERROR_MESSAGE];
int error;
/* set rmask to check our socket */
FD_ZERO(&rmask);
FD_SET(the_socket, &rmask);
/* check for connections to be accepted */
error = select(the_socket + 1, &rmask, 0, 0, &timeout);
if (error < 0) {
sprintf(error_msg, "[0.0.0.0:?] select on socket failed with error code of %d in Do_check_socket\n", error);
Do_log_error(error_msg);
exit(SOCKET_SELECT_ERROR);
}
/* if select found no matches, return */
if (error == 0) {
return FALSE;
}
/* if our socket flag is not set, something is wrong */
if (!FD_ISSET(the_socket, &rmask)) {
sprintf(error_msg, "[0.0.0.0:?] select returned %d, but socket flag is off in Do_check_socket.\n", error);
Do_log_error(error_msg);
exit (SOCKET_SELECT_ERROR);
}
return TRUE;
}
/************************************************************************
/
/ FUNCTION NAME: Do_send_buffer(int the_socket)
/
/ FUNCTION: Send data over the socket to the player
/
/ AUTHOR: Brian Kelly, 4/23/99
/
/ ARGUMENTS:
/ int the_socket - the socket to send the information on
/ size_t the_size - the number of byest to send
/ void *the_data - a pointer to the data to be sent
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
Do_send_buffer(struct client_t *c)
{
/*
char error_msg[SZ_ERROR_MESSAGE];
*/
char error_msg[2048];
int bytes_sent;
if (c->socket_up && c->out_buffer_size > 0) {
/* send off the data */
errno = 0;
c->out_buffer[c->out_buffer_size] = '\0';
#ifdef SEND_DEBUG
sprintf(error_msg, "[%s] sending %d bytes\n", c->connection_id,
c->out_buffer_size);
Do_log(DEBUG_LOG, error_msg);
#endif
#ifdef SEND_PACKET_DEBUG
sprintf(error_msg, "[%s] (%s)\n", c->connection_id, c->out_buffer);
Do_log(DEBUG_LOG, error_msg);
#endif
bytes_sent = send(c->socket, c->out_buffer, c->out_buffer_size, 0);
if (bytes_sent != c->out_buffer_size) {
sprintf(error_msg,
"[%s] send on socket sent %d out of %d bytes in Do_send_buffer: %s.\n",
c->connection_id, bytes_sent, c->out_buffer_size, strerror(errno));
Do_log_error(error_msg);
c->socket_up = FALSE;
sprintf(error_msg, "[%s] Error on socket while sending.\n",
c->connection_id);
Do_log(CONNECTION_LOG, error_msg);
}
c->out_buffer_size = 0;
}
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_send_out(struct client_t *c, void *the_data, size_t the_size)
/
/ FUNCTION: Send data over the socket to the player
/
/ AUTHOR: Brian Kelly, 5/6/99
/
/ ARGUMENTS:
/ int the_socket - the socket to send the information on
/ size_t the_size - the number of byest to send
/ void *the_data - a pointer to the data to be sent
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
Do_send_out(struct client_t *c, void *the_data, size_t the_size)
{
char error_msg[SZ_ERROR_MESSAGE];
char string_buffer[SZ_LINE], string_buffer2[SZ_LINE];
if (c->socket_up) {
if (the_size > SZ_OUT_BUFFER) {
sprintf(error_msg,
"[%s] buffer_out overflow with %d bytes in Do_send_out.\n",
c->connection_id, the_size);
Do_log_error(error_msg);
Do_send_error(c, error_msg);
c->socket_up = FALSE;
return;
}
if (the_size + c->out_buffer_size > SZ_OUT_BUFFER) {
Do_send_buffer(c);
if (the_size + c->out_buffer_size > SZ_OUT_BUFFER) {
return;
}
}
#ifdef SEND_QUEUE_DEBUG
memcpy(string_buffer, the_data, the_size);
/* remove the "\n" */
string_buffer[the_size - 1] = '\0';
sprintf(string_buffer2, "[%s] Queued (%s)\n", c->connection_id,
string_buffer);
Do_log(DEBUG_LOG, string_buffer2);
#endif
memcpy(&c->out_buffer[c->out_buffer_size], the_data, the_size);
c->out_buffer_size += the_size;
}
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_send_string(struct client_t *c, char *theMessage)
/
/ FUNCTION: Send data over the socket to the player
/
/ AUTHOR: Brian Kelly, 8/11/99
/
/ ARGUMENTS:
/ int the_socket - the socket to send the information on
/ size_t the_size - the number of byest to send
/ void *the_data - a pointer to the data to be sent
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
Do_send_string(struct client_t *c, char *theMessage)
{
int theSize;
/* determine the string size */
theSize = strlen(theMessage);
/* send the data */
Do_send_out(c, theMessage, theSize);
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_send_double(struct client_t *c, double theDouble)
/
/ FUNCTION: Send data over the socket to the player
/
/ AUTHOR: Brian Kelly, 8/13/99
/
/ ARGUMENTS:
/ int the_socket - the socket to send the information on
/ size_t the_size - the number of byest to send
/ void *the_data - a pointer to the data to be sent
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
Do_send_double(struct client_t *c, double theDouble)
{
char tmpDouble[SZ_NUMBER];
/* determine the string size */
sprintf(tmpDouble, "%0.lf\n", theDouble);
/* send the data */
Do_send_string(c, tmpDouble);
return;
}