📄 comm.c
字号:
if ( d->character != NULL && d->character->wait > 0 )
{
--d->character->wait;
continue;
}
read_from_buffer( d );
if ( d->incomm[0] != '\0' )
{
d->fcommand = TRUE;
stop_idling( d->character );
if ( d->connected == CON_PLAYING )
if ( d->showstr_point )
show_string( d, d->incomm );
else
interpret( d->character, d->incomm );
else
nanny( d, d->incomm );
d->incomm[0] = '\0';
}
}
/*
* Autonomous game motion.
*/
update_handler( );
/*
* Output.
*/
for ( d = descriptor_list; d != NULL; d = d_next )
{
d_next = d->next;
if ( ( d->fcommand || d->outtop > 0 ) )
{
if ( !process_output( d, TRUE ) )
{
if ( d->character != NULL )
save_char_obj( d->character );
d->outtop = 0;
close_socket( d );
}
}
}
/*
* Synchronize to a clock.
* Busy wait (blargh).
*/
now_time = last_time;
for ( ; ; )
{
int delta;
#if defined(MSDOS)
if ( kbhit( ) )
#endif
{
if ( dcon.character != NULL )
dcon.character->timer = 0;
if ( !read_from_descriptor( &dcon ) )
{
if ( dcon.character != NULL )
save_char_obj( d->character );
dcon.outtop = 0;
close_socket( &dcon );
}
#if defined(MSDOS)
break;
#endif
}
gettimeofday( &now_time, NULL );
delta = ( now_time.tv_sec - last_time.tv_sec ) * 1000 * 1000
+ ( now_time.tv_usec - last_time.tv_usec );
if ( delta >= 1000000 / PULSE_PER_SECOND )
break;
}
last_time = now_time;
current_time = (time_t) last_time.tv_sec;
}
return;
}
#endif
#if defined(unix)
void game_loop_unix( int control )
{
static struct timeval null_time;
struct timeval last_time;
#ifndef WIN32s
signal( SIGPIPE, SIG_IGN );
#endif
gettimeofday( &last_time, NULL );
current_time = (time_t) last_time.tv_sec;
/* Main loop */
while ( !merc_down )
{
fd_set in_set;
fd_set out_set;
fd_set exc_set;
DESCRIPTOR_DATA *d;
int maxdesc;
#if defined(MALLOC_DEBUG)
if ( malloc_verify( ) != 1 )
abort( );
#endif
/*
* Poll all active descriptors.
*/
FD_ZERO( &in_set );
FD_ZERO( &out_set );
FD_ZERO( &exc_set );
FD_SET( control, &in_set );
maxdesc = control;
for ( d = descriptor_list; d; d = d->next )
{
maxdesc = UMAX( maxdesc, d->descriptor );
FD_SET( d->descriptor, &in_set );
FD_SET( d->descriptor, &out_set );
FD_SET( d->descriptor, &exc_set );
}
if ( select( maxdesc+1, &in_set, &out_set, &exc_set, &null_time ) < 0 )
{
perror( "Game_loop: select: poll" );
exit( 1 );
}
/*
* New connection?
*/
if ( FD_ISSET( control, &in_set ) )
new_descriptor( control );
/*
* Kick out the freaky folks.
*/
for ( d = descriptor_list; d != NULL; d = d_next )
{
d_next = d->next;
if ( FD_ISSET( d->descriptor, &exc_set ) )
{
FD_CLR( d->descriptor, &in_set );
FD_CLR( d->descriptor, &out_set );
if ( d->character )
save_char_obj( d->character );
d->outtop = 0;
close_socket( d );
}
}
/*
* Process input.
*/
for ( d = descriptor_list; d != NULL; d = d_next )
{
d_next = d->next;
d->fcommand = FALSE;
if ( FD_ISSET( d->descriptor, &in_set ) )
{
if ( d->character != NULL )
d->character->timer = 0;
if ( !read_from_descriptor( d ) )
{
FD_CLR( d->descriptor, &out_set );
if ( d->character != NULL )
save_char_obj( d->character );
d->outtop = 0;
close_socket( d );
continue;
}
}
if ( d->character != NULL && d->character->wait > 0 )
{
--d->character->wait;
continue;
}
read_from_buffer( d );
if ( d->incomm[0] != '\0' )
{
d->fcommand = TRUE;
stop_idling( d->character );
if ( d->connected == CON_PLAYING )
if ( d->showstr_point )
show_string( d, d->incomm );
else
interpret( d->character, d->incomm );
else
nanny( d, d->incomm );
d->incomm[0] = '\0';
}
}
/*
* Autonomous game motion.
*/
update_handler( );
/*
* Output.
*/
for ( d = descriptor_list; d != NULL; d = d_next )
{
d_next = d->next;
if ( ( d->fcommand || d->outtop > 0 )
&& FD_ISSET(d->descriptor, &out_set) )
{
if ( !process_output( d, TRUE ) )
{
if ( d->character != NULL )
save_char_obj( d->character );
d->outtop = 0;
close_socket( d );
}
}
}
/*
* Synchronize to a clock.
* Sleep( last_time + 1/PULSE_PER_SECOND - now ).
* Careful here of signed versus unsigned arithmetic.
*/
{
struct timeval now_time;
long secDelta;
long usecDelta;
gettimeofday( &now_time, NULL );
usecDelta = ((int) last_time.tv_usec) - ((int) now_time.tv_usec)
+ 1000000 / PULSE_PER_SECOND;
secDelta = ((int) last_time.tv_sec ) - ((int) now_time.tv_sec );
while ( usecDelta < 0 )
{
usecDelta += 1000000;
secDelta -= 1;
}
while ( usecDelta >= 1000000 )
{
usecDelta -= 1000000;
secDelta += 1;
}
if ( secDelta > 0 || ( secDelta == 0 && usecDelta > 0 ) )
{
struct timeval stall_time;
stall_time.tv_usec = usecDelta;
stall_time.tv_sec = secDelta;
if ( select( 0, NULL, NULL, NULL, &stall_time ) < 0 )
{
perror( "Game_loop: select: stall" );
exit( 1 );
}
}
}
gettimeofday( &last_time, NULL );
current_time = (time_t) last_time.tv_sec;
}
return;
}
#endif
#if defined(unix)
void new_descriptor( int control )
{
static DESCRIPTOR_DATA d_zero;
char buf[MAX_STRING_LENGTH];
DESCRIPTOR_DATA *dnew;
BAN_DATA *pban;
struct sockaddr_in sock;
struct hostent *from;
int desc;
int size;
size = sizeof(sock);
getsockname( control, (struct sockaddr *) &sock, &size );
if ( ( desc = accept( control, (struct sockaddr *) &sock, &size) ) < 0 )
{
perror( "New_descriptor: accept" );
return;
}
#if !defined(FNDELAY)
#define FNDELAY O_NDELAY
#endif
#ifndef WIN32s
if ( fcntl( desc, F_SETFL, FNDELAY ) == -1 )
{
perror( "New_descriptor: fcntl: FNDELAY" );
return;
}
#endif
/*
* Cons a new descriptor.
*/
if ( descriptor_free == NULL )
{
dnew = alloc_perm( sizeof(*dnew) );
}
else
{
dnew = descriptor_free;
descriptor_free = descriptor_free->next;
}
*dnew = d_zero;
dnew->descriptor = desc;
dnew->connected = CON_GET_NAME;
dnew->showstr_head = NULL;
dnew->showstr_point = NULL;
dnew->outsize = 2000;
dnew->outbuf = alloc_mem( dnew->outsize );
size = sizeof(sock);
if ( getpeername( desc, (struct sockaddr *) &sock, &size ) < 0 )
{
perror( "New_descriptor: getpeername" );
dnew->host = str_dup( "(unknown)" );
}
else
{
/*
* Would be nice to use inet_ntoa here but it takes a struct arg,
* which ain't very compatible between gcc and system libraries.
*/
int addr;
addr = ntohl( sock.sin_addr.s_addr );
sprintf( buf, "%d.%d.%d.%d",
( addr >> 24 ) & 0xFF, ( addr >> 16 ) & 0xFF,
( addr >> 8 ) & 0xFF, ( addr ) & 0xFF
);
sprintf( log_buf, "Sock.sinaddr: %s", buf );
log_string( log_buf );
from = gethostbyaddr( (char *) &sock.sin_addr,
sizeof(sock.sin_addr), AF_INET );
dnew->host = str_dup( from ? from->h_name : buf );
}
/*
* Swiftest: I added the following to ban sites. I don't
* endorse banning of sites, but Copper has few descriptors now
* and some people from certain sites keep abusing access by
* using automated 'autodialers' and leaving connections hanging.
*
* Furey: added suffix check by request of Nickel of HiddenWorlds.
*/
for ( pban = ban_list; pban != NULL; pban = pban->next )
{
if ( str_suffix( pban->name, dnew->host ) )
{
write_to_descriptor( desc,
"Your site has been banned from this Mud.\n\r", 0 );
close( desc );
free_string( dnew->host );
free_mem( dnew->outbuf, dnew->outsize );
dnew->next = descriptor_free;
descriptor_free = dnew;
return;
}
}
/*
* Init descriptor data.
*/
dnew->next = descriptor_list;
descriptor_list = dnew;
/*
* Send the greeting.
*/
{
extern char * help_greeting;
if ( help_greeting[0] == '.' )
write_to_buffer( dnew, help_greeting+1, 0 );
else
write_to_buffer( dnew, help_greeting , 0 );
}
return;
}
#endif
void close_socket( DESCRIPTOR_DATA *dclose )
{
CHAR_DATA *ch;
if ( dclose->outtop > 0 )
process_output( dclose, FALSE );
if ( dclose->snoop_by != NULL )
{
write_to_buffer( dclose->snoop_by,
"Your victim has left the game.\n\r", 0 );
}
{
DESCRIPTOR_DATA *d;
for ( d = descriptor_list; d != NULL; d = d->next )
{
if ( d->snoop_by == dclose )
d->snoop_by = NULL;
}
}
if ( ( ch = dclose->character ) != NULL )
{
sprintf( log_buf, "Closing link to %s.", ch->name );
log_string( log_buf );
if ( dclose->connected == CON_PLAYING )
{
act( "$n has lost $s link.", ch, NULL, NULL, TO_ROOM );
ch->desc = NULL;
}
else
{
free_char( dclose->character );
}
}
if ( d_next == dclose )
d_next = d_next->next;
if ( dclose == descriptor_list )
{
descriptor_list = descriptor_list->next;
}
else
{
DESCRIPTOR_DATA *d;
for ( d = descriptor_list; d && d->next != dclose; d = d->next )
;
if ( d != NULL )
d->next = dclose->next;
else
bug( "Close_socket: dclose not found.", 0 );
}
close( dclose->descriptor );
free_string( dclose->host );
dclose->next = descriptor_free;
descriptor_free = dclose;
#if defined(MSDOS) || defined(macintosh)
exit(1);
#endif
return;
}
bool read_from_descriptor( DESCRIPTOR_DATA *d )
{
int iStart;
/* Hold horses if pending command already. */
if ( d->incomm[0] != '\0' )
return TRUE;
/* Check for overflow. */
iStart = strlen(d->inbuf);
if ( iStart >= sizeof(d->inbuf) - 10 )
{
sprintf( log_buf, "%s input overflow!", d->host );
log_string( log_buf );
write_to_descriptor( d->descriptor,
"\n\r*** PUT A LID ON IT!!! ***\n\r", 0 );
return FALSE;
}
/* Snarf input. */
#if defined(macintosh)
for ( ; ; )
{
int c;
c = getc( stdin );
if ( c == '\0' || c == EOF )
break;
putc( c, stdout );
if ( c == '\r' )
putc( '\n', stdout );
d->inbuf[iStart++] = c;
if ( iStart > sizeof(d->inbuf) - 10 )
break;
}
#endif
#if defined(MSDOS) || defined(unix)
for ( ; ; )
{
int nRead;
nRead = read( d->descriptor, d->inbuf + iStart,
sizeof(d->inbuf) - 10 - iStart );
if ( nRead > 0 )
{
iStart += nRead;
if ( d->inbuf[iStart-1] == '\n' || d->inbuf[iStart-1] == '\r' )
break;
}
else if ( nRead == 0 )
{
log_string( "EOF encountered on read." );
return FALSE;
}
else if ( errno == EWOULDBLOCK )
break;
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -